3

对于使用无效数据提交的 Rails 表单显示错误消息并使用无效数据重新填充表单似乎是正常功能。至少,我所有的 Active Record 托管资源都是这样工作的。

但是,我有一个不是 Active Record 的虚拟资源/模型,而是使用Railscast #219中的 Rails 3 ActiveModel 。

除了提交失败之外,一切都按我的预期工作。重新渲染的表单是空的。错误消息正常显示。

Rails 的哪个部分负责此功能,如何将其包含在基于 ActiveModel 的资源中?

澄清:

  1. 用户完成并提交包含两个值的表单。
  2. 验证失败,因为其中一个或多个值无效。
  3. 控制器重新渲染模型的“新”视图。
  4. 重新呈现的表单包含错误消息。
  5. 重新渲染的表单预先填充了两个无效数据值。

这是我不理解的第 5 步,尽管我的 Active Record 资源具有几乎相同的控制器代码和相同的视图代码,但我的 Active Model 资源并没有发生这种情况。

代码(根据要求)

控制器:

def new
  @contact = Contact.new
end

def create
  @contact = Contact.new(params[:contact])

  if @contact.valid?
    AgentMailer.contact_email(@contact).deliver
    redirect_to "/contact", notice: 'Your request was successful.' 
  else
    #TODO Figure out why data from an invalid submission does not carry over
    render action: "new"
  end
end

看法:

<%= form_for(@contact, :html => {:class => "new_contact custom"}) do |f| %>
  <% if @contact.errors.any? %>
    ...
  <% end %>

  ...

  <%= f.label :name %>
  <%= f.text_field :name, options = {placeholder: "Enter name here"} %>     

  ...
<% end %>
4

2 回答 2

1

脚手架命令创建包含您提到的错误消息的表单部分。这里没有魔法,只是一个从模型中呈现错误(如果存在)的视图。您可以使用下面的错误 ERB 代码作为如何将错误消息添加到其他视图的模板。

rails new test_project
cd test_project
rails generate scaffold users name

查看 app/views/users/_form.html.erb

 <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% @user.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
于 2013-06-10T19:45:12.317 回答
1

通过反复试验,我找到了解决方案;

为了让这点 Rails 魔法发挥作用,我的模型需要一个如下形式的初始化器:

def initialize(attributes = {})
  attributes.each do |name, value|
    send("#{name}=", value) if respond_to?("#{name}=")
  end
end

我怀疑是 ActiveModel 的 Validations 模块发挥了作用。如果有人能证实这一点并为我指出一些有用的文档,那就太好了。

更新

我相信上述方法是安全的,因为 send 方法不会绕过适当的访问器方法,并且由于respond_to检查而健壮。我仍然不确定 Rails 的哪个部分/模块在重新渲染视图时创建了一个新的模型实例。

于 2013-06-10T22:11:39.027 回答