2009-08-10 13 views
7

Si supponga Ho un ambito denominato:Controllare se l'istanza modello rientra nella named_scope rotaie

class Foo < ActiveRecord::Base 
    named_scope :bar, :conditions => 'some_field = 1' 
end 

Questa grande opera per le query e ho un sacco di named_scopes utile definita. Quello che vorrei è essere in grado di fare questo:

f = Foo.find(:first) 
f.some_field = 1 
f.is_bar? #=> true 

Il '.bar?' il metodo restituirà semplicemente true o false se l'istanza del modello rientra nell'ambito denominato. C'è comunque modo di farlo senza scrivere un 'is_bar?' metodo anche se ho già scritto un buon modo per verificare se qualcosa 'is_bar?' Se ricordo male, DRY è buono quindi qualsiasi aiuto sarebbe molto apprezzato/

risposta

20

È possibile chiamare il metodo exists? su un ambito denominato che interrogherà il database per verificare se il record specificato esiste con tali condizioni.

Foo.bar.exists?(f) 

Tuttavia questo non funzionerà se avete cambiato gli attributi sul f e non salvato nel database. Questo perché le condizioni dell'ambito con nome sono SQL, quindi il controllo deve esserci. Il tentativo di convertire in Ruby if condizioni è disordinato, soprattutto in scenari più complessi.

+0

grazie. Ok, fingi di aver chiamato .save dopo aver cambiato il valore. Foo.bar.exists? (Foo.find (: first)) restituirà true o false a seconda che rientri nell'ambito della barra? Eccezionale. – user94154

+0

corretto. Non dovresti nemmeno chiamare di nuovo Trova. "f.save; Foo.bar.exists? (f)" dovrebbe funzionare. – ryanb

+4

Questo è diventato più facile dal 2009? –

1

Se gli ambiti sono semplici, probabilmente si desidera evitare la duplicazione del codice. La mia soluzione consente di chiamare model.active? per sapere se un'istanza appartiene all'ambito e Model.active per trovare tutti i record corrispondenti all'ambito. model.active? non implica alcuna query di database.

considerare l'aggiunta di questo config/initializers/scope_and_method.rb:

require 'active_record/named_scope' 

module ActiveRecord::NamedScope::ClassMethods 
    def scope_and_method field, *values 
    field = field.to_sym 
    values.each do |value| 
     named_scope value.to_sym, :conditions => {field => value} 
     define_method "#{value}?" do 
     send(field.to_sym) == value 
     end 
    end 
    end 
end 

Usage:

scope_and_method :state, 'active', 'inactive' 

Opere come se fosse:

named_scope :active, :conditions => {:state => 'active'} 
named_scope :inactive, :conditions => {:state => 'inactive'} 

def active? 
    state == 'active' 
end 

def inactive? 
    state == 'inactive' 
end 

Questa è una soluzione per Rails 2.3. Ciò richiede una sintonizzazione molto piccola per Rails 3 e 4. (named_scope ->scope) Verificherò presto.

Problemi correlati