我正在寻找复杂查询的解决方案。
目标:我想知道一个实例的所有记录是否都具有值,并在该实例的所有记录具有相同值时执行一些操作。
订单模型:
has_many :items
Columns : treated
项目模型:
belongs_to :order
Columns : order_id / state
种子示例:
Order.create
@item1 = Item.create(order_id: 1, state: pending)
@item2 = Item.create(order_id: 1, state: pending)
在回调操作中,在Item Model上,我已经完成:
def treatment
self.order.items.each do |item|
if item.state = "order_accepted" or item.state = "order_refused"
item.order.update_attributes(treated: "true")
end
end
end
所以我试图得到类似这样的结果:
“如果我所有的商品都具有“ order_accepted”或“ order_refused”状态,则将订单更新为“已处理”。”
请帮助! 非常感谢
答案 0 :(得分:3)
您的问题标题与描述不符。您不是要检查“所有记录是否具有相同的值”,而是要检查所有记录是否具有多个值之一(来自列表)。
您的尝试存在一些问题:
self.order.items.each do |item|
if item.state = "order_accepted" or item.state = "order_refused"
# ...
self
=
是设置值,而不是检查是否相等。 (可以通过==
完成。)items
,您可以多次更新order
。item
,而不是所有项,因此您无需检查它们是否是所有都具有所需的值。您尝试成功的最小变化是:
if order.items.all? { |item| item.state == "order_accepted" || item.state == "order_refused" }
order.update_attributes(treated: "true")
end
但是,这不是一个很好的解决方案,因为您要将所有对象都加载到内存中并遍历它们。这效率低下,尤其是在有许多items
的情况下。更好的方法是直接在SQL
中而不是在ruby
中执行检查:
if order.items.where.not(state: ["order_accepted", "order_refused"]).empty?
order.update_attribute(:treated, "true")
end
为了稍微整理一下这段代码,我将该查询定义为Item
模型上的作用域,例如:
class Item < ApplicationRecord
scope :not_completed, -> { where.not(state: ["order_accepted", "order_refused"]) }
end
然后也许也可以在Order
模型上定义一个方法:
class Order < ApplicationRecord
def complete?
items.not_completed.empty?
end
end
然后在上面的代码中,您只需编写:
def treatment
# ...
order.update_attribute(:treated, "true") if order.complete?
# ...
end
此外,我怀疑应该确实是true
而不是"true"
。 true
是布尔值; "true"
是一个字符串。为作业使用正确的数据类型。
Rails可能会自动代表您将值转换为布尔值(?),但是无论如何,使用错误的数据类型都是我的不正确做法。