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 ...>