Stai vedendo un artefatto dell'uso di irb
per investigare.
Quando si dice questo:
> Product.first.title
#=> nil
tuo method_missing
sarà chiamata a lazy-caricare il metodo title
e si ottiene nil
.
Quando si dice questo:
> Product.first
Stai efficacemente facendo questo:
> p = Product.first; puts p.inspect
La prima istanza del prodotto verrà caricato e poi irb
chiamerà inspect
su di esso e AR aggiungerà la metodi di accesso lungo la strada. Il risultato è che il prodotto ora avrà un metodo title
. Quindi, fare questo:
> Product.first
> Product.first.title
non chiamerà il method_missing
a tutti come ci sarà un vero e proprio metodo di title
per Product.first.title
per chiamare.
Se si tenta ancora una volta come questo:
> Product.first; nil
> Product.first.title
vedrete due nil
s.
Per quanto riguarda il concatenamento va, ActiveRecord in realtà non rilevare la fine, è solo che alcune chiamate di metodo, naturalmente, richiede dati reali dal database e alcuni non lo fanno.
Se si chiama where
, order
, o uno qualsiasi degli altri metodi di interrogazione, si ottiene un'istanza ActiveRecord::Relation indietro e si può catena più metodi di query e gli ambiti su quell'oggetto relazione. Ad esempio, where
(che ActiveRecord :: Relation ottiene includendo ActiveRecord::QueryMethods) si presenta così:
def where(opts, *rest)
return self if opts.blank?
relation = clone
relation.where_values += build_where(opts, rest)
relation
end
quindi rende solo una copia della query corrente, aggiunge alcune cose per la copia, e ti dà la copia indietro.
Se si chiama first
, last
, to_a
, all
, uno qualsiasi dei metodi Enumerable (vale a dire si chiama each
), ...quindi stai chiedendo istanze specifiche e ActiveRecord dovrà eseguire la query per realizzare l'istanza del modello in questione. Ad esempio, ActiveRecord::Relation#to_a
assomiglia a questo:
def to_a
logging_query_plan do
exec_queries
end
end
e all
è poco più di un wrapper to_a
.
ActiveRecord non sa veramente dove si trova la fine della catena, non carica nulla dal database finché non lo ha, così gli dici dove finisce la catena dicendo vai avanti e recuperami alcuni dati.
penso che rilevi la fine della catena: è dove non si ottiene un oggetto proxy finder! – phoet
Questa non è la domanda. La domanda è: perché '' 'Product.first.title''' restituisce' '' nil''' finché viene chiamato '' 'Product.first''', quando' '' method_missing''' viene usato all'interno di un modello. Una volta chiamato '' 'Product.first''', il titolo restituisce' '' My sample blog'''. – user544941
@ user544941: Ah, vedo cosa sta chiedendo: cosa sta sostituendo o bypassando il suo 'method_missing'. –