范围内的 find_by 正在触发 2 个查询

问题描述 投票:0回答:3

我正在使用 Rails 4.2.3 和 ruby 2.2.1

我在角色模型中编写了一个范围,如下:

应用程序/模型/role.rb

scope :default, -> { find_by(default: true) }

现在当我跑步时

> Role.default

#this is the output I got.

Role Load (0.1ms)  SELECT  `roles`.* FROM `roles` WHERE `roles`.`default` = 1 LIMIT 1 
Role Load (0.1ms)  SELECT `roles`.* FROM `roles`
=> []

如您所见,这会触发 2 个查询并返回错误的结果。

我尝试使用类方法而不是范围

def self.default
  self.find_by(default: true)
end

现在当我跑步时

Role.default

#this is the output I got

Role Load (0.2ms)  SELECT  `roles`.* FROM `roles` WHERE `roles`.`default` = 1 LIMIT 1
=> nil

使用类方法 find_by 可以正常工作。

我无法理解我在这里做错了什么。任何帮助,将不胜感激。预先感谢。

ruby-on-rails ruby-on-rails-4 activerecord
3个回答
25
投票

您不应该在范围内使用

find_by
-
find_by
实际上执行数据库查询。

您应该只使用返回更多范围的方法,例如

where
limit
order
等。


4
投票

ActiveRecord 是 Rails 中内置的对象关系映射系统,它为您提供了一组在您的范围内使用的方法来抽象数据库查询。这些方法列于此处:

http://guides.rubyonrails.org/active_record_querying.html#retriving-objects-from-the-database

在您的情况下,您将需要使用

where
查询。

scope :default, -> { where(default: true) }


0
投票

我遇到了同样的问题

一开始,我将我的范围写为

 scope :detect_by_keyword, ->(keyword) {
    find_by(normal_name: keyword)
  }

但是会查询多次DB。

作为答案https://stackoverflow.com/a/31329956/7262646提到:

您不应该在范围内使用 find_by - find_by 实际上执行数据库查询。

您应该只使用返回更多范围的方法,例如 where、limit、order 等。

它有效,但我不喜欢它

  scope :detect_by_keyword, ->(keyword) {
    where(normal_name: keyword).limit(1)
  }

我必须这样做

MyClass.detect_by_keyword(keyword).first

如果我将

.first
放在范围
where(normal_name: keyword).limit(1).first
内,即使我使用
where(normal_name: keyword)[0]

也会导致同样的问题

所以我把它变成

Class method

这是我的最终解决方案:


  def self.detect_by_keyword(keyword)
    find_by(normal_name: keyword)
  end

顺便说一句,我想说:我以前做过这个(将

find_by
放入范围`)。没有任何问题。但最近的项目做到了。我猜这是 Rails 的问题。只是猜测,但现在确定了。希望有人能给我证明。

希望对您有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.