Ruby on Rails. Come uso il metodo .build di Active Record in a: appartiene alla relazione?


128

Non sono stato in grado di trovare alcuna documentazione sul metodo .build in Rails (attualmente sto usando 2.0.2).

Attraverso la sperimentazione sembra che tu possa usare il metodo build per aggiungere un record in una has_manyrelazione prima che entrambi i record siano stati salvati.

Per esempio:

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

Ciò salverà correttamente sia il cane che il tag con le chiavi esterne. Questo non sembra funzionare in una belongs_torelazione.

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

Ho anche provato

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

In Dogquesto caso la chiave esterna non è impostata a causa del fatto che al momento del salvataggio la nuova persona non ha un ID perché non è stata ancora salvata.

Le mie domande sono:

  1. Come funziona build in modo che Rails sia abbastanza intelligente da capire come salvare i record nell'ordine giusto?

  2. Come posso fare la stessa cosa in a belongs_to relazione?

  3. Dove posso trovare documentazione su questo metodo?

Grazie


Per quanto riguarda la documentazione, consultare le Guide di Rails "Metodi aggiunti da belongs_to" e "Metodi aggiunti da has_one" . Ulteriori documentazione tecnica è disponibile nei documenti API: belongs_toe has_one.
Dennis,

Risposte:


147

Dove è documentato:

Dalla documentazione API sotto l'associazione has_many in " Modulo ActiveRecord :: Associations :: ClassMethods "

collection.build (attributi = {}, ...) Restituisce uno o più nuovi oggetti del tipo di raccolta che sono stati istanziati con attributi e collegati a questo oggetto tramite una chiave esterna, ma non sono stati ancora salvati. Nota: funziona solo se esiste già un oggetto associato, non se è zero!

La risposta alla costruzione nella direzione opposta è una sintassi leggermente modificata. Nel tuo esempio con i cani,

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")

o anche

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

Puoi anche usare create_dog per salvarlo all'istante (proprio come il metodo "create" corrispondente che puoi chiamare sulla raccolta)

In che modo le rotaie sono abbastanza intelligenti? È magico (o più precisamente, semplicemente non lo so, mi piacerebbe scoprirlo!)


4
@BushyMark: usa method_missing o metaporgramming per aggiungere quei metodi con define_method.
Federico

@Federico dove è definito il metodo mancante?
risveglio il

1
@ alock27 Come per ActiveRecord che usa il metodo mancante per il tuo find_by_emaile i find_by_column_namemetodi. Converte il metodo che passi a una stringa e la analizza e cerca di abbinarlo ai nomi delle colonne della tabella.
bigpotato,

@edmund Grazie per il tuo commento. Per essere chiari, capisco come funziona method_missing. Stavo cercando di individuare l'effettiva posizione del file che definisce questo particolare metodo mancante.
risveglio il

@ alock27 se lo stai chiedendo perché vuoi esaminare come è definito, dai un'occhiata a Metaprogramming Ruby. Ma se stai davvero cercando la posizione effettiva, potresti probabilmente cercare Google per il codice sorgente.
MCB

48
@article = user.articles.build(:title => "MainTitle")
@article.save

>> d.tags.build (: number => "123456") >> d.save # => true Non è lo stesso?
Antiqe
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.