9

假设我有一个命名范围:

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

酒吧?' 如果模型实例在命名范围内,方法将简单地返回 true 或 false。无论如何都可以在不写“is_bar”的情况下做到这一点?方法,即使我已经写了一个很好的方法来检查是否有“is_bar?” 如果我没记错的话,DRY 很好,所以任何帮助都将不胜感激/

4

2 回答 2

25

exists?您可以在命名范围上调用该方法,该方法将查询数据库以查看给定记录是否在这些条件下存在。

Foo.bar.exists?(f)

f但是,如果您更改了属性并且没有将其保存到数据库中,这将不起作用。这是因为命名范围条件是 SQL,所以检查必须在那里进行。尝试转换为 Rubyif条件很麻烦,尤其是在更复杂的场景中。

于 2009-08-10T16:41:03.973 回答
0

如果您的范围很简单,您可能希望避免代码重复。我的解决方案允许您调用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) 我会尽快检查。

于 2013-12-18T14:12:36.207 回答