ActiveRecord-“第一” “范围”中的方法返回多个记录 [英] ActiveRecord - "first" method in "scope" returns more than one record
问题描述
我是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屋!