8

我在 Rails 3 中有一个表单向导。基本上,我创建了一个酒店对象,然后当所有这些都完成后,我想为该酒店创建一个位置对象。我用于创建酒店的控制器代码如下所示:

  def create
    @hotel = Hotel.new(params[:hotel])

    respond_to do |format|
      if @hotel.save
        @location = Location.new
        format.html { redirect_to '/set_location'}
      else
        format.html { render action: "new" }
      end
    end
  end

然后在“/set_location”页面中,我有一个设置位置的表单。但是,我'undefined method model_name for NilClass:Class'在 @location 实例变量的 html.erb 上遇到错误。

这真的很奇怪,因为当我使用 render '/set_location' 而不是 redirect_to 时它可以正常工作。但是,我想使用 redirect_to 方法来防止重复记录提交。

提前感谢您对此的任何帮助。

4

3 回答 3

15

HTTP 在设计上是无状态的。如果您想在请求之间共享状态(重定向导致另一个请求),您应该使用session哈希。像这样:

session[:hotel_id] = @hotel.id

然后你以这种方式检索你Hotel/set_location

Hotel.find(session[:hotel_id])
于 2012-04-11T11:13:02.457 回答
1

我相信你想做的是:

  1. 确定哪个控制器和操作响应“/set_location”请求。
  2. 在那里你会看到你错过了这条线@location = Location.new。你需要在那里创建它。

Rails 中的实例变量通常用于在控制器和视图之间传递信息,这就是为什么在执行渲染时不会出现该错误的原因。Rails 视图知道来自控制器的实例变量。

但是,您正在执行重定向,因此您正在调用另一个不知道是什么@location的控制器。

于 2012-04-11T11:21:32.840 回答
0

我相信大雄在这里的回答是最全面的,并且回答了 OP 的确切问题。请投票(@Ger)。

在 jdoe 的回答中,我预计或希望看到更多关于他/她(jdoe)在他的解释中使用“请求”的解释,因为“请求”可以解释为其他框架中对视图(或模板)的请求,所以当从 Rails 的角度阅读时,这句话可能会误导新的 Rails 开发人员(包括我自己):

“请求之间不能传递变量。我认为作者得到了这个想法:使用会话。”

从某种意义上说,当您使用“render”从控制器请求视图/模板时,确实可以传递变量。因此,如果您的控制器方法呈现一个视图,该视图将知道@variable您在该控制器中定义的内容。

此外,使用会话实际上并不是在请求之间传递变量的唯一方法。您可以修改重定向到路由以捕获变量:

考虑(在 routes.rb 文件中):

match 'surveys/result(/:id)' => "surveys#result", via: [:get], as: 'surveys_result'

现在,在“调查”控制器“结果”操作方法中,您将有一个:id参数。您可以将其称为params[:id],例如在您的数据库中查找具有此 ID 的对象。我相信,还有一种方法可以隐藏:idURI/URL,以防您不希望用户在那里看到它。

@shime:关于您的“重复条目”问题,我相信 OP 指的是在 POST 请求上呈现视图。想象一下,如果 POST 成功,那么在您提交表单后,您可能会在每次刷新页面时向数据库提交一个重复条目(重定向方法会确保不会发生这种情况,因此是标准方式从您的 POST 请求中路由),我发现这一段对两种实现都发生了什么有最清晰的解释之一:

https://gist.github.com/jcasimir/1210155#redirect

于 2018-01-02T20:23:02.450 回答