Pregunta

Tengo un modelo llamado Contact que tiene un invitado como este.

class Contact < ActiveRecord::Base
  has_one :guest, :class_name => "Contact", :foreign_key => "guest"
end

En mi vista de creación, estoy usando el método de ayuda selectivo para enumerar todos los contactos que se pueden elegir como invitados, así que ...

<% 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 %>

Cada vez que se envía este formulario, recibo un error que dice que esperaba un contacto pero recibió una cadena.

¿Dónde y cómo debo convertir la cadena enviada por el formulario a un contacto antes de guardar el contacto actual en la base de datos?

¿Fue útil?

Solución

Cuando crea una asociación en Rails, como has_one, hay ciertos métodos que se generan dinámicamente para su objeto para una fácil asignación.

En este momento, el método que está utilizando es

@contact.guest = @guest

Y su objeto de contacto espera recibir otro objeto ActiveRecord con el que pueda asociarse. Sin embargo, lo que intenta hacer es amable '' falso '' Este método en su formulario que envuelve un objeto modelo. (La información que proviene de los parámetros se presenta como una cadena, por lo que está recibiendo ese error)

Hay varias formas de implementar esto. El primero con está utilizando atributos de modelo anidados. . . formularios complejos que le permiten ajustar una asociación secundaria dentro del form_for que está utilizando (utilizando el asistente de formulario fields_for ). Una explicación de esto tomaría mucho tiempo para escribir, y afortunadamente hay recursos gratuitos increíbles en formas complejas:

Formularios complejos Railscasts parte 1

Formularios complejos Railscasts parte 2

Formularios complejos Railscasts parte 3

Además, si está utilizando Rails 2.3, consulte alguna información sobre " accept_nested_attributes_for " . . . Hay una clara falta de tutoriales en este momento, pero me imagino que con el lanzamiento de 2.3 habrá muchas novedades. Este pequeño y práctico ayudante recortará aproximadamente la mitad del código que Ryan usa en su pantalla para hacer que los formularios acepten un modelo subordinado.

Finalmente hay una solución alternativa. Si su relación es simple, si los invitados que desea asociar ya están en la base de datos y no necesita crear nuevos a partir del formulario que está utilizando, puede usar algo como un atributo virtual. En su formulario, simplemente cambie su f.select: guest a algo así como f.select: guest_select e implemente un método en su modelo:

def guest_select=(incoming_id_from_form)
  contact = Contact.find(incoming_id_from_form)
  self.guest = contact
end

¡Que asignará el modelo ActiveRecord sin tener que implementar un formulario complejo para que lo haga por usted!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top