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?
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
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 ...
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.
"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?
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)
=> #<struct Comp id=133>
irb(main):007:0> d = Comp.new("id"=>133)
=> #<struct Comp id=133>
irb(main):008:0>
Kind regards
robert
···
On 06.11.2008 21:44, Davi Barbosa wrote:
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?
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?
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)
=> #<struct Comp id=133>
irb(main):007:0> d = Comp.new("id"=>133)
=> #<struct Comp id=133>
irb(main):008:0>
Kind regards
robert
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama