gpt4 book ai didi

ruby-on-rails - 为什么这个方法实际上不影响 SQL 查询?

转载 作者:太空宇宙 更新时间:2023-11-03 17:25:00 25 4
gpt4 key购买 nike

我有一个方法可以根据一组条件从数据库中返回一些项目:

scope :expired_not_marked, lambda { |client|
items = where('items.status > 0 AND items.expires_at < ? AND items.expired_at IS NULL AND (winning_bid_id IS NULL OR winner_id IS NULL)', Time.now)
unless client.nil?
items.where('items.client_id = ?', client.id)
end
}

它被称为 Item.expired_not_marked nil。当我从 IRB 运行它时,我得到了很多结果,但它显示 SQL 查询被执行为:

SELECT `items`.* FROM `items` 

很明显这不是原作者的意图。因此,相同的项目被一遍又一遍地处理。

为什么这个坏了,我该如何修复它。 where 子句似乎是正确的。上述方法在item.rb模型中。

最佳答案

您的问题是您的 lambda 有时会返回 nil 并且返回 nil 的作用域不会做任何有用的事情。

lambda 将返回其最后一个表达式的值。在您的情况下,该表达式将是 unless。因此,如果 client 不是 nil,它将返回:

items.where('items.client_id = ?', client.id)

一切都会好起来的。但是,如果 client.nil? 为真,则 unless 的计算结果为 nil,您的作用域将返回 nil。我认为你最好用这样的东西:

scope :expired_not_marked, lambda { |client|
items = where('items.status > 0 AND items.expires_at < ? AND items.expired_at IS NULL AND (winning_bid_id IS NULL OR winner_id IS NULL)', Time.now)
unless client.nil?
items = items.where('items.client_id = ?', client.id)
end
items
}

这样一来,您始终拥有清晰、明确且定义明确的返回值。


ActiveRecord Query Interface Guide建议您对带参数的作用域使用类方法:

Using a class method is the preferred way to accept arguments for scopes.

所以如果 lambda 方法太嘈杂,你也可以这样做:

def self.expired_not_marked(client)
items = where('items.status > 0')
items = items.where('items.expires_at < ?', Time.now)
items = items.where('items.expired_at IS NULL')
items = items.where('winning_bid_id IS NULL OR winner_id IS NULL')
unless client.nil?
items = items.where('items.client_id = ?', client.id)
end
items
}

您当然不必使用类方法。并且您不必将查询分解为对每个组件的一堆小 where 调用,但这样可能更容易阅读。

关于ruby-on-rails - 为什么这个方法实际上不影响 SQL 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14736171/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com