Rails 4 attr_readonly更新

时间:2014-08-29 17:16:23

标签: ruby-on-rails activerecord readonly

我想在第一次更新后为每条记录设置一个属性只读,有没有办法在使用attr_readonly的Rails 4中执行此操作?还是另一种方法?

它与交易安全有关...

1 个答案:

答案 0 :(得分:3)

attr_readonly是一种类方法,所以它会"冻结"模型的所有实例上的属性,无论它们是否已更新。

我认为,执行所需操作的最佳方法是在模型中添加some_attribute_is_frozen布尔属性,然后在true回调中将其设置为before_update。然后,您可以进行仅在some_attribute_is_frozen?true时才会运行的验证,如果"冻结"属性已经改变。

这样的事情(为了一个例子,我任意选择"客户"作为模型的名称,address作为你想要的属性的名称& #34;冻结&#34):

# $ rails generate migration AddAddressIsFrozenToCustomers
# => db/migrate/2014XXXX_add_address_is_frozen_to_customers.rb
class AddAddressIsFrozenToCustomers < ActiveRecord::Migration
  def change
    add_column :customers, :address_is_frozen, :boolean,
      null: false, default: false
  end
end
# app/models/customer.rb
class Customer < ActiveRecord::Base
  before_update :mark_address_as_frozen  
  validate :frozen_address_cannot_be_changed, if: :address_is_frozen?

  # ...snip...

  private
  def mark_address_as_frozen
    self.address_is_frozen = true
  end

  def frozen_address_cannot_be_changed
    return unless address_changed?
    errors.add :address, "is frozen and cannot be changed"
  end
end

the before_update callback runs after validation以来,第一次更新记录时,address_is_frozen?将返回false,系统会跳过验证。但是,在下一次更新时,address_is_frozen?将返回true,因此验证将会运行,如果address已更改,则验证将失败,并显示有用的错误消息。

我希望这有用!