I am building a Ruby object that has defaults for arguments in its initialize
method:
attr_accessor :one, :two, :three
def initialize(one: nil, two: nil, three: nil)
@one = one
@two = two
@three = three
end
As you can see, this isn't very DRY, especially as the number of initializable variables grows. Ultimately, I would like to be able to loop through each of the arguments and assign an instance variable (some combination of a splat operator and instance_variable_set
?), but always have a defined list of expected instance variables with defaults if they aren't defined.
Typically having an initialize method require a whole bunch of arguments usually leads to the use of an options hash rather than splat.
With an options hash you're able to dry up your initialize method, set instance variables and attr_readers in a very ruby way:
class Animal
def initialize(opts = {})
options = defaults.merge(opts)
options.each do |k, v|
instance_variable_set("@#{k}", v)
self.class.send(:attr_reader, k)
end
end
private
def defaults
{
type: nil,
age: 100,
name: "Unknown"
}
end
end
animal = Animal.new(type:'cat', age: 99)
puts animal
puts animal.type
puts animal.age
puts animal.name
Output:
#<Animal:0x007f9773132650>
cat
99
Unknown