2010-05-29 2 views
15

Voglio scrivere un named scope per ottenere un record dal suo id.Come posso rendere named_scope in Rails restituire un valore invece di un array?

Ad esempio, ho un modello chiamato Event e voglio simulare Event.find(id) con l'uso di named_scope per flessibilità futura.

Ho usato questo codice nel mio modello:

named_scope :from_id, lambda { |id| {:conditions => ['id= ?', id] } } 

e mi chiamano dal mio controller come Event.from_id(id). Ma il mio problema è che restituisce una matrice di oggetti Event invece di un solo oggetto.

Così se voglio ottenere il nome dell'evento, devo scrivere

event = Event.from_id(id) 
event[0].name 

mentre quello che voglio è

event = Event.from_id(id) 
event.name 

sto facendo qualcosa di sbagliato qui?

risposta

10

Come dice Damien, non è consigliabile utilizzare un ambito personalizzato solo per cercare ID. Ma per rispondere alla tua domanda:

La ricerca di record con named_scope restituirà sempre un oggetto ActiveRecord::NamedScope::Scope, che si comporta come una matrice. Se c'è solo un singolo record restituito dalla tua ricerca, è possibile utilizzare il metodo first per ottenere l'oggetto ActiveRecord direttamente, in questo modo:

event = Event.from_id(id).first 
event.name # will work as you expect 
+0

hi Jimmy Grazie per la rapida risposta.Perché voglio avere uno scope con nome è (come ho accennato nel commento di Damien) perché in un secondo momento potrei voler ottenere solo gli eventi attivi Quindi posso cambiare solo l'ambito con il nome senza rompere il codice esistente (come solo aggiungendo attivo = 1) Per favore fatemi sapere i vostri commenti applausi, stessa cosa – sameera207

5

Non è necessario utilizzare uno scope qui. Potresti semplicemente fare Event.find_by_id id.
La differenza tra find e find_by_id è che il primo aumenterà un ActiveRecordNotFoundException se il record non esiste. Il secondo tornerà a zero.

Scrivere un ambito per ottenere il record in base al suo ID è un ID molto negativo poiché è qualcosa che è già fornito in modo nativo da binari.

+0

Ciao Damien, grazie per la rapida risposta. Perché voglio avere questo scopo come un nome è perché più tardi potrei desiderare di ottenere solo gli eventi attivi Quindi posso modificare solo l'ambito denominato senza rompere il codice esistente (come solo l'aggiunta di active = 1) Si prega di fatemi sapere i vostri commenti cheers, sameera – sameera207

+1

@sameera si potrebbe semplicemente aggiungere un metodo generico ('def ... end'); non deve essere un ambito con nome. –

10

In questo caso mi piacerebbe creare un metodo di classe

def self.from_id(id) 
    self.find(id).first 
end 

Un altro esempio:

class Invoice 
    def self.number 
    self.find(:first, 
     :select => "max(number) As last, max(number)+1 As next", 
     :conditions => "type = 'SalesOrder'") 
    end 
end 

Metodi come questo è meglio allora named_scope. È possibile chiamare Invoice.number.next, meglio di named_scope restituire Invoice.number[0].next.