Rails 3嵌套表单未创建

时间:2011-06-02 15:13:20

标签: ruby ruby-on-rails-3 activerecord

我正在使用的模型如下所示:

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或Expressions取回任何内容。好像没有任何可用的东西。但是,如果你看到我的控制器,我做了一个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 个答案:

答案 0 :(得分: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,请使表单中的代码如下所示:

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

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

我希望这有帮助并且有意义。此外,我还没有测试任何东西,只是指出了什么看起来不合适。