Ruby: idiomatic code

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 init.

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)

Leave a Reply

Your email address will not be published. Required fields are marked *