web-dev-qa-db-fra.com

Ruby sur Rails. Comment utiliser la méthode .build Active Record dans une relation: appartient à?

J'ai été incapable de trouver de la documentation sur la méthode .build dans Rails (j'utilise actuellement la version 2.0.2).

Après expérimentation, il semble que vous puissiez utiliser la méthode de construction pour ajouter un enregistrement dans un fichier has_many relation avant qu'un enregistrement n'ait été sauvegardé.

Par exemple:

class Dog < ActiveRecord::Base
  has_many :tags
  belongs_to :person
end

class Person < ActiveRecord::Base
  has_many :dogs
end

# Rails c
d = Dog.new
d.tags.build(:number => "123456")
d.save # => true

Cela enregistrera correctement le chien et l'étiquette avec les clés étrangères. Cela ne semble pas fonctionner dans un belongs_to relation.

d = Dog.new
d.person.build # => nil object on nil.build

J'ai aussi essayé

d = Dog.new
d.person = Person.new
d.save # => true

La clé étrangère dans Dog n'est pas définie dans ce cas car, au moment de son enregistrement, la nouvelle personne n'a pas d'identifiant car elle n'a pas encore été enregistrée.

Mes questions sont:

  1. Comment fonctionne la compilation pour que Rails soit suffisamment intelligent pour comprendre comment sauvegarder les enregistrements dans le bon ordre?

  2. Comment puis-je faire la même chose dans un belongs_to relation?

  3. Où puis-je trouver de la documentation sur cette méthode?

Je vous remercie

127
stellard

Où est-il documenté:

Extrait de la documentation de l'API sous l'association has_many dans " Module ActiveRecord :: Associations :: ClassMethods "

collection.build (attributs = {},…) Retourne un ou plusieurs nouveaux objets du type collection qui ont été instanciés avec des attributs et liés à cet objet via une clé étrangère, mais qui n'ont pas encore été enregistrés. Remarque: cela ne fonctionne que si un objet associé existe déjà, pas si il est nul!

La solution pour construire dans le sens opposé est une syntaxe légèrement modifiée. Dans votre exemple avec les chiens,

Class Dog
   has_many :tags
   belongs_to :person
end

Class Person
  has_many :dogs
end

d = Dog.new
d.build_person(:attributes => "go", :here => "like normal")

ou même

t = Tag.new
t.build_dog(:name => "Rover", :breed => "Maltese")

Vous pouvez également utiliser create_dog pour le sauvegarder instantanément (tout comme la méthode "create" correspondante, vous pouvez faire appel à la collection).

Comment est Rails assez intelligent? C'est magique (ou plus exactement, je ne sais pas, j'aimerais bien le découvrir!)

145
BushyMark
@article = user.articles.build(:title => "MainTitle")
@article.save
47
nehpets