【发布时间】:2019-09-13 23:40:04
【问题描述】:
我有一个带有“产品变体”表单的 Rails 项目。产品变体模型称为Variant,在Variant 表单上,用户应该能够为每个可用选项选择一个选项。例如,一件 T 恤可能有一个名为“尺寸”的“选项”,其中“选择”为小、中或大,另一个“选项”名为“颜色”,“选择”为红色、绿色、蓝色。因此,创建的Variant 是一个独特的 SKU,例如“T 恤 — 尺寸:小号,颜色:绿色”。或者,如果产品有 3 个选项而不是 2 个选项,则该变体将需要每个选项 3 个选项,例如“吉他背带 - 尺寸:长款,面料颜色:红色,皮革颜色:棕色”。
我不知道如何编写只允许用户为每个选项保存一个选项的自定义验证。每个选项应该只为每个变体选择一个选项。这是一个插图。
这是我的模型与相关的关联...
models/variant.rb
class Variant < ApplicationRecord
has_many :selections
has_many :choices, through: :selections
validate :one_choice_per_option
private
def one_choice_per_option
# can't figure out how to do this custom validation here
end
end
models/choice.rb
class Choice < ApplicationRecord
has_many :variants, through: :selections
belongs_to :option
end
models/selection.rb
class Selection < ApplicationRecord
belongs_to :choice
belongs_to :variant
end
models/option.rb
class Option < ApplicationRecord
has_many :choices, dependent: :destroy
accepts_nested_attributes_for :choices, allow_destroy: true
end
我设法做的最好的事情是在models/variant.rb 中进行此自定义验证
def one_choice_per_option
self.product.options.each do |option|
if option.choices.count > 1
errors.add(:choice, 'Error: select one choice for each option')
end
end
end
但这只允许一个Choice 总数通过变体形式。我想要做的是让每组选项都有一个选择。
我知道这可以在 UI 中使用 Javascript 来完成,但这对于保持数据库清洁和防止用户错误至关重要,所以我认为它应该是模型级别的 Rails 验证。
进行此类自定义验证的“Railsy”方式是什么?我应该尝试对Selection 模型进行自定义验证吗?如果有,怎么做?
更新
基于 cmets 中的讨论。看来我需要结合Active Record querying 来完成这项工作。 @sevensidemarble 下面的“EDIT 2”更接近,但这给了我这个错误:Type Error compared with non class/module
如果我将错误的行为保存到数据库中,然后在控制台中调用Variant.last.choices,那感觉就像我越来越接近了:
所以本质上,如果有多个Selection 具有相同的option_id,我需要做的是不允许保存Variant 表单。除非option_id 对关联的Variant 是唯一的,否则不应保存选择。
我正在尝试做这样的事情:
validate :selections_must_have_unique_option
private
def selections_must_have_unique_option
unless self.choices.distinct(:option_id)
errors.add(:options, 'can only have one choice per option')
end
end
但该代码不起作用。它只是保存表单,就好像验证不存在一样。
【问题讨论】:
-
您的第一个答案本身对我来说似乎没问题。我只是不确定这里的关系。您是否定义了 variant-belongs_to-product、product-has_many-options 关系?如果不是,请告诉我们这里的关系层次结构,因为我在“产品”模型方面感到困惑。
标签: ruby-on-rails forms validation activerecord simple-form