我有一个表单供用户在他们的个人资料页面上创建一个问题(除了用户模型,还有一个问题模型,有嵌套的答案)。它从用户个人资料页面/views/users/show.html.erb提交到questions_controller.rb的创建操作。如果它没有验证,我认为Rails的默认值是呈现表单(表单中的无效信息供用户编辑)。但是,由于我是从用户个人资料页面提交问题模型的表单,因此在验证失败时不会发生预填充;用户被迫再次输入表单中的所有信息。在这种情况下,是否有办法在用户显示页面上获取表单以填写提交前输入的信息?
questions_controller
def create
@question = current_user.questions.build(params[:kestion])
if @question.save
redirect_to current_user, :notice => "Successfully created question."
else
###render :action => 'show'
redirect_to current_user
end
end
更新 我也改变了创建方法的结束
Redirect ( : back ), :notice => "something went wrong.try again"
但是我仍然无法填写表单,并且验证错误消息也没有显示,只显示闪存通知。
更新 用户控制器的show方法创建新问题(与用户一起)
def show
@user = User.find(params[:id])
@question = Question.new
3.times {@question.answers.build}
end
/views/users/show.html.erb
<%= form_for @question do |f| %>
<% if @question.errors.any? %>
<h2><%= pluralize(@question.errors.count, "error") %> prohibited this question
from being saved: </h2>
<ul>
<% @question.errors.full_messages.each do |msg| %>
<li> <%= msg %></li>
<% end %>
</ul>
<% end %>
<p>
<%= f.label :content, "Question"%>
<%= f.text_area :content, :class => 'span4', :rows => 1 %>
</p>
<p>
<%= f.label :link, "QuoraLink" %>
<%= f.text_field :link, :class => 'span4', :rows => 1 %>
</p>
<%= f.fields_for :answers do |builder| %>
<p>
<%= render 'answer_fields', :f => builder %>
</p>
<% end %>
<p><%= link_to_add_fields "Add Answer", f, :answers %></p>
<p><%= f.submit %></p>
<% end %>
answer_fields部分从问题部分呈现
<p class="fields">
<%= f.label :content, "Answer..." %>
<%= f.text_field :content, :class => 'span3', :rows => 1%>
<%= f.label :correctanswer, "Correct" %>
<%= f.check_box :correctanswer, :class => 'span1' %>
<%= link_to_remove_fields "remove answer", f %>
</p>
答案 0 :(得分:1)
首先,使用redirect_to
代替render
而不重新填充表单的原因是当您redirect_to
时,操作的控制器逻辑会运行,而使用{{ 1}}忽略了控制器逻辑。
因此,当您render
(“默认”行为)时,它会呈现render :action => 'show'
,show.html.erb
设置如下:
@question
当您@question = current_user.questions.build(params[:kestion])
时,它会使用redirect_to current_user
操作中的代码设置show.html.erb
来呈现@question
:
show
这就是为什么你得到一个新的(空白)表单,而不是预先填充的表单。
使用@question = Question.new
3.times {@question.answers.build}
真的是否重要?如果是,您需要使用redirect_to
方法进行验证。例如,您可以将show
方法重写为:
show
然后在该页面上制作表格点,例如:
def show
@user = User.find(params[:id])
if params.has_key?(:kestion)
@question = @user.questions.build(params[:kestion])
else
@question = Question.new
3.times {@question.answers.build}
end
end
(取决于您的路线设置和命名方式)。当然,到目前为止,整个事情变得非常糟糕,有点混乱,而且绝对不是Rails的做事方式。 (另一个更糟糕的选择是重定向并通过获取查询传递参数。)在我看来,你因为一个小的收益而损失很多,而且我不确定我是否真的推荐它。
答案 1 :(得分:1)
目前,在views / users / show.rb中,您可以
@question = Question.new
创建一个空的新问题。然后使用此空模型填充表单。 你可以做的是:
if session[:question]
@question = @user.questions.new(session[:question])
session[:question] = nil
@question.valid? # run validations to to populate the errors[]
else
@question = Question.new
end
现在剩下要做的就是在你的questions_controller中填充session [:question],然后重定向到:controller =&gt;“users”,:action =&gt;“show”。类似的东西:
if @question.save
redirect_to current_user, :notice => "Successfully created question."
else
session[:question] = params[:question]
redirect_to current_user
end
您可能需要另外进行序列化/反序列化以填充/使用会话[:question]。我没有尝试编译,所以我不确定。
所有这些都是必需的,因为当您重定向到用户请求的处理结束时,用户浏览器会从您的服务器获取重定向状态代码并转到另一个页面,向您发送新请求(该请求落在路径上,以及最终控制器/动作,你重定向到)。因此,一旦从请求处理返回,所有变量都将丢失。对于下一个请求,您可以从头开始。
render :action => "show"
方法(在原始脚手架中并且您注释掉了)工作,因为您没有返回给用户,而只是使用您已有的变量使用特定名称呈现模板(包括@question,调用'save'并失败,因此调用内部验证并填充错误对象。)
实际上,这提醒我你可能想要使用另一种方法。您可能希望填充所有必需的变量,而只是从该控制器渲染视图,而不是通过session []传递参数并重定向到UsersController。如下所示:
if @question.save
redirect_to current_user, :notice => "Successfully created question."
else
@user = current_user
render "users/show"
end