如何检查实例的所有记录是否具有值列表中的多个值之一?
How to check if all records of an instance have one of many values from a list of values?
我正在寻找复杂查询的解决方案。
目标:我想知道一个实例的所有记录是否都有值,当实例的所有记录都具有相同的值时做一些动作。
订购型号:
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)
在项目模型上的回调操作中,我已经完成了:
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
所以我想得到这样的结果:
"If all my Items have the states "order_accepted" 或 "order_refused",然后将订单更新为 'treated'。"
请帮忙!
非常感谢
您的问题标题与描述不符。您不是在检查是否 "all records have the same value",而是在检查所有记录是否具有 多个值之一 (来自列表)。
您的尝试存在一些问题:
self.order.items.each do |item|
if item.state = "order_accepted" or item.state = "order_refused"
# ...
- 冗余使用
self
- 使用
=
是 设置 值,而不是 检查相等性 。 (这将通过 ==
完成。)
- 通过像这样遍历所有
items
,您将多次更新 order
。
- ...并且由于您正在执行检查 each
item
,而不是 all 项,您我没有检查它们 所有 是否具有所需的值。
对您的尝试进行 工作 的最小更改是:
if order.items.all? { |item| item.state == "order_accepted" || item.state == "order_refused" }
order.update_attributes(treated: "true")
end
但是,这不是一个很好的解决方案,因为您要将所有 objects 加载到内存中并循环遍历它们。这是低效的,尤其是在有很多 items
的情况下。更好的方法是直接在 SQL
中而不是在 ruby
:
中执行检查
if order.items.where.not(state: ["order_accepted", "order_refused"]).empty?
order.update_attribute(:treated, "true")
end
为了稍微整理一下这段代码,我将该查询定义为 Item
模型上的 scope,例如:
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 可能会代表您自动将值转换为布尔值 (?),但我认为无论如何使用错误的数据类型都是不好的做法。
我正在寻找复杂查询的解决方案。
目标:我想知道一个实例的所有记录是否都有值,当实例的所有记录都具有相同的值时做一些动作。
订购型号:
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)
在项目模型上的回调操作中,我已经完成了:
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
所以我想得到这样的结果:
"If all my Items have the states "order_accepted" 或 "order_refused",然后将订单更新为 'treated'。"
请帮忙! 非常感谢
您的问题标题与描述不符。您不是在检查是否 "all records have the same value",而是在检查所有记录是否具有 多个值之一 (来自列表)。
您的尝试存在一些问题:
self.order.items.each do |item|
if item.state = "order_accepted" or item.state = "order_refused"
# ...
- 冗余使用
self
- 使用
=
是 设置 值,而不是 检查相等性 。 (这将通过==
完成。) - 通过像这样遍历所有
items
,您将多次更新order
。 - ...并且由于您正在执行检查 each
item
,而不是 all 项,您我没有检查它们 所有 是否具有所需的值。
对您的尝试进行 工作 的最小更改是:
if order.items.all? { |item| item.state == "order_accepted" || item.state == "order_refused" }
order.update_attributes(treated: "true")
end
但是,这不是一个很好的解决方案,因为您要将所有 objects 加载到内存中并循环遍历它们。这是低效的,尤其是在有很多 items
的情况下。更好的方法是直接在 SQL
中而不是在 ruby
:
if order.items.where.not(state: ["order_accepted", "order_refused"]).empty?
order.update_attribute(:treated, "true")
end
为了稍微整理一下这段代码,我将该查询定义为 Item
模型上的 scope,例如:
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 可能会代表您自动将值转换为布尔值 (?),但我认为无论如何使用错误的数据类型都是不好的做法。