Редактирование моего вопроса для краткости и обновить то, что я сделал:
Как я моделирую наличие нескольких Адресов для Компании и присваиваю единственный Адрес Контакту и могу присвоиться им при создании или редактировании Контакта?
Я хочу использовать вложенные атрибуты, чтобы смочь добавить адрес во время создания нового контакта. Тот адрес существует как своя собственная модель, потому что я могу хотеть опцию к выпадающему от существующих адресов вместо того, чтобы войти с нуля.
Я, может казаться, не заставляю это работать. Я получаю неопределенный метод 'сборка' для nil:NilClass ошибки
Вот моя модель для Контактов:
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
Вот то, как я пытаюсь создать поле в Представлении для _form для Контакта так, чтобы, когда кто-то создает новый Контакт, они передали адрес модели Address и партнеру, которые адресуют к Контакту:
<% 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 в 12.05.2010 21:16:17)
[POST] Параметры: {"фиксация" => "Отправляет", "authenticity_token" => "d8/gx0zy0Vgg6ghfcbAYL0YtGjYIUC2b1aG+dDKjuSs = ", "связывается" => {"company_name" => "Allyforce", "заголовок" =>"", "campaign_id" => "2", "address_attributes" => {"street1" => "abc"} ", факс" =>"", "звонят" =>"" ", last_name" =>"" ", date_entered" => "2010-05-12", "электронная почта" =>"" ", first_name" => "abc" }}
Загрузка компании (0,0 мс) [0m [0mSELECT * ОТ "компаний", ГДЕ ("компании". "назовите" = 'Allyforce'), ОГРАНИЧИВАЮТ 1 [0m
Адрес создает (16,0 мс) [0m
[0; 1mINSERT В "адреса" ("город", "zip", "created_at", "street1", "updated_at", "street2", "состояние") ЗНАЧЕНИЯ (ПУСТОЙ УКАЗАТЕЛЬ, ПУСТОЙ УКАЗАТЕЛЬ, '13.05.2010 4:16:18', ПУСТОЙ УКАЗАТЕЛЬ, '13.05.2010 4:16:18', ПУСТОЙ УКАЗАТЕЛЬ, ПУСТОЙ УКАЗАТЕЛЬ) [0mКонтакт создает (0,0 мс) [0m
[0mINSERT В "контакты" ("компания", "created_at", "заголовок", "updated_at", "campaign_id", "address_id", "last_name", "телефон", "факс", "company_id", "date_entered", "first_name", "электронная почта") ЗНАЧЕНИЯ (ПУСТОЙ УКАЗАТЕЛЬ, '13.05.2010 4:16:18', '', '13.05.2010 4: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
Если вы посмотрите на исходный код, ваше поле ввода должно выглядеть так.
< input 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 %>
Поля partial содержат все ваши фиды вместе с:
<% 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, который добавляет адресные_атрибуты и удаляет (стиль переключения).
Я бы рекомендовал позволить Контакту иметь много адресов. Это происходит в любом случае. Если решено, что только один, то это будет has_one :address
О, и вы должны уменьшить их: has_many :Contacts
должно быть has_many :contacts
В модели адресов, на которую вы ссылаетесь (базе данных нужны поля addressable_id
и addressable_type
)
belongs_to :addressable, :polymorphic => true
Если каждый адрес принадлежит только одному контакту (например, домашний адрес), вы можете сделать:
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
Конечно, вы можете просто переместить столбцы адресов в таблицу контактов и полностью избавиться от модели адреса.
Если каждый адрес имеет несколько контактов (т. Е. Адреса являются объектами компании, где работают контакты):
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: через
, чтобы получить company.addresses
]:
class Company < ActiveRecord::Base
has_many :contacts
has_many :addresses, :through => :contacts
end
В обоих случаях компоненты адреса (улица, город, штат и т. Д.) Являются столбцами в таблице адресов.
Последняя часть вашего вопроса действительно зависит от распределения данных - если у вас всего несколько адресов, вы можете просто вставить их в элемент select с основным адресом по умолчанию. При большем количестве адресов вам может потребоваться форма AJAXified с автозаполнением для поиска в таблице адресов.
Чтобы добавить новые контакты / адреса в таблицы, вы можете просмотреть вложенные формы. Railscast 196 - хорошее введение.
РЕДАКТИРОВАТЬ - подробнее о вложенных атрибутах
accept_nested_attributes_for
должен работать с ассоциацией has_many
или has_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
Затем в представлении используйте form_for
и fields_for
как описано в Railscast, чтобы получить вложенные элементы формы. Это может быть немного сложно сделать правильно, если ваша форма необычна.Здесь есть отличные примеры от ryanb , которые охватывают несколько типичных ситуаций.
Поскольку вы хотите, чтобы адрес принадлежал и компании, и контакту, у вас есть два варианта.Если вам никогда не понадобится несколько адресов (что я бы не рекомендовал предполагать), вы можете указать «own_to: address» как в Company, так и в контакте. Тогда адрес будет иметь как «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, такие как сбор, чтобы собрать их вместе.
Удачи!