简体   繁体   中英

Variables in ruby method names

I have the following code:

for attribute in site.device_attributes
  device.attribute
end

where I would like the code to substitute the value of "attribute" for the method name.

I have tried device."#{attribute}" and various permutations.

Is this completely impossible? Am I missing something?

I have considered overriding method_missing, but I can't figure out how that would actually help me when my problem is that I need to call an "unknown" method.

You can use #send method to call object's method by method's name:

object.send(:foo) # same as object.foo

You can pass arguments with to invoked method:

object.send(:foo, 1, "bar", 1.23) # same as object.foo(1, "bar", 1.23)

So, if you have attribute name in variable "attribute" you can read object's attribute with

object.send(attribute.to_sym)

and write attribute's value with

object.send("#{attribute}=".to_sym, value)

In Ruby 1.8.6 #send method can execute any object's method regardless of its visibility (you can eg call private methods). This is subject to change in future versions of Ruby and you shouldn't rely on it. To execute private methods, use #instance_eval:

object.instance_eval {
  # code as block, can reference variables in current scope
}

# or

object.instance_eval <<-CODE
  # code as string, can generate any code text
CODE

Update

You can use public_send to call methods with regard to visibility rules.

object.public_send :public_foo # ok
object.public_send :private_bar # exception

The "send" method should do what you're looking for:

object = "upcase me!"
method = "upcase"
object.send(method.to_sym) # => "UPCASE ME!"

Matt and Maxim are both correct, but leave out a detail that might help you get your head around the #send syntax: In Ruby, calling a method is really sending a message. Softies on Rails has a relatively straightforward explanation of that .

你也可以

device.instance_eval(attribute)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM