我在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'页面中我有一个设置位置的表单。但是,我在@location实例变量的html.erb上收到'undefined method model_name for NilClass:Class'
错误。
这真的很奇怪,因为当我使用render'/ set_location'而不是redirect_to时,它工作正常。但是,我想使用redirect_to方法来防止重复记录提交。
提前感谢您提供任何帮助。
答案 0 :(得分:15)
HTTP在设计上是无状态的。如果要在请求之间共享状态(将引导重定向到另一个请求),则应使用session
哈希。像这样:
session[:hotel_id] = @hotel.id
然后您以Hotel
的方式检索/set_location
:
Hotel.find(session[:hotel_id])
答案 1 :(得分:1)
我相信你想要做的是:
@location = Location.new
。你需要在那里创建它。Rails中的实例变量通常用于在控制器和视图之间传递信息,这就是为什么在执行渲染时,您不会收到该错误。 Rails视图了解控制器的实例变量。
但是,您正在进行重定向,因此您正在调用另一个不知道@location
是什么的控制器。
答案 2 :(得分:0)
我相信Nobita在这里的回答是最全面的,并且回答了OP的确切问题。请投票(@Ger)。
在jdoe的回答中,我期待或希望看到更多关于他/她(jdoe' s)使用"请求"的解释。在他的解释中,作为"请求"可以解释为对其他框架中的视图(或模板)的请求,因此当使用Rails读取时,此语句可能对新Rails开发人员(包括我自己)有点误导:
"变量不能在请求之间传递。我觉得作者得到了 想法:使用会话。"
从某种意义上说,当您使用" render"从控制器请求视图/模板时,确实可以传递变量。因此,如果您的控制器方法呈现视图,则该视图将了解您在该控制器中定义的@variable
。
此外,使用会话实际上不是在请求之间传递变量的唯一方法。您可以修改重定向到路由以捕获变量:
考虑(在routes.rb文件中):
match 'surveys/result(/:id)' => "surveys#result", via: [:get], as: 'surveys_result'
现在,在"调查"控制器"结果"动作方法您将拥有:id
参数。您可以将其称为params[:id]
,例如,使用此ID在数据库中查找对象。我相信,还有一种方法可以隐藏URI / URL中的:id
,以防您不希望用户在那里看到它。
@shime:关于"重复条目"的问题,我认为OP指的是在POST请求上呈现视图。想象一下,如果POST成功,那么在您已经提交该表单之后,您可能会在每次刷新页面时向数据库提交一个重复的条目(重定向方法会处理这种情况不会发生,因此是标准方式)从您的POST请求路由)和我发现的这个段落对两个实现中发生的事情有一个最明确的解释: