我想在第一次更新后为每条记录设置一个属性只读,有没有办法在使用attr_readonly的Rails 4中执行此操作?还是另一种方法?
它与交易安全有关...
答案 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
已更改,则验证将失败,并显示有用的错误消息。
我希望这有用!