ruby 引用联接Rails表中枚举的查询

mfuanj7w  于 2023-10-18  发布在  Ruby
关注(0)|答案(3)|浏览(135)

请考虑下面的域模型的简化表示。

class Item < ApplicationRecord
  has_many :tags
end

class Tag < ApplicationRecord
  belongs_to :item
  enum :value, %i{hot cold}

  validates :value, uniqueness: { scope: :item_id }
end

每个项目都有零个或多个标记,这些标记指示与我的程序相关的项目的属性。在此示例中,“热”和“冷”是唯一有效的标签。
如果我想找到所有被标记为“热门”的项目,我可以这样写

Item.joins(:tags).where('tags.value = 0')

当然,我更喜欢写单词“hot”而不是枚举的整数值。我可以用一个命名的参数来强制ActiveRecord。

Item.joins(:tags).where('tags.value': 'hot')

但是有一个名称不是有效的Ruby标识符的命名参数感觉有点...有没有更简洁的方法来进行这个查询,不涉及这样一个奇怪的伪变量?

5lwkijsr

5lwkijsr1#

这感觉好点了吗:

Item.joins(:tags).where(tags: {value: :hot})

class Item < ApplicationRecord
  has_many :tags

  scope :tagged, ->(value) { joins(:tags).where(tags: {value:}) }
end

Item.tagged(:hot)
t0ybt7op

t0ybt7op2#

首先,问题中的代码是错误的。如果项目有许多标记,则需要使用此关联名称。joins(:tags),不是joins(:tag)。否则将引发错误
对于where中的连接表,通常使用hash方法。Key是表名,value是带有必要参数的散列

Item.joins(:tags).where(tags: { value: 'hot' })
rryofs0p

rryofs0p3#

是的,您可以利用enum声明来编写一个更加惯用的查询,该查询利用枚举值的符号名称。在这种特殊情况下,由于您已经在Tag模型中定义了valueenum,因此可以利用ActiveRecord的查询接口来构造更简洁的查询:

Item.joins(:tags).where(tags: { value: Tag.values[:hot] })

这段代码将利用ActiveRecord中为枚举自动定义的values方法,提供一个哈希,将枚举值的符号名称Map到它们的底层整数表示。在这里,Tag.values[:hot]将返回与枚举中的:hot符号对应的整数值,结果查询将找到所有标记有该值的项。

相关问题