Rails:通过实例方法过滤的模型范围

时间:2012-12-14 18:50:59

标签: ruby-on-rails

我有一个封面模型,在cover.rb文件中,我还定义了一个名为size的方法,它返回一个表示小,中,大的整数'。 我的问题是如何检索所有小/中/大型封面? 我的猜测是使用scope,但我无法弄清楚如何将size方法作为条件传递。

class Cover < ActiveRecord::Base
  attr_accessible :length, :width

  # TODO
  scope :small
  scope :intermediate
  scope :large

  # I have simplified the method for clarity.
  # 0 - small; 1 - intermediate;  2 - large
  def size
    std_length = std_width = 15
    if length < std_length && width < std_width
      0
    elsif length > std_length && width > std_width
      2
    else
      1
    end
  end

end

3 个答案:

答案 0 :(得分:4)

这可行:

class Cover < ActiveRecord::Base
  attr_accessible :length, :width

  scope :of_size, lambda{ |size| 
                          case size
                            when :small
                              where('width < 15 AND height < 15')
                            when :large
                              where('width > 15 AND height > 15')
                            when :intermediate
                              where('(width < 15 AND height > 15) OR (width > 15 AND height < 15)')
                            else
                              where(id: -1) # workaround to return empty AR::Relation
                        }

  def size
    std_length = std_width = 15
    return :small if length < std_length && width < std_width
    return :large if length > std_length && width > std_width
    return :intermediate
  end

end

并像这样使用它:

Cover.of_size(:small) # => returns an array of Cover with size == small

使其适用于多个参数:

# in the model:
scope :of_size, lambda{ |*size| all.select{ |cover| [size].flatten.include?(cover.size) } }
# how to call it:
Cover.of_size(:small, :large) # returns an array of covers with Large OR Small size

答案 1 :(得分:0)

我认为你最简单的解决方案是类方法:

def self.small
  Cover.all.select {|c| c.size == 0}
end

答案 2 :(得分:0)

如果您正在考虑传递三种尺寸中的一种,您可以调用三种尺寸中的一种。它会更具可读性。

scope :small, where('width < 15 AND height < 15')
scope :large, where('width > 15 AND height > 15')
scope :intermediate, where('(width < 15 AND height > 15) OR (width > 15 AND height < 15)')