在ActiveRecord类方法中返回`self`会失去间接引用

时间:2016-02-10 23:42:09

标签: ruby-on-rails ruby activerecord least-astonishment

在ActiveRecord中定义类方法时,如果我返回self,则间接引用将丢失。

我不确定我是否正在使用正确的词汇表,因为我只是学习Ruby on Rails,所以这是一个例子:

class User < ActiveRecord::Base
  has_many :orchids
end

class Orchid < ActiveRecord::Base
  belongs_to :user

  def self.search(query)
    if query.present?
      query = '%' + query.gsub(/\s+/, '%') + '%'
      where 'gender ILIKE :query OR variety ILIKE :query', query: query
    else
      # Problematic line:
      self
    end
  end
end

使用上面的定义,会发生这种情况:

% User.last.orchids.count
   (0.8ms)  SELECT COUNT(*) FROM "orchids" WHERE "orchids"."user_id" = $1  [["user_id", 2]]
 => 0 

% User.last.orchids.search('').count
   (1.2ms)  SELECT COUNT(*) FROM "orchids"
 => 449 

% User.last.orchids.search('cat').count
   (1.2ms)  SELECT COUNT(*) FROM "orchids" WHERE "orchids"."user_id" = $1 AND (gender ILIKE '%cat%' OR variety ILIKE '%cat%')  [["user_id", 2]]
 => 0

因此,返回self似乎使“只有这个用户的兰花”的间接范围消失了。返回self表示我正在返回Orchid课而不是ActiveRecord::Relation

在互联网上读了一下,我确实找到了范围以及为什么要使用它们。范围确实按照我期望的方式工作,我现在正在使用它们。我只是不明白为什么在使用类方法定义时这会出现这种情况。

1 个答案:

答案 0 :(得分:2)

自我将返回班级,因为自我是班级。作为scope返回ActiveRecord :: Relation实例。所以Orchid.where方法构建并返回一个新的ActiveRecord :: Relation,而self只返回类本身。

如果您选择,两者仍然可以与其他范围链接。如果您真的想要AR :: Relation,请将self更改为Orchid.none。