rails fields_for和嵌套属性

时间:2013-11-22 14:08:32

标签: ruby-on-rails ruby ruby-on-rails-4

我很难理解如何使用fields_for和嵌套属性。为了更好地理解它,我创建了一个repo,它不起作用。

我看了this,这没什么用。

我正在使用:

Rails 4.0.1 Ruby 2.0.0-p247

问题:

  1. 地址表格显示,为什么无法保存到数据库?
  2. 为什么不工作?

    jack = Person.create(name: 'Jack')

    jack.address.create(street: '12w 33st')

  3. 主要功能如下:

    #model
    class Person < ActiveRecord::Base
      has_one :address
      accepts_nested_attributes_for :address
    end
    
    class Address < ActiveRecord::Base
      belongs_to :person
    end
    

    查看如下:

    <%= form_for(@person) do |f| %>
      <% if @person.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@person.errors.count, "error") %> prohibited this person from being saved:</h2>
    
          <ul>
          <% @person.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
          <% end %>
          </ul>
        </div>
      <% end %>
    
      <div class="field">
        <%= f.label :name %><br>
        <%= f.text_field :name %>
      </div>
      <div class="field">
        <%= f.label :age %><br>
        <%= f.text_field :age %>
      </div>
      <div class="field">
        <%= f.label :gender %><br>
        <%= f.text_field :gender %>
      </div>
      <%= fields_for :address do |address_fields|%>
        Street:
        <%= address_fields.text_field :street%>
        Zip code:
        <%= address_fields.text_field :zip_code%>
      <% end %>  
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>
    

    nested attributes

    结论:

    1. has_one relation不支持person.address.create。这只适用于has_many
    2. fields_for的rails api,真的不太清楚。它只是缺少整个控制器部分。跟着它不会成功。

1 个答案:

答案 0 :(得分:6)

尝试:

jack = Person.create(name: 'Jack')
jack.create_address(street: '12w 33st')

如果只有一个关联地址(has_one :address),则使用create_address。如果有多个关联地址(has_many :addresses),则使用addresses.create

此外,在您的视图中,您需要f.fields_for而不是fields_for

我建议您查看嵌套模型表单的RailsCasts以了解更多信息。

其他信息(以解决以下评论)

另请注意,create将创建一个新对象并尝试将其保存在数据库中。 build将只构建新对象。在你的PeopleController中,你需要这样的东西:

def new
  @person = Person.new
  @person.build_address
end

根据您的需要,您可以确定是否希望此build在模型中的其他操作或回调中发生。但这会让你开始。

您还需要将person_params更新为

def person_params
  params.require(:person).permit(:name, :age, :gender, address_attributes: [:id, :street, :zip_code])
end