假设我有一个命名范围:
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?'如果模型实例属于命名范围,则method将简单地返回true或false。不管怎么说没有写'is_bar'吗?即使我已经写了一个很好的方法来检查'is_bar'是否有问题?如果我没记错的话,DRY很好,所以任何帮助都会非常感激/
答案 0 :(得分:22)
您可以在命名范围内调用exists?
方法,该范围将查询数据库以查看给定记录是否存在这些条件。
Foo.bar.exists?(f)
但是,如果您更改了f
上的属性并且未将其保存到数据库,则无法使用此功能。这是因为命名的范围条件是SQL所以必须在那里进行检查。尝试转换为Ruby if
条件很麻烦,尤其是在更复杂的情况下。
答案 1 :(得分: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
- &gt; scope
)我会尽快检查。