In the available Ruby method name space, there are also method names, which are known from collection classes like Array or Hash. Since they are quite common, it is easy to understand the intention of such named methods quickly, especially when used in a similar context.
For example a simple bank account:
class BankAccount
def initialize attributes={}
valid_keys = %i(name amount)
@attributes = attributes.select { |key, value| valid_keys.include?(key) }
end
def add_money money
@attributes[:amount] += money
end
def attribute key
@attributes[key]
end
def set_attribute key, value
@attributes[key] = value
end
end
works like:
bank_account = BankAccount.new name: 'Chris', amount: 1000
bank_account.add_money 300 # => 1300
bank_account.set_attribute :amount, 2000 # => 2000
bank_account.attribute :name # => "Chris"
but is obviously fairly cumbersome. Especially the setter BankAccount#set_attribute looks awkward.
Fortunately the class can be refactored taking advantage of the Ruby method namespace:
class BankAccount
def initialize attributes={}
valid_keys = %i(name amount)
@attributes = attributes.select { |key, value| valid_keys.include?(key) }
end
def << money
@attributes[:amount] += money
end
def [] key
@attributes[key]
end
def []= key, value
@attributes[key] = value
end
end
Using the accessors then is way more expressive and concise:
bank_account = BankAccount.new name: 'Chris', amount: 1000
bank_account << 300 # => 1300
bank_account[:amount] = 2000 # => 2000
bank_account[:name] # => "Chris"
It is definitely worth it.