2012-08-10 24 views
13

Qualcuno può spiegare cosa fa questo metodo e cosa posso passare ad esso?Scoped e scope in rotaie

scoped(options = nil) 
Returns an anonymous scope. 

E anche il metodo di ambito? Non capisco dopo aver letto la documentazione.

risposta

30

In ActiveRecord, tutti i metodi di creazione delle query (come where, order, joins, limit e così via) restituiscono un cosiddetto portata. Solo quando si chiama un metodo kicker come all o first viene eseguita la query incorporata e vengono restituiti i risultati dal database.

Il metodo di classe scoped restituisce anche un ambito. L'ambito restituito è di default vuoto, il che significa che il set di risultati non sarà limitato in alcun modo, nel senso che tutti i record verrebbero restituiti se la query è stata eseguita. Puoi usarlo per fornire un'alternativa "vuota" come nell'query_by_date esempio di MurifoX. Oppure si può utilizzare per combinare più condizioni in una chiamata di metodo, come ad esempio:

Model.scoped(:conditions => 'id < 100', :limit => 10, :order => 'title ASC') 

# which would be equivalent to 
Model.where('id < 100').limit(10).order('title ASC') 

Il metodo della classe scope consente di definire un metodo di classe che restituisce anche un ambito, come ad esempio:

class Model 
    scope :colored, lambda {|col| 
    where(:color => col) 
    } 
end 

che può essere utilizzato in questo modo:

Model.colored 

La cosa bella con gli ambiti è che si possono combinare (quasi) come si desidera, quindi il seguente è assolutamente possibile:

Model.red.where('id < 100').order('title ASC').scoped(:limit => 10) 

ho anche fortemente suggerire la lettura attraverso http://guides.rubyonrails.org/active_record_querying.html

+0

Grazie severin, ha aiutato. Come faccio a sapere cosa posso passare a .scoped? Vedo: condizioni => ecc. – LuckyLuke

+1

Troverai un elenco completo di tutte le opzioni qui: http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find-label-Options – severin

+0

Impressionante ! Grazie per il vostro aiuto – LuckyLuke

5

ho usato nel past.When di effettuare chiamate concatenati all'interfaccia ActiveRecord query come questa:

Model.where(:conditions).where(:more_conditions).where(:final_conditions) 

Ognuno di essi è già scope, rendendo il lavoro catena senza alcun problema. Ma supponiamo di avere qualcosa di simile:

Model.query_by_date(date).query_by_user(user).query_by_status(status) 

scope :query_by_date, lambda { |date| 
    case date 
    when "today" 
    where(:date => Date.today) 
    when "tomorrow" 
    where(:date => Date.tomorrow) 
    else 
    # Any value like '' or 0 or Date.whatever 
    end 
} 

Ciò causerebbe un errore se la data param non è oggi o domani. Prenderà l'ultimo valore e cercherà di concatenare questa query con la successiva query_by_user, risultante in un undefined method default_scoped? for ''. Ma se metti un metodo nella condizione else, funzionerebbe senza difetti, perché stai dicendo a activerecord che passi attraverso questo metodo/named scope e non hai fatto nessuna chiamata a where/find/other activerecord methods, ma hai restituito un oggetto ambito, così puoi continuare a concatenare query e cose.
Sarebbe così alla fine.

else 
    scoped 
end 

Spero che tu capisca questo semplice esempio.

+0

Ci può spiegare cosa significa essere "ambito"? – LuckyLuke

+1

È come "essere" compatibile con ActiveRecord. Incapsulato da tutte le specifiche di ActiveRecords. – MurifoX

+0

Non sono sicuro di capire "ambito" a parte quello capisco cosa intendi ... cioè, vedo che fallirà altrimenti. Ma non capisco cosa possa fare ed essere lo "scoped". – LuckyLuke