web-dev-qa-db-fra.com

Utilisation de build avec une association has_one dans les rails

Dans cet exemple, je crée une user sans profile, puis je crée ensuite une profile pour cet utilisateur. J'ai essayé d'utiliser build avec une association has_one mais ça a explosé. La seule façon dont cela fonctionne fonctionne avec has_many. La user est supposée avoir au plus une profile.

J'ai essayé cela. J'ai:

class User < ActiveRecord::Base
  has_one :profile
end

class Profile < ActiveRecord::Base
  belongs_to :user
end

Mais quand je fais:

user.build_profile 

Je reçois l'erreur:

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

Y a-t-il un moyen dans Rails d’avoir 0 ou 1 association? 

132
espinet

La signature de la méthode build est différente pour les associations has_one et has_many.

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

La syntaxe de construction pour l'association has_many:

user.messages.build

La syntaxe de construction pour l'association has_one:

user.build_profile  # this will work

user.profile.build  # this will throw error

Lisez le has_one association documentation pour plus de détails.

341
Harish Shetty

Regardez bien le message d'erreur. Cela vous indique que vous n'avez pas la colonne requise user_id dans la table profile. La définition des relations dans le modèle n’est qu’une partie de la réponse.

Vous devez également créer une migration qui ajoute la colonne user_id à la table de profils. Rails s'attend à ce que cela soit là et si ce n'est pas le cas, vous ne pourrez pas accéder au profil.

Pour plus d'informations, consultez ce lien:

Bases de l'association

16
sosborn

Selon le cas d'utilisation, il peut s'avérer pratique d'envelopper la méthode et de construire automatiquement l'association lorsqu'elle est introuvable.

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

l'appel de la méthode #profile renverra le profil associé ou créera une nouvelle instance.

source: Lorsque Monkey corrige une méthode, pouvez-vous appeler la méthode remplacée à partir de la nouvelle implémentation?

0
Shiyason