2009-08-10 57 views
7

named_scope內假設我有一個名爲範圍:檢查模型實例落在鐵軌

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

這個偉大的工程查詢和我有一大堆的定義有用named_scopes的。我希望能夠做到這一點:

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

'.bar?'方法將簡單地返回true或false,如果模型實例在命名範圍內。無論如何不寫'is_bar?'就可以做到這一點方法,即使我已經寫了一個很好的方法來檢查是否有'is_bar?'如果我沒有記錯,DRY很好,所以任何幫助將不勝感激/

回答

20

您可以在命名作用域上調用exists?方法,它將查詢數據庫以查看給定記錄是否存在這些條件。

Foo.bar.exists?(f) 

但是,如果你已經改變了f屬性,它不保存到數據庫中這是行不通的。這是因爲命名範圍條件是SQL,所以檢查必須在那裏進行。試圖轉換爲Ruby if的條件很混亂,特別是在更復雜的情況下。

+0

謝謝。好吧,假裝我改變了值後調用了.save。 Foo.bar.exists?(Foo.find(:first))將返回true或false,取決於它是否在bar範圍內?真棒。 – user94154 2009-08-10 16:46:51

+0

正確。你不應該再次調用Find。 「f.save; Foo.bar.exists?(f)」應該工作。 – ryanb 2009-08-10 16:47:57

+4

自2009年以來,這變得更容易了嗎? – 2014-12-04 18:49:21

1

如果你的範圍很簡單,你可能想避免代碼重複。我的解決方案允許您撥打model.active?來知道某個實例是否屬於該範圍,並且Model.active可以查找與範圍匹配的所有記錄。 model.active?不涉及任何數據庫查詢。

考慮添加這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 

用法:

scope_and_method :state, 'active', 'inactive' 

作品,彷彿它是:

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

def active? 
    state == 'active' 
end 

def inactive? 
    state == 'inactive' 
end 

這是爲Rails 2.3的溶液。這需要Rails 3和4的微調。(named_scope - >scope)我會盡快檢查。