簡體   English   中英

如何使用accepts_nested_attributes_for?

[英]How do I use accepts_nested_attributes_for?

為簡潔起見,請編輯我的問題並更新我所做的事情:

如何為公司具有多個地址建模,並為聯系人分配一個地址,並在創建或編輯聯系人時進行分配?

我想使用嵌套屬性來在創建新聯系人時添加地址。 該地址作為其自身的模型存在,因為我可能希望該選項從現有地址下拉而不是從頭輸入。

我似乎無法正常工作。 我為nil:NilClass錯誤得到一個未定義的方法'build'

這是我的通訊錄模型:

class Contact < ActiveRecord::Base
  attr_accessible :first_name, :last_name, :title, :phone, :fax, :email, :company, 
                  :date_entered, :campaign_id, :company_name, :address_id, :address_attributes

  belongs_to :company
  belongs_to :address
  accepts_nested_attributes_for :address
end

這是我的地址模型:

class Address < ActiveRecord::Base
  attr_accessible :street1, :street2, :city, :state, :zip

  has_many :contacts
end

我想在創建新聯系人時,訪問屬於公司的其他聯系人的所有地址。 所以這是我代表公司的方式:

class Company < ActiveRecord::Base
  attr_accessible :name, :phone, :addresses

  has_many :contacts

  has_many :addresses, :through => :contacts

end

這是我嘗試在View for _form for Contact中創建一個字段的方式,以便當某人創建新的Contact時,他們將地址傳遞給Address模型並將該地址與Contact關聯:

  <% f.fields_for :address, @contact.address do |builder| %>
  <p>
    <%= builder.label :street1, "Street 1" %> </br> 
    <%= builder.text_field :street1 %>
  <p>
  <% end %>

當我嘗試編輯時,“街道1”的字段為空白。 而且我不知道如何顯示show.html.erb中的值。

最下面是我的錯誤控制台-似乎無法在地址表中創建值:

我的聯系人控制器如下:

  def new
    @contact = Contact.new
    @contact.address.build # Iundefined method `build' for nil:NilClass

    @contact.date_entered = Date.today
    @campaigns = Campaign.find(:all, :order => "name")
    if params[:campaign_id].blank? 

    else
      @campaign = Campaign.find(params[:campaign_id])
      @contact.campaign_id = @campaign.id
    end

    if params[:company_id].blank?

    else
      @company = Company.find(params[:company_id])
      @contact.company_name = @company.name
    end

  end

  def create
    @contact = Contact.new(params[:contact])
    if @contact.save
      flash[:notice] = "Successfully created contact."
      redirect_to @contact
    else
      render :action => 'new'
    end
  end

  def edit
    @contact = Contact.find(params[:id])
    @campaigns = Campaign.find(:all, :order => "name")
  end

這是我的錯誤控制台的摘要我正在發布屬性,但在地址表中未創建。

處理ContactsController#create(對於127.0.0.1在2010-05-12 21:16:17)

[POST]參數:{“ commit” =>“ Submit”,“ authenticity_token” =>“ d8 / gx0zy0Vgg6ghfcbAYL0YtGjYIUC2b1aG + dDKjuSs =”,“ contact” => {“ company_name” =>“ Allyforce”,“ title” =>“ “,” campaign_id“ =>” 2“,” address_attributes“ => {” street1“ =>” abc“},”傳真“ =>”“,”電話“ =>”“,”姓氏“ =>”“ ,“ date_entered” =>“ 2010-05-12”,“電子郵件” =>“”,“名字” =>“ abc”}}

公司負載(0.0ms)[0m [0mSELECT * FROM“ companies” WHERE(“ companies”。“ name” ='Allyforce')LIMIT 1 [0m

地址創建(16.0ms)[0m
[0; 1mINSERT INTO“ addresses”(“ city”,“ zip”,“ created_at”,“ street1”,“ updated_at”,“ street2”,“ state”)VALUES(NULL,NULL,'2010-05-13 04 :16:18',NULL,'2010-05-13 04:16:18',NULL,NULL)[0m

Contact Create(0.0ms)[0m
[0mINSERT INTO“聯系人”(“公司”,“ created_at”,“標題”,“ updated_at”,“ campaign_id”,“ address_id”,“ last_name”,“ phone”,“ fax”,“ company_id”,“ date_entered” ,“ first_name”,“ email”)VALUES(NULL,'2010-05-13 04:16:18','','2010-05-13 04:16:18',2,2,'',' ','',5,'2010-05-12','abc','')[0m

只是一個平凡的問題,如果您在聯系表中使用此地址,是否不應該使用單數形式?

 <% f.fields_for :address, @contact.address do |builder| %>
   <p>
     <%= builder.label :street1, "Street 1" %> </br> 
     <%= builder.text_field :street1 %>
   <p>
 <% end %>

在您的行動中,您還必須做

@ycontact.build_address

如果您查看源代碼,則輸入字段應該看起來像。

<輸入type =“ text” size =“ 30” name =“ contact [address_attributes] [street1]” id =“ contact_address_attributes_street1”>

我認為您的關聯也存在問題,如果您將address_id存儲在聯系人中,那么

class Contact < ActiveRecord::Base
  belongs_to :address
  accepts_nested_attributes_for :address
end

class Address < ActiveRecord::Base
  attr_accessible :street1
  has_many :contacts
end

我認為這是您的情況,因為您想為多個聯系人分配一個地址。

如果您將contact_id存儲在地址模型中,也可以進行逆操作:

class Contact < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address
end

class Address < ActiveRecord::Base
  attr_accessible :street1
  belongs_to :contact
end

在這種情況下,您不能讓用戶使用相同的地址。

更新資料

在您的用戶show.html.eb中,您可以使用

<%= @contact.address.street1 %>

在您公司的show.html.erb中,您可以顯示以下地址:

<% @company.addresses.each do |address| %>
  <%= address.street1 %>
  ...
<% end %>

在用戶編輯頁面上,表單字段應與new.html.erb相同,只是表單標簽應類似於:

<% form_for @contact do |form| %>
  <%=render :partial=>'fields' %>
<% end %>

該字段的一部分包含您所有的fied togheter,其中包括:

 <% f.fields_for :address, @contact.address do |builder| %>
   <p>
     <%= builder.label :street1, "Street 1" %> </br> 
     <%= builder.text_field :street1 %>
   <p>
 <% end %>

這應該工作。

更新2

您可以通過以下方式訪問屬於公司的所有地址:

@company.addresses

如果你有

class Company<Activerecord::Base
    has_many :contacts
    has_many :addresses, :through=>:contacts
end

關於草稿或默認地址。 您可以根據需要選擇不同的選項。 我想要一個選項,使聯系人可以從數據庫中選擇現有地址之一。 您可以在聯系表單中做一個選擇框,例如:

 <%= form.select :address_id, options_from_collection_for_select(@company.addresses, 'id', 'street1')%>

另外,在這種情況下,如果用戶選擇現有地址之一,則可以使用一些精美的javascript來添加或刪除地址表格。 在這種情況下,您必須從表單中刪除address_attributes。 我建議使用JavaScript代碼創建一個添加address_attributes並刪除(切換樣式)的鏈接。

如果每個地址僅屬於一個聯系人(例如家庭住址),則可以執行以下操作:

class Company < ActiveRecord::Base
  has_many :contacts
end

class Contact < ActiveRecord::Base
  belongs_to :company
  has_one :address
end

class Address < ActiveRecord::Base
  belongs_to :contact
end

當然,您可以僅將地址列移到Contact表中,並完全擺脫Address模型。

如果每個地址都有多個聯系人(即,地址是聯系人工作的公司設施):

class Company < ActiveRecord::Base
  has_many :contacts
end

class Contact < ActiveRecord::Base
  belongs_to :company
  belongs_to :address
end

class Address < ActiveRecord::Base
  has_many :contacts
end

您可以添加has_many :through關聯以獲取company.addresses

class Company < ActiveRecord::Base
  has_many :contacts
  has_many :addresses, :through => :contacts
end

在兩種情況下,地址組成部分(街道,城市,州等)都是地址表中的列。

問題的最后一部分實際上取決於數據的分布-如果您只有幾個地址,則可以簡單地將其放在主地址為默認地址的select元素中。 使用更多地址,您可能需要具有自動完成功能的AJAXified表單來搜索地址表。

要將新的聯系人/地址添加到表中,您可能需要查看嵌套表單。 Railscast 196是一個很好的介紹。

編輯-有關嵌套屬性的更多信息

accepts_nested_attributes_for應該與has_manyhas_one關聯一起使用,並且應該與多層嵌套一起使用。 在這種情況下,您似乎想讓一個聯系人屬於公司,而一個地址屬於聯系人。

class Company < ActiveRecord::Base
  has_many :contacts
  accepts_nested_attributes_for :contact
end

class Contact < ActiveRecord::Base
  belongs_to :company
  has_one :address # or has_many, if you prefer
end

class Address < ActiveRecord::Base
  belongs_to :contact
end

然后在視圖中使用Railscast中所述的form_forfields_for來獲取嵌套的表單元素。 如果您的表格不正常,這可能會有點棘手。 有來自ryanb很好的例子在這里涵蓋了幾種典型的情況。

由於您希望地址同時屬於公司和聯系人,因此有兩種選擇。 如果您永遠不需要多個地址(建議您不建議使用多個地址),則可以在“公司”和“聯系人”中都添加一個“ belongs_to:address”。 然后,地址將同時具有“ has_many:companies”和“ has_many:contacts”。

更好的選擇是使用多態關聯,其中地址表將具有:addressable_type和:addressable_id列以鏈接回任一模型。

class Company < ActiveRecord::Base
  attr_accessible :name, :phone, :addresses

  has_many :contacts  
  accepts_nested_attributes_for :contacts

  has_many :addresses, :as => :addressable
  accepts_nested_attributes_for :addresses

end

class Contact < ActiveRecord::Base
  attr_accessible :first_name, :last_name, :title, :phone, :fax, :email, :company, 
                  :date_entered, :campaign_id, :company_name

  belongs_to :company
  has_many :addresses, :as => :addressable
  accepts_nested_attributes_for :addresses
end

class Address < ActiveRecord::Base
  attr_accessible :street1

  belongs_to :addressable, :polymorphic => true
end

現在,您的麻煩就在於希望有一個關聯“ company.addresses”來獲取其地址及其聯系人的地址。 我可能建議您避免使用此方法,並使用其他方法。

您將需要將視圖中的那些地址映射到正確的記錄,因此最好將它們分開:

<% form_for @company do |company_form| %>
  <% company_form.fields_for :addresses do |address_form| %>
    <%= address_form.text_field :street1 %>
  <% end %>
  <% company_form.fields_for :contacts do |contact_form| %>
    <% contact_form.fields_for :addresses do |contact_address_form| %>
      <%= contact_address_form.text_field :street1 %>
    <% end %>
  <% end %>
<% end %>

您的地址表具有如下所示的多態列:

class CreateAddresses < ActiveRecord::Migration
  def self.up
    create_table :addresses do |t|
      t.string :street1
      t.string :addressable_type
      t.integer :addressable_id
      t.timestamps
    end
  end

  def self.down
    drop_table :addresses
  end
end

如果您不像這樣單獨嵌套記錄,我不確定如何保持所有鏈接直接。

如果您確實需要獲取公司的所有地址以用於顯示,則可以使用標准的ruby可枚舉操作(例如collect)將它們收集在一起。

祝好運!

我建議讓聯系人有很多地址。 無論如何,它在野外發生。 如果只決定一個,那就是has_one :address

哦,你必須小寫它們: has_many :Contacts必須是has_many :contacts

在您引用的地址模型中(數據庫需要一個addressable_idaddressable_type字段)

belongs_to :addressable, :polymorphic => true

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM