# How to iterate through instance attribute names (attr\_accessor)

**URL:** <https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041>\
**Category:** Ruby\
**Created:** [March 15, 2008, 8:05pm UTC](https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041 "2008-03-15T20:05:29Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mememe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mememe](https://www.ruby-forum.com/u/mememe)\
**Post date:** [March 15, 2008, 8:05pm UTC](https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041/1 "2008-03-15T20:05:29Z")

</div>

Say, I have a class:

class Event  
attr\_accessor :a,  
:b,  
:c,  
:d

def initialize()  
end

def validate  
# validate all attributes at once here  
end

protected

def validate\_a  
# a can be any number from 1-10 if b = ‘Y’ and c is blank  
end

def validate\_b  
# b can be ‘Y’ or ‘N’  
end

def validate\_c  
end

def validate\_d  
end

end

And in method validate, I’d like to iterate through all the attributes  
and run their respective validating method. Is there a way for me to  
be able to iterate through my list of attr\_accessor symbols and  
reference their names to know which method to call?

Thanks,

-Al

---

<div class="post-metadata">

**Author:** ![mememe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mememe](https://www.ruby-forum.com/u/mememe)\
**Post date:** [March 15, 2008, 8:30pm UTC](https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041/2 "2008-03-15T20:30:20Z")

</div>

On Saturday 15 March 2008, me wrote:

> end
> 
> end
> 
> And in method validate, I’d like to iterate through all the attributes  
> and run their respective validating method. Is there a way for me to  
> be able to iterate through my list of attr\_accessor symbols and  
> reference their names to know which method to call?
> 
> Thanks,
> 
> -Al

You must understand that all attr\_accessor does is create a couple of  
methods:  
a setter and a getter. For example

attr\_accessor :a

creates the two methods a and a=, which are more or less equivalent to  
the  
following hand-written methods:

def a  
@a  
end

def a= value  
@a = value  
end

Once defined, the methods created by attr\_accessor can’t be  
distinguished from  
the other instance methods of the class. This means that you can’t  
iterate on  
the methods themselves. What you can do is iterate on the instance  
variables  
methods created this way refer to. For example, your ‘validate’ method  
could  
be something like:

def validate  
instance\_variables.each{|v| send “validate\_#{v.sub(’@’,’’)}”}  
end

instance\_variables is a method which returns an array with the names of  
all  
the instance variables of the object. The method send, instead, calls  
the  
method with the name passed as its first argument (in this case,  
‘validate\_a’,  
‘validate\_b’ and so on. v.sub is needed because the names of the  
instance  
variables contain the initial ‘@’).

The code above works provided there’s a validate\_ method for each  
instance  
variable. If this is not the case, you can enclose the call to send in a  
begin/rescue block:

def validate  
instance\_variables.each do |v|  
begin send “validate\_#{v.sub(’@’,’’)}”  
rescue NoMethodError  
end  
end  
end

Of course, you can also keep an array of the names of those instance  
variables  
for which a validation method exists and use the following code:

def validate  
[:a, :b, :c, :d].each{|v| send “validate\_#{v}”}  
end

I hope this helps

Stefano

---

<div class="post-metadata">

**Author:** ![mememe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mememe](https://www.ruby-forum.com/u/mememe)\
**Post date:** [March 15, 2008, 8:38pm UTC](https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041/3 "2008-03-15T20:38:51Z")

</div>

me wrote:

> And in method validate, I’d like to iterate through all the attributes  
> and run their respective validating method. Is there a way for me to  
> be able to iterate through my list of attr\_accessor symbols and  
> reference their names to know which method to call?

If you just want to run the validates for the variables specified in the  
“attr\_accessor” methods and not for other instance variables, then you  
could do something like this:

class Event  
@@attributes = [:a, :b, :c, :d]  
@@attributes.each {|attr| attr\_accessor attr}

def validate  
@@attributes.each {|attr| send “validate\_#{attr.to\_s}” }  
end

---

<div class="post-metadata">

**Author:** ![mememe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mememe](https://www.ruby-forum.com/u/mememe)\
**Post date:** [March 15, 2008, 9:05pm UTC](https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041/4 "2008-03-15T21:05:43Z")

</div>

On Mar 15, 2:38 pm, Mark B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> end

This is also very helpful. Thanks for the swift responses!

---

<div class="post-metadata">

**Author:** ![mememe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mememe](https://www.ruby-forum.com/u/mememe)\
**Post date:** [March 15, 2008, 9:01pm UTC](https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041/5 "2008-03-15T21:01:00Z")

</div>

> I hope this helps

Yes, it does greatly! Thanks!

---

<div class="post-metadata">

**Author:** ![mememe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mememe](https://www.ruby-forum.com/u/mememe)\
**Post date:** [March 15, 2008, 9:36pm UTC](https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041/6 "2008-03-15T21:36:22Z")

</div>

Le 15 mars 2008 à 20:21, Stefano C. a écrit :

> Of course, you can also keep an array of the names of those instance variables  
> for which a validation method exists and use the following code:
> 
> def validate  
> [:a, :b, :c, :d].each{|v| send “validate\_#{v}”}  
> end

You can metaprogram your way around it too. Full example (that can  
surely be improved) :

module Kernel  
def attr\_with\_validation(\*atts)  
unless method\_defined? :validate  
class\_eval \<\<-\_EOE  
@\_validations = []  
def self.validations  
@_validations  
end  
def validate  
self.class.validations.each do |v|  
self.send("validate_#{v}")  
end  
end  
\_EOE  
end  
atts.each do |att|  
class\_eval \<\<-\_EOE  
@\_validations \<\< :#{att}  
def #{att}  
@#{att}  
end  
def #{att}=(v)  
@#{att} = v  
end  
\_EOE  
end  
end  
end

class Toto  
attr\_with\_validation :a, :b  
attr\_with\_validation :c

def validate\_a() ; raise if @a.nil? ; end  
def validate\_b() ; raise if @b.nil? ; end  
def validate\_c() ; raise if @c.nil? ; end

def initialize(a)  
@a = a  
end  
end

t = Toto.new(“I’m a”)  
t.b = “Hoy b”

puts t.a  
puts t.b

t.validate

Result is :

I’m a  
Hoy b  
./validate.rb:38:in `validate_c': unhandled exception from (eval):7:in`send’  
from (eval):7:in `validate' from (eval):6:in`each’  
from (eval):6:in `validate’  
from ./validate.rb:51

---

<div class="post-metadata">

**Author:** ![mememe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mememe](https://www.ruby-forum.com/u/mememe)\
**Post date:** [March 16, 2008, 6:35am UTC](https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041/7 "2008-03-16T06:35:49Z")

</div>

On Mar 15, 2:38 pm, Mark B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> class Event  
> @@attributes = [:a, :b, :c, :d]

> @@attributes.each {|attr| attr\_accessor attr}

This line can also be written as:  
attr\_accessor \*@@attributes

---

<div class="post-metadata">

**Author:** ![mememe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mememe](https://www.ruby-forum.com/u/mememe)\
**Post date:** [March 16, 2008, 2:01am UTC](https://www.ruby-forum.com/t/how-to-iterate-through-instance-attribute-names-attr-accessor/132041/8 "2008-03-16T02:01:35Z")

</div>

On Mar 15, 2008, at 1:04 PM, me wrote:

> def validate
> 
> # validate all attributes at once here
> 
> end

# gem install fattr

# [http://codeforpeople.com/lib/ruby/fattr/fattr-1.0.3/README](http://codeforpeople.com/lib/ruby/fattr/fattr-1.0.3/README)

require ‘rubygems’  
require ‘fattr’

class Event

fattrs :a, :b, :c, :d

def initialize  
fattrs.each do |fattr|  
name, value = fattr, send(fattr)  
validate name, value  
end

def validate name, value  
case name  
…

also see the traits lib, more heavyweight than fatter, but also  
included built-in validations

[http://codeforpeople.com/lib/ruby/traits/traits-0.9.2/README](http://codeforpeople.com/lib/ruby/traits/traits-0.9.2/README)

regards.

a @ [http://codeforpeople.com/](http://codeforpeople.com/)
