Ruby on rails 重定向到和呈现是否可交换?

Ruby on rails 重定向到和呈现是否可交换?,ruby-on-rails,Ruby On Rails,对于下面的代码,如果用render或vise-verse替换redirect_to,会发生什么情况 def create @product = Product.new(params[:product]) respond_to do |format| if @product.save format.html { redirect_to(@product, :notice => 'Product was successfully created.') }

对于下面的代码,如果用render或vise-verse替换redirect_to,会发生什么情况

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
在上面的代码中,用一个替换另一个似乎没问题。是否有一个只需使用重定向或渲染的地方?“渲染”只渲染视图。重定向到将302请求发送到服务器,重定向后当前参数丢失


谢谢。

当您重定向时,您将生成一个新的请求,该请求将命中控制器方法,“渲染”只渲染关联的视图。在“创建”中使用“渲染”是因为希望在保存失败时保持模型对象的状态,以便可以渲染有关其错误的信息。如果您试图重定向到新的产品路径,您将创建一个新的模型对象,并丢失用户输入的所有表单数据和任何错误等

编辑(包含更多信息):


必须使用
redirect\u to
的情况的一个示例是,视图模板使用的实例变量未在重定向的控制器方法中初始化。因此,您可能无法在创建方法中调用
render{:action=>'index'}
,因为索引模板可能使用了
@products
变量,但您只初始化了
@product
,因此当用户刷新页面时,如果您使用
render
,则会导致异常,它将再次提交上一个POST请求。这可能会导致不希望的结果,如重复购买和其他

但是如果您使用的是
重定向\u to
,当用户刷新页面时,它只会再次请求相同的页面。这也称为模式

因此,应该使用
redirect\u to
的位置是在您执行HTTP POST请求时,您不希望用户在请求完成时重新提交请求(这可能会导致重复项和其他问题)

在Rails中,当模型无法保存时,
render
用于重新显示具有先前填写的相同条目的表单。这更简单,因为如果使用重定向,则必须使用参数或会话传递表单条目。副作用是,如果刷新浏览器,它将尝试重新提交以前的表单条目。这是可以接受的,因为它可能会以同样的方式失败,或者如果它现在成功了,这是用户首先应该期望的


有关
渲染
重定向
的更深入的解释,请阅读此文。

以下是我遵循的两种方法的完整列表:

1) 将_重定向到默认情况下将发出HTTP 302状态代码。302重定向是一种临时更改,它会在有限的时间内将用户和搜索引擎重定向到所需页面,直到将其删除。您可以选择指定一个301状态代码以重定向到。当任何页面永久移动到其他位置时,使用301状态代码。用户现在将看到新页面,因为它已替换旧页面。这将更改页面在搜索引擎结果中显示时的URL

2) 重定向到将发出一个新的HTTP请求,因为它被重定向到不同的控制器操作或URL。您不应该让浏览器需要重新调用,除非您真的必须这样做,所以请始终询问您何时使用redirect_to,以及它是否正确,或者渲染是否更好。 -将_重定向到将导致跳过当前操作的任何自动模板呈现

3) 默认情况下,render将发出HTTP 200状态代码(但对于无效的ActiveRecord对象,您可能希望将其更改为422不可处理实体)。HTTP 200 OK success status响应代码表示请求已成功。422(不可处理实体)状态代码表示服务器了解请求实体的内容类型,请求实体的语法正确,但无法处理包含的指令

4) render将渲染模板,并且在控制器操作中定义的任何实例变量都将在模板中可用。当然,如果将_重定向到的后续操作调用,则实例变量将不可用。要点:重定向命中控制器,而渲染不命中控制器,因此如果渲染不同的模板,它将不会命中与该模板关联的操作,因此这些实例变量将不可用

5) 使用render时,请使用flash.now,而不是普通的flash

flash.now[:error] = "There was a problem"  
# not 
flash[:error] = "There was a problem"
6) 如果没有,则flash消息可能不会显示在呈现的页面上,它将显示在访问的下一个页面上

7) 渲染不会导致当前操作停止执行!将_重定向到将不会导致当前操作停止执行!如果需要在操作中绕过代码的进一步执行,则需要调用“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) flash消息提供了一种在操作之间传递临时基元类型(字符串、数组、散列)的方法。你在闪光灯中放置的任何东西都将暴露在下一个动作中,然后被清除。这是一种很好的通知和提醒方式:

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 %>
class PostsController
由于flash中可以同时显示通知和警报,因此可以通过以下方式同时显示通知和警报:

<% flash.each do |key, value| %>
  <%= content_tag :div, value, class: "flash #{key}" %>
<% end %>


在更多地方使用渲染似乎是安全的。是否需要使用重定向到的任何地方?谢谢,谢谢。这是一个彻底的解释。我想我还没有见过比这更完美的解释,尤其是菲尼希