Rails: 将模型属性设置为只读,但允许通过方法更新
Rails: set a model attribute as read-only, but allow updating via method
我有一个帐户模型,我希望 balance
是只读的,但它可以通过私有方法更新。
目前
class Account < ActiveRecord::Base
def deposit(amount)
# do some stuff and then
update_balance(amount)
end
private
def update_balance(amount)
self.balance += amount
end
end
但是,这仍然是可能的:
account = Account.first
account.balance += 5
account.save
我想上面给出一个错误,但仍然可以做到:
account.balance #=> 0
account.deposit(5)
account.balance #=> 5
ActiveRecord
不仅railsgem。这是一个常用的 pattern,这意味着您的数据库在您的对象中的镜像表示。因此,您模型中的所有数据访问方法都可以使用 ruby 元编程机制自动定义。
也许最好让您的逻辑保持清晰和方便并编写 class AccountManager
,它将在 Account
之上运行并且可以为您提供您需要的隔离:
class AccountManager
def initialize(account)
@account = account
end
def deposit(amount)
# do some stuff and then
update_balance(amount)
end
private
def update_balance(amount)
@account.balance += amount
end
end
您可以为属性定义私有 setter:
class Account < ActiveRecord::Base
private
def balance=(the_balance)
write_attribute(:balance, the_balance)
end
end
然后,你不能在你的 Account
之外调用它 class:
Account.new(balance: 1234)
# => ActiveRecord::UnknownAttributeError: unknown attribute 'balance' for 'Account'
Account.new.balance = 1234
# => NoMethodError: private method `balance=' called for <Account ...>
我有一个帐户模型,我希望 balance
是只读的,但它可以通过私有方法更新。
目前
class Account < ActiveRecord::Base
def deposit(amount)
# do some stuff and then
update_balance(amount)
end
private
def update_balance(amount)
self.balance += amount
end
end
但是,这仍然是可能的:
account = Account.first
account.balance += 5
account.save
我想上面给出一个错误,但仍然可以做到:
account.balance #=> 0
account.deposit(5)
account.balance #=> 5
ActiveRecord
不仅railsgem。这是一个常用的 pattern,这意味着您的数据库在您的对象中的镜像表示。因此,您模型中的所有数据访问方法都可以使用 ruby 元编程机制自动定义。
也许最好让您的逻辑保持清晰和方便并编写 class AccountManager
,它将在 Account
之上运行并且可以为您提供您需要的隔离:
class AccountManager
def initialize(account)
@account = account
end
def deposit(amount)
# do some stuff and then
update_balance(amount)
end
private
def update_balance(amount)
@account.balance += amount
end
end
您可以为属性定义私有 setter:
class Account < ActiveRecord::Base
private
def balance=(the_balance)
write_attribute(:balance, the_balance)
end
end
然后,你不能在你的 Account
之外调用它 class:
Account.new(balance: 1234)
# => ActiveRecord::UnknownAttributeError: unknown attribute 'balance' for 'Account'
Account.new.balance = 1234
# => NoMethodError: private method `balance=' called for <Account ...>