roscioli
roscioli

Reputation: 1230

Can I refer to an object's attribute by string in Ruby?

If I have a ruby class called Node:

class Node
  attr_accessor :a, :b, :c
  attr_reader :key
  def initialize(key)
    @key = key
  end
  def [](letter)
    if letter == 'a'
      return self.a
    elsif letter == 'b'
      return self.b
    elsif letter == 'c'
      return self.c
    end
  end
end

How can I optimize def [](letter) so I won't have repetitive code? More specifically, how can I access an attribute of an object (that is a ruby symbol :a, :b, or :c) by using a corresponding string?

Upvotes: 0

Views: 88

Answers (1)

coreyward
coreyward

Reputation: 80041

You can use send, which invokes a method dynamically on the caller, in this case self:

class Node
  def [](key)
    key = key.to_sym
    send(key) if respond_to?(key)
  end
end

Note that we check that self has the appropriate method before calling it. This avoids getting a NoMethodError and instead results in node_instance[:banana] returning nil, which is appropriate given the interface.

By the way, if this is the majority of the behavior of your Node class, you may simply want to use an OpenStruct:

require 'ostruct'
node_instance = OpenStruct.new(a: 'Apple', b: 'Banana')
node_instance.a    #=> 'Apple'
node_instance['b'] #=> 'Banana'
node_instance.c = 'Chocolate'
node_instance[:c]  #=> 'Chocolate'

Upvotes: 2

Related Questions