1 ################################################################################
2 # A financial account from which and to which transactions are made.
4 # _Account_ objects are both flyweights and a flyweight factory. Since there
5 # is only one kind of flyweight, there is no need to increase complexity with
7 ################################################################################
9 attr_reader :balance, :parent, :children
11 # Initializes a new _Account_ object given the account's full path in the
12 # accounts hierarchy, from the top-most parent to the account's name.
14 # +auto_repair_account = Account.new *['Expenses', 'Auto', 'Repair']
15 # groceries_account = Account.new(*'Expenses.Groceries'.split('.'))+
16 def initialize(name, parent)
23 # Returns the terminal name of this account.
25 # +account = Account.new(*'Income.Bursaries.Government'.split('.'))
26 # account.name => 'Government'+
31 # The string representation of the account.
33 # +account = AccountRegister.new.open('Income', 'Bursaries', 'Uncle Joe')
34 # account.to_s => 'Income.Bursaries.Uncle Joe'
36 return @name if @parent.nil?
37 @parent.to_s + '.' + @name
44 # Returns this account's depth in the accounts' hierarchy. A depth of 0 means
45 # this account is a root account.
47 return 0 if @parent.nil?
51 # Invoke block on each of the account's parents.
53 # account = Account.new(*['Expenses', 'Groceries'])
54 # account.each_parent { |parent| puts parent } => Expenses
56 # account.each_parent { |parent| puts parent } => Expenses
58 def each_parent(&block)
59 return if @parent.nil?
61 @parent.each_parent(&block)
64 # Test for equal id of this _Transaction_ against another.
69 # Check whether this object's class is the same as that of the given parameter
70 # and that this transaction's id is the same as that of the given parameter.
72 self.class.eql?(other.class) and to_s.eql?(other.to_s)
76 # the hash method is called by functions such as Array.uniq. We consider
77 # a Transaction's identity by looking at its id.
86 # Set a new value for this account's balance, and update this accont's parents'
88 def balance=(new_balance)
89 difference = new_balance - @balance
90 @balance += difference
91 @parent.balance += difference unless @parent.nil?
94 # Get the path to the account, from the root parent to the account's literal
97 # The path is an array. For example,
99 # +account = AccountRegister.open(*%w[Income Salary])
100 # account.path => ["Income", "Salary"]+