在具有特定值后锁定属性

时间:2012-07-12 00:26:28

标签: ruby-on-rails

我有一个模型,如果它被赋予某种状态,则状态永远不会再被改变。我试图通过在模型上放入before_save来检查状态是什么来实现这一点,并在设置为某个状态时引发异常。

问题是这个 -

 def raise_if_exported
   if self.exported?
     raise Exception, "Can't change an exported invoice's status"
   end
 end  

工作正常,但是当我最初通过执行以下操作将状态设置为导出时 -

 invoice.status = "Exported"
 invoice.save

引发异常是因为状态已经设置为在模型上导出而不是db(我认为)

那么有没有办法阻止该属性在被设置为“已导出”后被更改?

4 个答案:

答案 0 :(得分:3)

您可以根据需要使用验证器

class Invoice < ActiveRecord::Base

  validates_each :status do |record, attr, value|
     if ( attr == :status and status_changed? and status_was == "Exported")
       record.errors.add(:status, "you can't touch this")
     end
  end

end

现在

invoice.status= "Exported"
invoice.save # success

invoice.status= "New"
invoice.save # error

答案 1 :(得分:1)

您还可以使用ActiveModel::Dirty跟踪更改,而不是检查当前状态:

def raise_if_exported
  if status_changed? && status_was == "Exported"
    raise "Can't change an exported invoice's status"
  end
end

试试这个,只有 if 你真的希望在保存时引发异常。如果没有,请在验证过程中检查它,如@Trip建议

有关详细信息,请参阅this page

答案 2 :(得分:1)

我会选择@Trip和@Sikachu的答案:

validate :check_if_exported

def check_if_exported
  if status_changed? && status_was.eql?("Exported")
    errors.add(:status, " cannot be changed once exported.")
  end
end

使模型失效是一种比仅仅抛出错误更好的响应,除非你 reeeally 想要这样做。

答案 3 :(得分:0)

在模型中尝试内置验证的Rails:

validate :check_if_exported

def check_if_exported
  if self.exported?
    errors.add(:exported_failure, "This has been exported already.")
  end
end