views:

58

answers:

2

I have a User model with a number of very similar properties that I want to list without typing each on in individually.

So, rather than:

"eye color: #{@user.his_eye_color}"
"hair color: #{@user.his_hair_color}"
"height: #{@user.his_height}"
"weight: #{@user.his_weight}"
...

"eye color: #{@user.her_eye_color}"
"hair color: #{@user.her_hair_color}"
"height: #{@user.her_height}"
"weight: #{@user.her_weight}"
...

I'd like to do a block or something (Proc? Lambda? Still a touch unclear what those are...):

['eye color','hair color','height','weight',...].do |stat|
   "#{stat}: #{@user.her_(stat.underscore)}"
end

['eye color','hair color','height','weight',...].do |stat|
   "#{stat}: #{@user.his_(stat.underscore)}"
end

I know that what I just wrote above is mystical, magical, and wholly and completely WRONG (the @user.his_(stat.underscore) part), but what could I do that's like this? I basically need to call my Model's attributes dynamically, but I'm unsure how to do this...

Any help would be really appreciated!

+5  A: 
['eye color','hair color','height','weight',...].do |stat|
   "#{stat}: #{ @user.send(:"her_#{stat.tr(" ","_")}") }"
end

['eye color','hair color','height','weight',...].do |stat|
   "#{stat}: #{ @user.send(:"his_#{stat.tr(" ","_")}") }"
end

This should work. You can always use send to call method on object, and generate that method name on the fly as string

MBO
I knew there must be something like this I was missing... however, `.underscore` seems to have stopped working, thus the call fails. Any idea why that is?
neezer
underscore is possibly only available from ActiveSupport in Rails. I don't think it's available in the standard Ruby String API.
Farrel
If nothing else, `stat` is a string so you could always use `stat.tr(' ','_')` to convert them if you can't get `.underscore` working.
bta
+2  A: 

If you're using ActiveRecord in Rails you can also use the Object#[] method to get the values of attributes dynamically

['eye color','hair color','height','weight',...].do |stat|
   "#{stat}: #{ @user[ "her_#{ stat.underscore }"]}"
end
Farrel
I am using Rails, and this method works too... except I still don't have access to `.underscore`.
neezer
According the the Rails API underscore will turn "EyeColor" to "eye_color" but leave "eye color" alone.
Farrel
I used bta's comment from the other answer with your Object#[] method and it works and it looks very clean! Thanks!
neezer