amingilani amingilani - 7 months ago 22
Ruby Question

Rails: set a model attribute as read-only, but allow updating via method

I have an accounts model, where I would like the

balance
to be readonly, but it can be updated via private methods.

Currently

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


However, this is still possible:

account = Account.first
account.balance += 5
account.save


I would like for the above to give an error, but still be able to do:

account.balance #=> 0
account.deposit(5)
account.balance #=> 5

Answer

You may define a private setter for the attribute:

class Account < ActiveRecord::Base

  private

  def balance=(the_balance)
    write_attribute(:balance, the_balance)
  end
end

Then, you are not allowed to call it outside your Account class:

Account.new(balance: 1234)
# => ActiveRecord::UnknownAttributeError: unknown attribute 'balance' for 'Account'

Account.new.balance = 1234
# => NoMethodError: private method `balance=' called for <Account ...>
Comments