我有一个Review模型,该模型具有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
将生成一个新的审阅,状态为“待处理”。创建新评论时,我仍然需要验证reviewable
和user
是否与评论相关联(因此,我不能在create动作中一起跳过所有验证)...但仅用户更新评论时需要验证title
,description
和stars
。
有没有一种方法可以将三个验证(标题,说明和星号)包装成条件,以便仅在用户更新评论(将status
从pending
到submitted
)...而不是全部调用if: -> { status == "submitted" }
?
答案 0 :(得分:2)
第一个简化是,您可以使用符号代替内联块:
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
并不是一种特别知名或广泛使用的方法,它确实存在,但是我只建议在非常不寻常的情况下使用它。