# Creating object from hash

**URL:** <https://www.ruby-forum.com/t/creating-object-from-hash/152727>\
**Category:** Ruby\
**Created:** [November 6, 2008, 9:46pm UTC](https://www.ruby-forum.com/t/creating-object-from-hash/152727 "2008-11-06T21:46:01Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![dmjb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/898d66/32.png) [@dmjb](https://www.ruby-forum.com/u/dmjb)\
**Post date:** [November 6, 2008, 9:46pm UTC](https://www.ruby-forum.com/t/creating-object-from-hash/152727/1 "2008-11-06T21:46:01Z")

</div>

I’m creating an object from a hash using this:

class Computer  
def initialize(hash)  
hash.each do |k,v|  
instance\_variable\_set("@#{k}", v) ## create and initialize an  
instance variable for this key/value pair  
instance\_eval %Q{ class \<\< self ; attr\_reader #{k.intern.inspect}  
; end }  
end  
end  
end

This works fine except if I need to define a method with the same name  
of a key (if I need an complicated getter/setter for example). So I  
added a test to attr\_reader line:  
instance\_eval %Q{ class \<\< self ; attr\_reader #{k.intern.inspect} ; end  
} if !instance\_eval %Q{defined? #{k}}

As an Object, some methods are defined (like “id”). So “pc =  
Computer.new({‘id’ \> 1})” does not create the reader for @id and “pc.id”  
calls some unwanted method.

If I just add “attr\_reader :id” everything works. Can I do it directly,  
without adding attr\_reader (or attr\_accessor) every time that I get an  
error?

---

<div class="post-metadata">

**Author:** ![dmjb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/898d66/32.png) [@dmjb](https://www.ruby-forum.com/u/dmjb)\
**Post date:** [November 6, 2008, 11:07pm UTC](https://www.ruby-forum.com/t/creating-object-from-hash/152727/2 "2008-11-06T23:07:45Z")

</div>

Hi,

On Nov 6, 2008, at 2:44 PM, Davi Barbosa wrote:

> end  
> end

Just wondering if you’ve looked at OpenStruct?

% ri OpenStruct

You can achieve the above more simply.

require ‘ostruct’  
Computer = Class.new(OpenStruct) # or class Computer \< OpenStruct …

> calls some unwanted method.  
> “id” is technically deprecated. Even so, it’s also available at  
> Object# **id** and Object#object\_id.

But still, you can undefine methods:

% ri Module#undef\_method

> If I just add “attr\_reader :id” everything works. Can I do it  
> directly,  
> without adding attr\_reader (or attr\_accessor) every time that I get an  
> error?

Try some of the things I’ve mentioned above?

Best,  
Stephen

---

<div class="post-metadata">

**Author:** ![dmjb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/898d66/32.png) [@dmjb](https://www.ruby-forum.com/u/dmjb)\
**Post date:** [November 7, 2008, 12:07am UTC](https://www.ruby-forum.com/t/creating-object-from-hash/152727/3 "2008-11-07T00:07:32Z")

</div>

On 06.11.2008 21:44, Davi Barbosa wrote:

> end  
> calls some unwanted method.
> 
> If I just add “attr\_reader :id” everything works. Can I do it directly,  
> without adding attr\_reader (or attr\_accessor) every time that I get an  
> error?

You can make your life easier with Struct:

irb(main):001:0\> Comp = Struct.new :id do  
irb(main):002:1\* def initialize(h)  
irb(main):003:2\> members.each {|m| self[m] = h[m] || h[m.to\_sym]}  
irb(main):004:2\> end  
irb(main):005:1\> end  
=\> Comp  
irb(main):006:0\> c = Comp.new(:id=\>133)  
=\> #  
irb(main):007:0\> d = Comp.new(“id”=\>133)  
=\> #  
irb(main):008:0\>

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![dmjb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/898d66/32.png) [@dmjb](https://www.ruby-forum.com/u/dmjb)\
**Post date:** [November 7, 2008, 12:19am UTC](https://www.ruby-forum.com/t/creating-object-from-hash/152727/4 "2008-11-07T00:19:15Z")

</div>

On Nov 6, 2008, at 4:03 PM, Robert K. wrote:

> > end  
> > Computer.new({‘id’ \> 1})" does not create the reader for @id and  
> > irb(main):001:0\> Comp = Struct.new :id do
> 
> Kind regards
> 
> robert

and even easier with fattr

class Computer  
fattr :foo  
fattr :bar

def initialize options = {}  
options.each{|k,v| send k, v}  
end  
end

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