2011-08-03 64 views
0

我有一个表单,我想同时创建一个父记录和一个子记录。举一个简单的例子,让我们说一个公司与第一名员工。Rails的复杂形式

在我的控制器

我做这样的事情:

def new 
    @company = Company.new 
    @company.employees.new 
end 

,这在我看来:

<%= form_for(@company) do |form| %> 

    <div> 
     <%= form.label :name %> 
     <%= form.text_field :name %> 
    </div> 

    <%= form.fields_for :employees do |employee_form| %> 

     <div> 
      <%= employee_form.label :name %> 
      <%= employee_form.text_field :name %> 
     </div> 

    <% end %> 

<% end %> 

,并回到我的控制器再次:

def create 
    @company = Company.new(params[:company]) 
    @company.employees << Employee.new(params[:company][:employees_attributes]["0"]) 

    # save stuff 
end 

问题1:

我无法获得公司员工集合中填入的表单中创建的单个员工。当我查看参数时,我发现[:employees_attributes] [“0”]的东西。

我有什么工作,但有没有更干净的方法来做到这一点?

问题2:

如果验证未通过的员工,我得到一个通用的“员工是无效的”,而不是需要的名称验证消息。我得到我打电话保存在收集和轨道正在尽最大努力冒出一个验证错误,但有没有一种更清洁的方式来做到这一点,所以我可以得到特定于员工的错误?

在短期

如何清洁这件事使相关模型从PARAMS自动创建的,所以我得到的验证消息的一个员工。

感谢您的期待。

回答

0

1)fields_for安排子对象属性嵌套在params散列中的父对象属性中,并发送回控制器动作。要让Rails自动更新子对象,请使用accep_nested_attributes_for声明来告诉父模型接受嵌套属性。

2)每个ActiveRecord对象都有一个错误对象。循环显示错误列表并显示消息。

实现此目的的最佳方法是创建一个部分视图帮助器方法,它将为您呈现错误。然后用您对render_error_messages方法的调用来替换窗体中生成的错误消息。你有所有的代码已经在生成的表单中执行此操作。您只需将该代码重构为部分代码,创建帮助程序(应该接受一个模型名称数组作为参数,然后按照您所需的信息进行操作)。无论是为每个模型渲染一个部分,还是渲染一个将处理子对象以及父对象的部分。完全是你的电话。

3)更换新的行动来建立,而创造一个新的子对象,而不是

def new 
    @company = Company.new 
    @company.employees.new 
end 

做到这一点

def new 
    @company = Company.new 
    @company.employees.build 
end 

4)看看那些Railscasts怎么看accepts_nested_attributes工作

http://railscasts.com/episodes/196-nested-model-form-part-1

and

http://railscasts.com/episodes/197-nested-model-form-part-2

更新

那么,如何在上述信息让你在关系到你的问题。

1)我有什么作品,但有没有更干净的方法来做到这一点?

您是否按照上述第3点修正了新操作?现在你的创建动作可以看起来像这样

def create 
    @company = Company.new(params[:company]) 

    # save stuff 
end 

这更清洁,因为它已恢复到原始生成的创建操作。 你可能不认为这是一个更新,因此没有那么干净。好吧,隔离你会是对的。但考虑到你可以添加尽可能多的关系,只要你喜欢广告添加尽可能多的fields_for声明,你可以把用户 - >员工关系变成has_many(我知道你不会)。你可以做到这一切,你的创建和更新操作保持完全相同,这就是为什么它更干净。

2)有没有一种更清洁的方式来做到这一点,以便我可以得到特定于员工的错误? 鉴于我在上面第2点中的回答,您知道员工对象以及用户对象上有错误对象吗?您现在也知道,您可以循环查看错误对象以获取正确的消息吗? 所以,你可以做到这一点

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

     <ul> 
     <% @user.employee.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 

在重复自己的风险,我只想说,你应该重构你的错误信息查看代码放到一个部分,将采取任何对象作为参数,那么你可以把它叫做任何视图,从而使您可以更改所有表单的样式和功能。

希望更清楚

+0

感谢您的回应。我已经在父模型中设置了accep_nested_attributes_。我已经有了一个部分,它的作用是model.errors.full_messages.each,我得到的是“Employees is invalid”,而不是“Name不能为空”。在阅读两者之间的细微差别后,关于构建的建议很有意义,谢谢。在寻求帮助之前,我已经观看了Railscasts。不知道我留下的是什么,其他任何想法都会很棒,但不知道我能从我的结局中得到什么。再次感谢。 – blu

+0

我的确涵盖了这些要点,但也许我所说的不够清楚。我会更新我的答案,使其更清晰 – jamesc

+0

@blu - 我已更新我的答案,希望您现在可以看到如何使用我给你的信息 – jamesc