Rails – Best-Practice: Comment créer des relations has_one dépendantes

Pourriez-vous me dire quelle est la meilleure pratique pour créer des relations has_one?

fe si j’ai un modèle d’utilisateur, et qu’il doit avoir un profil …

Comment pourrais-je accomplir cela?

Une solution serait:

# user.rb class User << ActiveRecord::Base after_create :set_default_association def set_default_association self.create_profile end end 

Mais cela ne semble pas très propre … Quelqu’un suggère?

La meilleure pratique pour créer une relation has_one consiste à utiliser le rappel ActiveRecord before_create plutôt que after_create . Ou utilisez un rappel encore plus précoce et résolvez les problèmes (le cas échéant) de l’enfant qui ne passe pas sa propre étape de validation.

Car:

  • avec un bon codage, vous avez la possibilité d’afficher les validations de l’enregistrement enfant à l’utilisateur si les validations échouent
  • Il est plus propre et explicitement pris en charge par ActiveRecord – L’AR remplit automatiquement la clé étrangère de l’enregistrement enfant après l’enregistrement de l’enregistrement parent (lors de la création). AR enregistre alors l’enregistrement enfant dans le cadre de la création de l’enregistrement parent.

Comment faire:

 # in your User model... has_one :profile before_create :build_default_profile private def build_default_profile # build default profile instance. Will use default params. # The foreign key to the owning User model is set automatically build_profile true # Always return true in callbacks as the normal 'continue' state # Assumes that the default_profile can **always** be created. # or # Check the validation of the profile. If it is not valid, then # return false from the callback. Best to use a before_validation # if doing this. View code should check the errors of the child. # Or add the child's errors to the User model's error array of the :base # error item end 

Votre solution est sans aucun doute une façon décente de le faire (du moins jusqu’à ce que vous la dépassiez), mais vous pouvez la simplifier:

 # user.rb class User < ActiveRecord::Base has_one :profile after_create :create_profile end 

S’il s’agit d’une nouvelle association dans une grande firebase database existante, je gérerai la transition comme suit:

 class User << ActiveRecord::Base has_one :profile before_create :build_associations def profile super || build_profile(avatar: "anon.jpg") end private def build_associations profile || true end end 

de sorte que les enregistrements d'utilisateurs existants obtiennent un profil lorsque cela leur est demandé et que de nouveaux sont créés avec lui. Cela place également les atsortingbuts par défaut à un seul endroit et fonctionne correctement avec accept_nested_atsortingbutes_for dans Rails 4 et suivants.

Probablement pas la solution la plus propre, mais nous avions déjà une firebase database avec un demi-million d’enregistrements, dont certains avaient déjà le modèle «Profile» créé, et d’autres non. Nous avons opté pour cette approche, qui garantit qu’un modèle Profile est présent à tout moment, sans avoir à passer par et générer rétroactivement tous les modèles Profile.

 alias_method :db_profile, :profile def profile self.profile = Profile.create(:user => self) if self.db_profile.nil? self.db_profile end 

Voici comment je le fais. Je ne sais pas si c’est standard, mais ça marche très bien et c’est paresseux car cela ne crée pas de surcharge supplémentaire à moins qu’il soit nécessaire de construire la nouvelle association (je suis heureux d’être corrigé):

 def profile_with_auto_build build_profile unless profile_without_auto_build profile_without_auto_build end alias_method_chain :profile, :auto_build 

Cela signifie également que l’association est là dès que vous en avez besoin. Je suppose que l’alternative est d’accéder à after_initialize, mais cela semble append un peu de temps, car il est exécuté à chaque fois qu’un object est initialisé, et il peut arriver que vous ne souhaitiez pas accéder à l’association. Cela semble être un déchet pour vérifier son existence.

Il y a un bijou pour cela:

https://github.com/jqr/has_one_autocreate

On dirait que c’est un peu vieux maintenant. (pas travailler avec des rails3)