Как я могу заставить form.select возвращать модель в Rails?
-
03-07-2019 - |
Вопрос
У меня есть модель с именем Contact, у которой has_one guest, например.
class Contact < ActiveRecord::Base
has_one :guest, :class_name => "Contact", :foreign_key => "guest"
end
В моем представлении создания я использую метод выбора помощника, чтобы вывести список всех контактов, которые можно выбрать в качестве гостя, например ...
<% form_for(@contact) do |f| %>
<%= f.error_messages %>
...
<p>
<%= f.label :guest %><br />
<% @guests = Contact.find(:all, :order => "lastname").map { |u| [u.lastname + ', ' + u.firstname, u.id] } %>
<%= f.select :guest, @guests, {:include_blank => true} %>
</p>
...
<% end %>
Всякий раз, когда эта форма отправляется, я получаю сообщение об ошибке, в котором говорится, что он ожидал контакта, но получил строку.
Где и как мне преобразовать строку, представленную в форме, в контакт, прежде чем сохранить текущий контакт в базе данных?
Решение
Когда вы создаете ассоциацию в Rails, например has_one, существуют определенные методы, которые динамически генерируются для вашего объекта для легкого назначения. Р>
Сейчас вы используете метод
@contact.guest = @guest
И ваш контактный объект ожидает получения другого объекта ActiveRecord, с которым он может ассоциировать себя. То, что вы пытаетесь сделать, это "фальшивка" этот метод в вашей форме, который оборачивает объект модели. (Информация, поступающая из параметров, вводится в виде строки, поэтому вы получаете эту ошибку)
Есть несколько способов реализовать это. Первый с использованием атрибутов вложенной модели. , , сложные формы, которые позволяют вам обернуть дочернюю ассоциацию в form_for
, который вы используете (используя помощник формы fields_for
). Объяснение этого заняло бы много времени, и, к счастью, в сложных формах есть невероятные бесплатные ресурсы:
Сложные формы Railscasts часть 1
Сложные формы Railscasts часть 2
Сложные формы Railscasts часть 3
Кроме того, если вы используете Rails 2.3, ознакомьтесь с информацией о " accepts_nested_attributes_for
" , , , Сейчас явно не хватает учебных пособий, но я думаю, что с выпуском 2.3 их будет много. Этот удобный маленький помощник будет вырезать примерно половину кода, который Райан использует в своих скриншотах, чтобы формы принимали подчиненную модель. Р>
Наконец, есть обходной путь. Если ваши отношения просты, если гости, которых вы хотите связать, уже находятся в базе данных, и вам не нужно создавать новых из формы, которую вы используете, тогда вы можете использовать что-то вроде виртуального атрибута. В вашей форме просто измените f.select: guest
на что-то вроде f.select: guest_select
и внедрите метод в вашей модели:
def guest_select=(incoming_id_from_form)
contact = Contact.find(incoming_id_from_form)
self.guest = contact
end
Который будет назначать модель ActiveRecord без необходимости реализовывать сложную форму, чтобы сделать это за вас!