如何检查实例的所有记录是否具有值列表中的多个值之一?

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"
    # ...
  1. 冗余使用 self
  2. 使用 = 设置 值,而不是 检查相等性 。 (这将通过 == 完成。)
  3. 通过像这样遍历所有 items,您将多次更新 order
  4. ...并且由于您正在执行检查 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 可能会代表您自动将值转换为布尔值 (?),但我认为无论如何使用错误的数据类型都是不好的做法。