You could use the double splat operator ** in conjunction with logical or (double pipes) || inside the initialize method to achieve the same effect.
class Person
def initialize(**options)
@name = options[:name] || options[:first_name] << ' ' << options[:last_name]
end
end
james = Person.new(name: 'James')
#=> #<Person @name="James">
jill_masterson = Person.new(first_name: 'Jill', last_name: 'Masterson')
#=> #<Person @name="Jill Masterson">
However, if a new Person is created without a first_name, then the append << operation will fail with NoMethodError: undefined method '<<' for nil:NilClass. Here is a refactored initialize method to handle this case (using strip to remove whitespace if either option is excluded).
class Person
def initialize(**options)
@name = options[:name] || [ options[:first_name] , options[:last_name] ].join(' ').strip
end
end
goldfinger = Person.new(last_name: 'Goldfinger')
#=> #<Person @name="Goldfinger">
oddjob = Person.new(first_name: 'Oddjob')
#=> #<Person @name="Oddjob">
In fact, this approach handles calling Person.new without arguments or with an unexpected key to return the new instance with @name set to an empty string:
nameless = Person.new
#=> <#Person @name="">
middle_malcom = Person.new(middle_name: 'Malcom')
#=> <#Person @name="">