首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Hacking ActiveRecord:添加全局命名作用域

Hacking ActiveRecord:添加全局命名作用域
EN

Stack Overflow用户
提问于 2010-09-30 17:02:38
回答 4查看 2.8K关注 0票数 9

我正在尝试为ActiveRecord模型提供一组非常通用的命名作用域,如下所示:

代码语言:javascript
运行
复制
module Scopes
  def self.included(base)
    base.class_eval do
      named_scope :not_older_than, lambda {|interval|
        {:conditions => ["#{table_name}.created_at >= ?", interval.ago]
      }
    end
  end
end
ActiveRecord::Base.send(:include, Scopes)

class User < ActiveRecord::Base
end

如果命名作用域应该是一般的,我们需要指定*table_name*,以防止来自其他链式命名作用域的is连接出现命名问题。

问题是我们无法获取table_name,因为它是在ActiveRecord::Base上调用的,而不是在User上调用的。

代码语言:javascript
运行
复制
User.not_older_than(1.week)

NoMethodError: undefined method `abstract_class?' for Object:Class
from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2207:in `class_of_active_record_descendant'
from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:1462:in `base_class'
from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:1138:in `reset_table_name'
from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:1134:in `table_name'
from /home/bogdan/makabu/railsware/startwire/repository/lib/core_ext/active_record/base.rb:15:in `included'
from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:92:in `call'
from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:92:in `named_scope'
from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:97:in `call'
from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/named_scope.rb:97:in `not_older_than'

如何在Scopes模块中获得实际的table_name?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-02-28 12:25:49

Rails 5,ApplicationRecord (希望它能帮助其他人)

代码语言:javascript
运行
复制
# app/models/concerns/not_older_than.rb

module NotOlderThan
  extend ActiveSupport::Concern

  included do
    scope :not_older_than, -> (time, table = self.table_name){ 
      where("#{table}.created_at >= ?", time.ago)
    }
  end
end

# app/models/application_record.rb

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
  include NotOlderThan
end

# app/models/user.rb
class User < ApplicationRecord
  # Code
end

# Usage
User.not_older_than(1.week)

在Rails5中,默认情况下所有模型都继承自ApplicationRecord。如果您希望将此范围仅应用于特定模型集,请仅将include语句添加到这些模型类。这也适用于连接查询和链接作用域。

票数 4
EN

Stack Overflow用户

发布于 2010-09-30 17:38:03

尝试在ActiveRecord::Base的类方法中使用#scoped方法。这应该是可行的:

代码语言:javascript
运行
复制
module Scopes
  def self.included(base)
    base.class_eval do
      def self.not_older_than(interval)
        scoped(:conditions => ["#{table_name}.created_at > ?", interval.ago])
      end
    end
  end
end

ActiveRecord::Base.send(:include, Scopes)
票数 15
EN

Stack Overflow用户

发布于 2014-04-24 05:26:19

下面是其他有用的作用域:

代码语言:javascript
运行
复制
module Scopes
  def self.included(base)
    base.class_eval do
      def self.created(date_start, date_end = nil)
          if date_start && date_end
            scoped(:conditions => ["#{table_name}.created_at >= ? AND #{table_name}.created_at <= ?", date_start, date_end])
          elsif date_start
            scoped(:conditions => ["#{table_name}.created_at >= ?", date_start])
          end
      end
      def self.updated(date_start, date_end = nil)
          if date_start && date_end
            scoped(:conditions => ["#{table_name}.updated_at >= ? AND #{table_name}.updated_at <= ?", date_start, date_end])
          elsif date_start
            scoped(:conditions => ["#{table_name}.updated_at >= ?", date_start])
          end
      end
    end
  end
end

ActiveRecord::Base.send(:include, Scopes)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3829174

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档