Rails 3默认范围,范围与覆盖

时间:2011-08-02 22:09:42

标签: ruby-on-rails ruby-on-rails-3 activerecord named-scope default-scope

我的情况是现有应用的行为正在发生变化,这让我头疼不已。

我的应用有照片。照片的状态为:"batch", "queue", or "complete"。应用中的所有现有照片都是“完整的”。

99%的时间我只需要显示完整的照片,而在所有现有的代码库中,我需要每次调用照片仅限于完整的照片。

但是,在与上传和分类照片相关的屏幕中,我需要能够相当轻松地覆盖该默认范围以显示批量或排队的照片。

与许多其他人一样,我需要找到一种在某些情况下轻松覆盖默认范围的方法。我查看了这些问题(12),他们似乎没有回答我正在寻找的问题。

我希望的代码是:

class Photo < ActiveRecord::Base
  ...
  default_scope where(:status=>'complete')
  scope :batch, unscoped.where(:status=>'batch')
  scope :queue, unscoped.where(:status=>'queue')
  ...
end

然而,这不起作用。我尝试在lambdas中包装范围方法,但这也不起作用。

我发现default_scope带有行李,但如果我不能使用覆盖,那么我正在寻找添加scope :complete ...并且必须梳理现有应用中对照片的每次调用并添加{{1为了过滤未经处理的照片。

你会如何解决这个问题?

2 个答案:

答案 0 :(得分:6)

def self.batch
  Photo.unscoped.where(:status=>"batch")
end
这个主题更具权威性:Overriding a Rails default_scope

答案 1 :(得分:3)

我试了一下。假设您要从默认范围中删除where子句(而不是仅使用其他值覆盖它)并保留关联,您可以尝试这样做:

class Photo < ActiveRecord::Base
  default_scope where(:status => 'complete').where(:deleted_at => '').order('id desc')

  def self.without_default_status
    # Get the ActiveRecord::Relation with the default_scope applied.
    photos = scoped.with_default_scope
    # Find the where clause that matches the where clause we want to remove 
    # from the default scope and delete it.
    photos.where_values.delete_if { |query| query.to_sql == "\"photos\".\"status\" = 'complete'" }
    photos
  end

end