tags:

views:

58

answers:

3

Hi, I'm looking for a elegant way to assign the value stored inside an Hash into a pre-existed object. Just to be clear, if I have an object, say obj with two attributes, say name and age, I want to assign this values coming from an hash without do something like:

obj.name = hash[:name]
obj.age = hash[:age] 

Thanks for your attention. Simone

+1  A: 

Don't know about elegant, but you can do:

[:name, :age].each do |att|
  obj.send("#{att}=", hash[att])
end
Chris
Your method looks good, but what if I have more then name and age?
Simone Di Cola
+3  A: 

Best bet is probably to simply define a method like update_attributes which takes a hash and does it inside an instance method of the class.

Expanding on what others have written and what you seem to need I think your best bet would be:

hash.keys.each do |key|
  m = "#{key}="
  obj.send( m, hash[key] ) if obj.respond_to?( m )
end

This will account for:

  • not having all the attributes of the class in the hash at all times, and
  • any number of keys in the hash (not just :name, etc)
thenduks
Could you lpease explain me why you have to wirte m = "#{key}=" insted of m = "#{key}" ?
Simone Di Cola
Well it's tricky to explain but actually very simple. First lets say for the purposes of explaining that `key` is the string `x` and `hash[key]` is `1`... Now, in Ruby the code `obj.x = 1` is actually equivalent to `obj.x=( 1 )`. So in the next line when I'm doing `obj.send( m, ... )`, I need it to _assign_ to that property. In other words, if I hadn't put the equals sign in the method name it would have called `obj.x( 1 )` and `x` simply doesn't take a parameter (because it's a property). What I want is `obj.x=( 1 )` and that's why I need `#{key}=`
thenduks
A: 
obj.methods.grep(/[^!=]=$/).each {|attr| obj.send(attr, hash[attr]) }
Jörg W Mittag
Probably want to at least add a `if hash.has_key?(attr)` in there in case you don't have every attribute of the object in the hash.
thenduks
@thenduks: As far as I can decode the specification, the object has two attributes which are always in the hash. But of course, the question isn't exactly well worded. It should probably at least have a specification and a test suite to be answered properly.
Jörg W Mittag
Your method seems very tidy, but could you explain me what the regular expression stand for ?
Simone Di Cola
@user442622: I want to get all setter methods, i.e. all methods that end with an equals sign (that's the `=$` part), but there are a couple of other methods that also end with an equals sign (namely `==`, `===` and `!=`), so I match only on those which do not have `!` or `=` as their second-to-last character (that's the `[^!=]` part).
Jörg W Mittag