Here’s an example of making some not-particularly idiomatic Ruby code into something that’s a little more “Ruby’ish”:
Non-idiomatic code:
class Person
attr_accessor :id, :name
def initialize(init)
init.each_pair do |key, val|
instance_variable_set(‘@’ + key.to_s, val)
end
end
end
@adam = Person.new(:id => 1, :name => “Adam”)
@eve = Person.new(:id => 2)
@people = [ @adam, @eve, nil ]
print @people
puts
@people.map! do |person|
person ||= Person.new(:id => 3, :name => “Some default”)
if person.name.nil?
person.name = “Eve”
end
person
end
print @people
And the idiomatic version:
class Person
attr_accessor :id, :name
def initialize(init = {})
init.each do |k, v|
send(“#{k}=”, v)
end
end
end
people = [
Person.new(:id => 1, :name => “Adam”),
Person.new(:id => 2),
nil,
]
print people
puts
people.map! do |person|
person ||= Person.new(:id => 3, :name => “Some default”)
person.name ||= ‘Eve’
person
end
print people
Notes:
1. we’re initialising init to an empty hash here:
def initialize(init = {})
2. ‘send’ invokes the method identified by the symbol passing it any arguments specified.
http://ruby-doc.org/core-2.0/Object.html#method-i-send
Here it is called on self which is an instance of Person.
3. people is created with Person.new code inline
4. we can save 2 lines of code by using the same ||= operator for Eve
All in all, a lot tidier.
For more on the send method, see this post:
http://stackoverflow.com/questions/12892045/send-method-in-ruby
which explains this, initially obtuse, code:
x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)