开发者

Rails 3 Nested Form not being created

The models I'm working with look like this:

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

My form looks like the following:

<%= 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>
      <% e开发者_JAVA百科nd %>
    </div>
  </div>
</div>
<div id="createComplex" align="center">
  <%= f.submit :value=>'Submit' %>
</div>
<% end %>

And my controller looks like:

def new_complex_assertion
  @complex_assertion = ComplexAssertion.new
end

When I load the page, I only the ComplexAssertion portion of the form and get nothing back for the ExpressionGroups or the Expressions. It's as if there isn't anything available. But, if you see my controller, I did a ComplexAssertion.new which I though would create the dependent objects automagically; I assume I'm incorrect?

I'm debugging through RubyMine and when I evaluate the ComplexAssertion.new, I only see 5 attributes, the five that are defined for only that object, none of the relational objects. What am I doing incorrectly?

EDIT Looks like if I do the following:

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

And change my form to use:

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

instead of eg.fields_for, it shows the forms.

This DOES NOT give me the correct nesting. I thought I should be able to do:

@complex_assertion.expression_groups.expressions.build

but it tells me that expressions is an undefined method.


Yes, you have to explicitly instantiate the associated objects. It is not done for you.

@complex_assertion.expression_groups.expressions.build

Will not work because expression_groups is an array and not an individual expression group. So, after you create the expressions_groups do the following:

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

Also, you could replace the 2nd line with the following as well to create multiple expressions

2.times do { group.expressions.build }

As for using fields_for with nested models, make your code in the form look like this:

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

I will try to explain what is going on. The :expressions_groups is telling fields_for what class of object it is going to render fields for, and the second part I added is telling fields_for where to find the object(s) to render fields for. If we are passing in an array, which we are in this case, it will automatically iterate over the array. On each iteration, it puts the current model object we are working with into a variable called object which is stored in the form builder instance returned by fields_for. So we use this to tell the second fields_for where to find the expression model objects it needed. This means eg.object points to an expression_group model object.

I hope this helps and makes sense. Also, I have not tested anything and am only pointing out what looks out of place.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜