Ruby: How to evaluate multiple methods for each send command?

Let's say I have XML :: Element ... I want to do something like:

my_xml_element.send ("parent.next_sibling.next_sibling")

+7
ruby metaprogramming
source share
5 answers

In your case it is better to use instance_eval

 "Test".instance_eval{chop!.chop!} #=> "Te" 

And for your code:

 my_xml_element.instance_eval{parent.next_sibling.next_sibling} 
+7
source share

This is not what he asked, if I understand his question correctly. I mean, send accepts a string or character as arg, and your solution is not. I donโ€™t think there is a built-in method that will do what you want, but I hacked into a method that will be with the test.

 require 'test/unit' class Example def multi_send(str) str.split('.').inject(self){|klass, method| klass.send(method) } end end class MyTest < Test::Unit::TestCase def test_multi_send a = Example.new methods = "class.to_s.downcase.chop!" assert a.multi_send(methods) == 'exampl' end end 
+5
source share

Actually, Hell was almost right. Use this:

 methods_chain = "parent.next_sibling.next_sibling" result = my_xml_element.instance_eval( eval methods_chain ) 

This code is up to 20 times faster than using split () and allows you to pass chaining methods using args, for example:

 methods = "power!(2).div(57).+(12).to_f" 42.instance_eval { eval methods } 
+4
source share

I think the question is that you definitely have a number of methods defined as a string, and you want to call this on some object, right?

 class Object def call_method_chain(method_chain) return self if method_chain.empty? method_chain.split('.').inject(self){|o,m| o.send(m.intern)} end end >> User.first.profile.address.state.name => "Virginia" >> User.first.call_method_chain("profile.address.state.name") => "Virginia" 
+1
source share

Problem with eval based Alfuken answer

A) eval is pretty dangerous though fast

B) if you have an extra (sequential) point to call a method like this

 "example".instance_eval{eval "chop!..chop!"}.class => "examp".."examp" "example".instance_eval {eval "chop!..chop!"}.class => Range # this is not what is desired 
0
source share

All Articles