2010-03-18 9 views
123

En este ejemplo, creo un user sin profile, y luego creo un profile para ese usuario. Intenté usar build con una asociación has_one, pero explotó. La única forma en que veo que esto funciona es usando has_many. Se supone que el user solo tiene como máximo un profile.Usar compilación con una asociación has_one en raíles

He estado intentando esto. Tengo:

class User < ActiveRecord::Base 
    has_one :profile 
end 

class Profile < ActiveRecord::Base 
    belongs_to :user 
end 

Pero cuando lo haga:

user.build_profile 

me sale el error:

ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'profiles.user_id' in 'where clause': SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4) LIMIT 1 

¿Hay alguna manera en los carriles de tener 0 ó 1 asociación?

+0

lo que es exactamente lo que intenta? podría usted, por favor, publicar un código? –

Respuesta

324

La firma del método build es diferente para has_one y has_many asociaciones.

class User < ActiveRecord::Base 
    has_one :profile 
    has_many :messages 
end 

La sintaxis para la construcción has_many asociación:

user.messages.build 

La sintaxis para la construcción has_one asociación:

user.build_profile # this will work 

user.profile.build # this will throw error 

Leer la asociación has_onedocumentation para más detalles.

+22

La sintaxis diferente para has_one siempre me atrapa ... ¡maldita sea! – Galaxy

+2

Aprendiendo nuevos métodos mágicos cotidianos (extraños) ... – tackleberry

+0

@tackleberry, se llama metaprogramación –

-13

Debe ser un has_one. Si build no está funcionando, sólo puede utilizar new:

ModelName.new(:owner => @owner) 

es lo mismo que

@owner.model_names.build 
+10

Esto no es lo mismo: si crea un nuevo nombre_modelo con compilación, cuando @owner se guarda, entonces también se guardará el nuevo nombre_modelo. Por lo tanto, puedes usar compilación para crear un padre e hijos que se guarden juntos. Este no es el caso si haces un nombre_de_modelo con .new –

16

Eche un vistazo al mensaje de error. Le indica que no tiene la columna requerida user_id en la tabla de perfil . Establecer las relaciones en el modelo es solo una parte de la respuesta.

También debe crear una migración que agregue la columna user_id a la tabla de perfil. Rails espera que esté allí y, si no lo está, no puede acceder al perfil.

Para obtener más información, echar un vistazo a este enlace:

Association Basics

+0

Acabo de descubrir mi problema. El libro del que estoy aprendiendo no explica muy bien la creación de la clave foránea. Creé una nueva migración que agrega una clave externa a mi modelo. Gracias. – espinet

+0

¿Necesita crear la columna usted mismo cada vez? Tuve esta idea de que sucedió automágicamente. No sé de dónde saqué esa idea. – Rimian

0

Dependiendo del caso de uso, puede ser conveniente envolver el método y construir automáticamente cuando la asociación no se encontró.

old_profile = instance_method(:profile) 
define_method(:profile) do 
    old_profile.bind(self).call || build_profile 
end 

ahora llamando al método #profile, o bien devolver el perfil asociado o construir una nueva instancia.

fuente: When monkey patching a method, can you call the overridden method from the new implementation?

Cuestiones relacionadas