Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get attributes that were defined through attr_reader or attr_accessor

Suppose I have a class A

class A
  attr_accessor :x, :y

  def initialize(x,y)
    @x, @y = x, y
  end
end

How can I get x and y attributes without knowing how exactly they were named.

E.g.

a = A.new(5,10)
a.attributes # => [5, 10]
like image 508
user1179942 Avatar asked Apr 04 '12 07:04

user1179942


People also ask

What does Attr_reader mean in Ruby?

Summary. attr_reader and attr_writer in Ruby allow us to access and modify instance variables using the . notation by creating getter and setter methods automatically. These methods allow us to access instance variables from outside the scope of the class definition.

What does Attr_accessor mean in Ruby?

In Ruby, object methods are public by default, while data is private. To access and modify data, we use the attr_reader and attr_writer . attr_accessor is a shortcut method when you need both attr_reader and attr_writer .

What is Attr_accessor?

attr_accessor is used to define an attribute for object of Model which is not mapped with any column in database.

What does ATTR reader do?

An attribute reader returns the value of an instance variable. Another way of looking at this is that an attribute reader is a method that “exposes” an instance variable. It makes it accessible for others.


3 Answers

Use introspection, Luke!

class A
  attr_accessor :x, :y

  def initialize(*args)
    @x, @y = args
  end

  def attrs
    instance_variables.map{|ivar| instance_variable_get ivar}
  end
end

a = A.new(5,10)
a.x # => 5
a.y # => 10
a.attrs # => [5, 10]
like image 119
Sergio Tulentsev Avatar answered Oct 20 '22 07:10

Sergio Tulentsev


While Sergio's answer helps, it will return all the instance variables, which if I understand correctly the OP's question, is not what is asked.

If you want to return only the 'attributes' that have e.g. a mutator, you have to do something slightly more complicated such as:

attrs = Hash.new
instance_variables.each do |var|
  str = var.to_s.gsub /^@/, ''
  if respond_to? "#{str}="
    attrs[str.to_sym] = instance_variable_get var
  end
end
attrs

This returns only the attributes declared with attr_accessor (or with a manually created mutator), and keep the internal instance variables hidden. You can do something similar if you want the ones declared with attr_reader.

like image 27
Nicolas Bonnefon Avatar answered Oct 20 '22 07:10

Nicolas Bonnefon


class A
  ATTRIBUTES = [:x, :y]
  attr_accessor *ATTRIBUTES

  def initialize(x,y)
    @x, @y = x, y
  end

  def attributes
    ATTRIBUTES.map{|attribute| self.send(attribute) }
  end
end

This may not be the DRY-est, but if you are only concerned with doing this for one class (as opposed to a base class that everything inherits from), then this should work.

like image 25
marksiemers Avatar answered Oct 20 '22 07:10

marksiemers