2010-10-14 10 views
6

No estoy exactamente seguro de cuál es mi problema, por lo que esta cuestión puede requerir alguna aclaración más, pero esto es lo que parece ser más relevante:carriles 3 has_many: por medio del registro guardar error

Tengo un has_many :through y la modelo de unión tiene algunos campos que no son claves foráneas. Cuando construyo los modelos y trato de guardar obtengo un error de validación en los campos clave no foráneos del modelo de unión.

Mis archivos parecen:

Person.rb 

    has_many :wedding_assignments, :dependent => :destroy 
    has_many :weddings, :through=>:wedding_assignments 
    accepts_nested_attributes_for :weddings 
    accepts_nested_attributes_for :wedding_assignments 

Wedding.rb 

    has_many :wedding_assignments, :dependent => :destroy 
    has_many :people, :through=>:wedding_assignments 
    accepts_nested_attributes_for :people 
    accepts_nested_attributes_for :wedding_assignments 

WeddingAssignment.rb 

    belongs_to :person 
    belongs_to :wedding 
    validates_presence_of :role, :person, :wedding 

(papel es una cadena)

people_controller.rb 

    def new 
    @person = Person.new 

    1.times do 
     wedding = @person.weddings.build 
     1.times do 
     assignment = wedding.wedding_assignments.build 
     assignment.person = @person 
     assignment.wedding = wedding 
     end 
    end 
    end 

    def create 
    @person = Person.new(params[:person]) 
    @person.weddings.each do |wedding| 
     wedding.wedding_assignments.each do |assignment| 
     assignment.person = @person #i don't think I should need to set person and wedding manually, but I get a validation error if I don't 
     assignment.wedding = wedding 
     end 
    end 
end 

los parametros que vuelven parecen:

{"first_name"=>"", "last_name"=>"", "weddings_attributes"=>{"0"=>{"wedding_assignments_attributes"=>{"0"=>{"role"=>"Bride's Maid", "budget"=>""}}, "date"=>"", "ceremony_notes"=>""}}} 

Y el error exacto es:

ActiveRecord::RecordInvalid in PeopleController#create 
Validation failed: Role can't be blank 

que claramente no es correcta, ya que se puede ver en params[]

¿Qué estoy haciendo mal?

Ésta es raíles 3.0.0

+2

Tengo curiosidad por saber cuál es el uso de esos '1.times'? – PeterWong

+0

Hago eso para que sea más fácil si quiero cambiarlo a 2. veces o más después. – SooDesuNe

+0

Tienes razón, hacer eso incluso puede permitir al usuario elegir agregar 10 bodas de una vez. : D – PeterWong

Respuesta

0

trate de cambiar "Person.new" a "Person.create", tal vez crea el registro en el PP de inmediato le ayudará con las asociaciones.

+0

Definitivamente no los quiero en la base de datos de inmediato. ¿Qué sucede si el usuario cambia de opinión y se aleja de la página? ¿No tendré un registro vacío si uso 'crear'? – SooDesuNe

1

derecho, esto es un poco de una conjetura, por lo disculpas si termino perdiendo el tiempo aquí ...

A mi me parece como en su método de creación, que está creando la relación 'boda' (que es solo una relación 'simulada' realmente, tiene que ser: through =>: wedding_assignments), y luego regresa esto. Luego está pidiendo a los rieles que vuelvan a crear estos objetos en su llamada a Person.new. Supongo que los rieles se confunden al intentar crear un objeto en el lado opuesto de un has_many: through sin que esté presente el objeto intermedio.

estaría tentado a reestructurar esto un poco (código no probado!):

def new 
    @person = Person.new 
    @wedding = Wedding.new 
    @wedding_assignment = WeddingAssignment.new 
end 

def create 
    @person = Person.new(params[:person]) 
    @wedding = Wedding.new(params[:person]) 
    @assignment = WeddingAssignment.new(params[:wedding_assignment].merge({:person => @person})) 
end 

Tengo una sensación de que esto va a trabajar hasta la última línea. Sospecho que conseguir que funcione puede que tenga que utilizar las transacciones:

def create 
    @person = Person.new(params[:person]) 
    @wedding = Wedding.new(params[:person]) 
    ActiveRecord::Base.transaction do 
    if @person.valid? && @wedding.valid? 
     [@person,@wedding].each.save! 
     @assignment = WeddingAssignment.new(params[:wedding_assignment].merge({:person => @person})) 
     @assignment.save! 
    end 
    end 
end 

Esto debe asegurarse de que todo se crea en el orden correcto y los ID están disponibles en el momento adecuado, etc. Lamentablemente, sin embargo, es un poco más complicado que su ejemplo, y significa que tendrá dificultades para soportar bodas múltiples.

Espero que esto ayude, y no terminar siendo un callejón sin salida.

+0

Con mucho, la mejor respuesta hasta ahora. Hacerlo de esta manera significa que no podré generar los campos de formulario limpiamente (es decir, como en: http://railscasts.com/episodes/196-nested-model-form-part-1). Rails debería ser capaz de administrar estas asociaciones. Durante el fin de semana reescribí el código para compilar y ejecutar, comenzando con el modelo join, WeddingAssignment, en lugar de Person, y funciona bien. Así que creo que estás en el camino correcto porque los rieles se confunden ' – SooDesuNe

+0

Tengo una cuestión similar que estoy tratando de resolver con esta pregunta, pero recibo un error de seguridad de asignación masiva en persona. ¿Algunas ideas? – ctilley79

Cuestiones relacionadas