Являются ли redirect_to и могут ли они быть заменяемыми? - PullRequest
40 голосов
/ 21 сентября 2011

Для кода ниже, что произойдет, если заменить redirect_to на render или vise verse?

def create
  @product = Product.new(params[:product])

  respond_to do |format|
    if @product.save
      format.html { redirect_to(@product, :notice => 'Product was successfully created.') }

    else
      format.html { render :action => "new" }
    end
  end
end

Кажется, все в порядке, заменяя одно на другое в приведенном выше коде. Есть ли место, где нужно использовать только redirect_to или render? Render делает только рендеринг вида. Redirect_to отправляет 302 запроса на сервер и текущие параметры теряются после перенаправления.

Спасибо.

Ответы [ 3 ]

112 голосов
/ 21 сентября 2011

Если вы используете render, когда пользователь обновит страницу, он снова отправит предыдущий запрос POST.Это может привести к нежелательным результатам, таким как повторная покупка и т. Д.

enter image description here

Но если вы используете redirect_to, когда пользователь обновляет страницу, он просто запрашивает эту же страницуснова.Это также называется шаблоном Post / Redirect / Get (PRG) .

enter image description here

Таким образом, место, где следует использовать redirect_to, - это когда вывыполняется HTTP-запрос POST, и вы не хотите, чтобы пользователь повторно отправлял запрос, когда он выполнен (что может вызвать дублирование элементов и другие проблемы).

В Rails, когда не удается сохранить модель,render используется для повторного отображения формы с теми же записями, которые были заполнены ранее.Это проще, потому что если вы используете перенаправление, вам придется передавать записи формы, используя параметры или сеанс.Побочным эффектом является то, что если вы обновите браузер, он попытается повторно отправить предыдущие записи формы.Это приемлемо, потому что, вероятно, он потерпит неудачу таким же образом, или, если он успешен сейчас, это было именно тем, чего пользователь должен ожидать в первую очередь.

Для более подробного объяснения о render и redirect, вы должны прочитать эту статью .

9 голосов
/ 21 сентября 2011

Когда вы перенаправляете, вы генерируете новый запрос, который попадает в метод контроллера, render просто визуализирует связанный вид.Вы используете render при создании, потому что хотите сохранить состояние объекта модели в случае сбоя сохранения, чтобы вы могли отобразить информацию о его ошибках.Если вы попытаетесь перенаправить на путь new_product, вы создадите новый объект модели и потеряете все введенные пользователем данные формы, любые ошибки и т. Д.

РЕДАКТИРОВАТЬ (с дополнительной информацией):

Пример ситуации, в которой вы ДОЛЖНЫ использовать redirect_to, - это если ваш шаблон представления использует переменные экземпляра, которые не инициализируются в методе контроллера, из которого вы перенаправляете.Таким образом, вы, вероятно, не могли вызвать render {:action => 'index'} в своем методе create, потому что шаблон индекса, вероятно, использует переменную @products, но ваша единственная инициализированная @product, так что это вызовет исключение

1 голос
/ 22 октября 2018

Вот полный список двух методов, которым я следую:

1) redirect_to выдаст код состояния HTTP 302 по умолчанию.Перенаправление 302 является временным изменением и перенаправляет пользователей и поисковые системы на нужную страницу в течение ограниченного периода времени, пока она не будет удалена.При желании вы можете указать код статуса 301 для redirect_to.Код состояния 301 используется, когда какая-либо страница была навсегда перемещена в другое место.Теперь пользователи увидят новую страницу, поскольку она заменила старую.Это изменит URL-адрес страницы при отображении в результатах поиска.

2) redirect_to выдаст новый HTTP-запрос, поскольку он перенаправляет на другое действие контроллера или URL-адрес.Вы не должны заставлять браузер совершать новый вызов, если только вам это не нужно, поэтому всегда задавайте вопросы, когда вы используете redirect_to и правильно ли это, или, возможно, визуализация будет лучше.- redirect_to приведет к пропуску любого автоматического рендеринга шаблона текущего действия.

3) рендер выдаст код состояния HTTP 200 по умолчанию (но с недопустимым объектом ActiveRecord вы можете изменить его на 422).не обрабатываемый объект).Код ответа HTTP 200 OK об успешном статусе указывает, что запрос выполнен успешно.Код состояния 422 (Unprocessable Entity) означает, что сервер понимает тип содержимого объекта запроса, и синтаксис объекта запроса является правильным, но не смог обработать содержащиеся в нем инструкции.

4) рендеринг отобразит шаблони любые переменные экземпляра, определенные в действии контроллера, будут доступны в шаблоне.Конечно, переменные экземпляра не будут доступны, если последующее действие, которое вызывает redirect_to.ВАЖНАЯ ТОЧКА: Перенаправление попадает в контроллер, а Render - нет, поэтому, если вы рендерите другой шаблон, он не будет воздействовать на действие, связанное с этим шаблоном, и поэтому эти переменные экземпляра будут недоступны!

5) С render, используйте flash.now, вместо обычной вспышки.

flash.now[:error] = "There was a problem"  
# not 
flash[:error] = "There was a problem"

6) Если вы этого не сделаете, то флэш-сообщение может не отображаться на отображаемой странице и будет отображаться на следующей посещенной странице.

7) рендер не приведет к прекращению выполнения текущего действия!redirect_to не приведет к прекращению выполнения текущего действия!Вам нужно вызвать 'return', если вам нужно обойти дальнейшее выполнение кода в действии!В приведенном ниже коде есть явный рендер в нижней части, поэтому вы должны выполнить возврат, чтобы избежать ошибки перенаправления и рендеринга при наличии обоих:

def update
  @record = Record.new(record_params)
  if @record.save
    flash[:success] = "record was successfully saved"
    redirect_to records_path
    return
  end
  flash.now[:error] = "please fix the problems in the record"
  render :edit
end

Другой вариант:

def update
  @record = Record.new(record_params)
  if @record.save
    flash[:success] = "record was successfully saved"
    redirect_to records_path
  else
    flash.now[:error] = "please fix the problems in the record"
    render :edit
  end  
end

8) Флэш-сообщение обеспечивает способ передачи временных примитивных типов (String, Array, Hash) между действиями.Все, что вы поместите во вспышку, будет подвергнуто следующему действию, а затем очищено.Это отличный способ создания уведомлений и оповещений:

class PostsController < ActionController::Base
  def create
    # save post
    flash[:notice] = "Post successfully created"
    redirect_to @post
  end

  def show
    # doesn't need to assign the flash notice to the template, that's done automatically
  end
end

show.html.erb
  <% if flash[:notice] %>
    <div class="notice"><%= flash[:notice] %></div>
  <% end %>

Поскольку во флэш-памяти могут быть как уведомления, так и предупреждения, вы можете отображать уведомления и оповещения следующим образом:

<% flash.each do |key, value| %>
  <%= content_tag :div, value, class: "flash #{key}" %>
<% end %>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...