2011-06-02 43 views
0

我与工作的样子像这样的模式:Rails 3中嵌套表单无法创建

class ComplexAssertion < ActiveRecord::Base 
    has_many :expression_groups 
    has_many :expressions, :through => :expression_group 
    accepts_nested_attributes_for :expression_groups, :allow_destroy=>true 
end 

class ExpressionGroup < ActiveRecord::Base 
    belongs_to :complex_assertion 
    has_many :expressions 
    accepts_nested_attributes_for :expressions, :allow_destroy=>true 
end 

class Expression < ActiveRecord::Base 
    belongs_to :expression_group 
end 

我的形式如下所示:

<%= form_for(@complex_assertion) do |f| %> 
<div id="mainAssertionGroup" style="border:1px; border-style:solid; width:1000px; padding:5px"> 
    <div class="field"> 
    <%= f.label :title %>: <%= f.text_field :title, :size=>'10' %> 
    <%= f.label :description %>: <%= f.text_field :description, :size=>'25' %> 
    <%= f.label :scope %>: <%= f.text_field :scope, :size=>'1' %> 
    Test 
    Category: <%= collection_select(:complex_assertion, :assertion_category_id, AssertionCategory.all, :id, :name, {:include_blank=>"UNCATEGORIZED"}) %> 
    </div> 
    <div id="initialGroup" style="border:1px; margin-left:10px; margin-top:10px; border-style:solid; width:850px;"> 
    <div class="childGroup1" style="padding:5px;"> 
     <%= f.fields_for :expression_groups do |eg| %> 
      <%= eg.fields_for :expressions do |e| %> 
       Type: <%= e.collection_select :assertion_type_id, AssertionType.all, :id, :name %> 
       Attribute: <%= e.collection_select :attribute_name, Attribute.find_by_sql("select distinct a.name from attributes a "), :name, :name %> 
       <%= e.label :operator_type_id %> 
       : <%= e.collection_select :operator_type_id, OperatorType.all, :id, :value %> 
       Value: <%= e.text_field :value, :size=>'1' %> 
      <% end %> 
      <div id="innerOperator"> 
      <%= eg.collection_select :logical_operator_type_id, LogicalOperatorType.all, :id, :value %> 
      </div> 
     <% end %> 
    </div> 
    </div> 
</div> 
<div id="createComplex" align="center"> 
    <%= f.submit :value=>'Submit' %> 
</div> 
<% end %> 

而且我的控制器看起来像:

def new_complex_assertion 
    @complex_assertion = ComplexAssertion.new 
end 

当我加载页面时,我只有表单的ComplexAssertion部分,并且没有返回ExpressionGroups或Expres sions。就好像没有任何可用的东西。但是,如果你看到我的控制器,我做了一个ComplexAssertion.new,我虽然会自动创建依赖对象;我认为我不正确?

我正在通过RubyMine进行调试,当我计算ComplexAssertion.new时,我只看到5个属性,仅为该对象定义的五个属性,没有任何关系对象。我做错了什么?

编辑 看起来像如果我做到以下几点:

@complex_assertion = ComplexAssertion.new 
@complex_assertion.expression_groups.build 
@complex_assertion.expressions.build 

而改变我的形式使用:的

<%= f.fields_for :expressions do |e| %> 

代替eg.fields_for,它显示的形式。

这不会给我正确的嵌套。我以为我应该能够做到:

@complex_assertion.expression_groups.expressions.build 

但它告诉我,表达式是一个未定义的方法。

回答

1

是的,你必须显式实例化关联的对象。这不是为你做的。

@complex_assertion.expression_groups.expressions.build 

不会工作,因为expression_groups是一个数组而不是个别表达式组。因此,在创建后的expressions_groups做到以下几点:

@complex_assertion.expressions_groups.each do |group| 
    group.expressions.build 
end 

此外,您可以用下面以及创建多个表达式

2.times do { group.expressions.build } 

至于使用fields_for与嵌套模型替换2号线,使您的代码如下所示:

<%= f.fields_for :expression_groups, @complex_assertions.expression groups do |eg| %> 
    <%= eg.fields_for :expressions, eg.object.expressions do |e| %> 

我会尝试解释发生了什么。 :expressions_groups告诉fields_要渲染什么类的对象,而我添加的第二部分是告诉fields_for在哪里找到渲染字段的对象。如果我们传入一个数组,我们在这种情况下,它会自动遍历数组。在每次迭代中,它将我们正在使用的当前模型对象放入一个名为object的变量,该变量存储在fields_for返回的表单构建器实例中。所以我们用这个来告诉第二个fields_for找到它需要的表达式模型对象的位置。这意味着eg.object指向expression_group模型对象。

我希望这有助于并有意义。另外,我还没有测试任何东西,只是指出看起来不合适的地方。

+0

太棒了!添加完毕后:@ complex_assertion.expression_groups.each循环来实例化表达式对象,一切正常!它写入数据库并且工作得很好!这是第一步,现在我必须让它们变得有活力,但非常感谢你让我渡过了最初的障碍。 – 2011-06-02 17:09:18

+0

@QuazzMoto没问题:-)我记得不久前,我还在为自己挣扎! – brettish 2011-06-02 17:23:10