满足特定条件时仅 运行 一组验证的最佳实践?
Best practice for only running a group of validations when a certain condition is met?
我有一个包含 3 个验证的评论模型,如果评论的 status
是 "submitted"
,则应该只 运行。这是我目前的模型...
class Review < ApplicationRecord
enum status: { pending: 0, submitted: 1 }
...
belongs_to :reviewable, polymorphic: true
belongs_to :user
validates :title, presence: true, length: { in: 5..50 }, if: -> { status == "submitted" }
validates :description, length: { in: 10..500 }, if: -> { status == "submitted" }
validates :stars, presence: true, inclusion: { in: (1..5) }, if: -> { status == "submitted" }
...
end
已生成状态为 "pending" 的新评论。我仍然需要在创建新评论时验证 reviewable
和 user
是否与评论相关联(因此,我不能在创建操作中一起跳过验证)...但仅需要在用户更新评论时验证 title
、description
和 stars
。
有没有办法将三个验证(标题、描述和星级)包装在一个条件中,以便它只 运行 在用户更新评论时进行验证(这会改变status
从 pending
到 submitted
)...而不是对所有这些都调用 if: -> { status == "submitted" }
?
第一个简化是您可以使用符号而不是内联块:
validates :title, presence: true, length: { in: 5..50 }, if: :submitted?
validates :description, length: { in: 10..500 }, if: :submitted?
validates :stars, presence: true, inclusion: { in: (1..5) }, if: :submitted?
一般来说,你会定义一个方法来匹配:
def submitted?
status == "submitted"
end
..但是你不需要在这里,因为enum
免费给你这样的方法
如果真的要挤,还有一个更隐晦的选择:
with_options if: -> { status == "submitted" } do |x|
x.validates :title, presence: true, length: { in: 5..50 }
x.validates :description, length: { in: 10..500 }
x.validates :stars, presence: true, inclusion: { in: (1..5) }
end
(我切换回块,因为只有一个副本,但在这种情况下我仍然喜欢 if: :submitted?
形式。)
with_options
不是特别知名或广泛使用的方法 -- 它在那里,但我只建议在非常不寻常的情况下使用它。
我有一个包含 3 个验证的评论模型,如果评论的 status
是 "submitted"
,则应该只 运行。这是我目前的模型...
class Review < ApplicationRecord
enum status: { pending: 0, submitted: 1 }
...
belongs_to :reviewable, polymorphic: true
belongs_to :user
validates :title, presence: true, length: { in: 5..50 }, if: -> { status == "submitted" }
validates :description, length: { in: 10..500 }, if: -> { status == "submitted" }
validates :stars, presence: true, inclusion: { in: (1..5) }, if: -> { status == "submitted" }
...
end
已生成状态为 "pending" 的新评论。我仍然需要在创建新评论时验证 reviewable
和 user
是否与评论相关联(因此,我不能在创建操作中一起跳过验证)...但仅需要在用户更新评论时验证 title
、description
和 stars
。
有没有办法将三个验证(标题、描述和星级)包装在一个条件中,以便它只 运行 在用户更新评论时进行验证(这会改变status
从 pending
到 submitted
)...而不是对所有这些都调用 if: -> { status == "submitted" }
?
第一个简化是您可以使用符号而不是内联块:
validates :title, presence: true, length: { in: 5..50 }, if: :submitted?
validates :description, length: { in: 10..500 }, if: :submitted?
validates :stars, presence: true, inclusion: { in: (1..5) }, if: :submitted?
一般来说,你会定义一个方法来匹配:
def submitted?
status == "submitted"
end
..但是你不需要在这里,因为enum
免费给你这样的方法
如果真的要挤,还有一个更隐晦的选择:
with_options if: -> { status == "submitted" } do |x|
x.validates :title, presence: true, length: { in: 5..50 }
x.validates :description, length: { in: 10..500 }
x.validates :stars, presence: true, inclusion: { in: (1..5) }
end
(我切换回块,因为只有一个副本,但在这种情况下我仍然喜欢 if: :submitted?
形式。)
with_options
不是特别知名或广泛使用的方法 -- 它在那里,但我只建议在非常不寻常的情况下使用它。