我有一个名为lifecycle_id的表,另一个名为lifecycle_change_reason。 lifeycle_id通常由系统根据其他因素自动更改,但某些用户可以手动更改生命周期。如果他们这样做,我想要求他们提供改变的理由,但我不想在任何其他时间要求该字段。有没有人建议我如何进行这种验证?
thx:)
-C
答案 0 :(得分:0)
我可以看到几种不同的方式。我认为最好的方法是在表格中添加另一个名为lifecycle_id_original
的字段。然后你的模型会包含这样的代码:
class Member < ActiveRecord::Base
belongs_to :lifecycle
validates :lifecycle_change_reason, :if => :lifecycle_changed?
before_save :reset_original_lifecycle
protected
def lifecycle_changed?
self.life_cycle_id != self.lifecycle_id_original && !self.lifecycle_id_original.nil?
end
def reset_original_lifecycle
self.lifecycle_id_original = self.lifecycle_id
end
end
当验证对象(此示例中的成员)时,仅当original和lifecycle_id不相同时才需要lifecycle_change_reason。原始版本也允许使用nil值,因为这是新创建记录时的内容。
然后保存时,“original”设置为与lifecycle_id匹配,因此下一个更新周期将正常工作。
这不像我想的那么干净。我的第一个想法是使用attr_accessor
,因此副本不会一直存储在数据库中,但这意味着每次加载记录时都要设置该值。我不知道ActiveRecord模型的任何on_load样式回调。
答案 1 :(得分:-1)
这似乎是控制器的用途。我意识到人们希望将逻辑推送到模型,并且有充分的理由,但是让我们在这里务实:如果您的系统自动更改此值,并且您的系统中只有一个点可以手动更改它,那么在我看来,并没有引入所有那么多的复杂性来简单地在控制器中强制存在一个理由,例如:
if params[:object_name][:life_cycle_id] != @object.life_cycle_id && params[:object_name][:life_cycle_change_reason].blank?
flash[:error] = "You must enter a reason for changing the life cycle."
redirect_to :back and return false # or whatever
end