ActiveRecord-“第一” “范围”中的方法返回多个记录 [英] ActiveRecord - "first" method in "scope" returns more than one record

查看:70
本文介绍了ActiveRecord-“第一” “范围”中的方法返回多个记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Rails的新手,但遇到了奇怪的问题。

I'm new to Rails and I have strange problem.

以下是代码示例:

class News < ActiveRecord::Base
  scope :pinned, -> { where(pinned: true).first }
end

如果记录中包含固定标志没有问题,当我调用 News.pinned 会返回一条记录。

If there are records with "pinned" flag there is no problem, when I call News.pinned returns a single record.

在日志中查询以下内容:

And I see this query in the log:

SELECT `news`.* 
FROM `news` 
WHERE `news`.`pinned` = 1 
ORDER BY `news`.`id` ASC 
LIMIT 1

但是如果没有带有 pinned标志的记录,当我调用 News.pinned 时,将执行以下两个查询:

But if there are no records with "pinned" flag, when I call News.pinned the next two queries are executed:

SELECT `news`.* 
FROM `news` 
WHERE `news`.`pinned` = 1 
ORDER BY `news`.`id` ASC 
LIMIT 1

SELECT `news`.* FROM `news`

谢谢!

推荐答案

友好,这是方法范围 ActiveRecord的内容:

Friendy, here is the method "scope" of the ActiveRecord:

1   # File activerecord/lib/active_record/scoping/named.rb, line 145
2   def scope(name, body, &block)
3     extension = Module.new(&block) if block
4
5     # Check body.is_a?(Relation) to prevent the relation actually being
6     # loaded by respond_to?
7     if body.is_a?(Relation) || !body.respond_to?(:call)
8       ActiveSupport::Deprecation.warn(
9         "Using #scope without passing a callable object is deprecated. For "                "example `scope :red, where(color: 'red')` should be changed to "                "`    scope :red, -> { where(color: 'red') }`. There are numerous gotchas "                "in the former usage and it makes the implementation more complicated "                "and     buggy. (If you prefer, you can just define a class method named "                "`self.red`.)"
10      )
11    end
12
13    singleton_class.send(:define_method, name) do |*args|
14      if body.respond_to?(:call)
15        scope = all.scoping { body.call(*args) }
16        scope = scope.extending(extension) if extension
17      else
18        scope = body
19      end
20
21      scope || all
22    end
23  end

如果范围是

在您的情况下,当您在第15行中调用没有记录的 News.pinned时,将运行第一个查询,并且作用域将收到 nil,因此当它获得时到第21行,因为范围为 nil,所以运行 all以进行第二次查询并返回所有寄存器。

Note the line 21 if the scope is "nil" then "all" is returned.
In your case, when you call "News.pinned" without records in line 15 the first consult is run and scope receive "nil", so when it gets to line 21, as scope is "nil", "all" is run making the second consult and returning all registers.

我已经对其进行了测试,覆盖了 scope方法通过删除第21行的全部,我只有一个查询

I've tested it overwriting the method "scope" by removing the "all" of the line 21 and i had just one query

要绕过此用法:

class News < ActiveRecord::Base
  def self.pinned
    where(pinned: true).first
  end
end

这篇关于ActiveRecord-“第一” “范围”中的方法返回多个记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆