Is there a good way to chain methods conditionally in Ruby?
What I want to do functionally is
if a && b && c my_object.some_method_because_of_a.some_method_because_of_b.some_method_because_of_c elsif a && b && !c my_object.some_method_because_of_a.some_method_because_of_b elsif a && !b && c my_object.some_method_because_of_a.some_method_because_of_c etc...
So depending on a number of conditions I want to work out what methods to call in the method chain.
So far my best attempt to do this in a "good way" is to conditionally build the string of methods, and use eval
, but surely there is a better, more ruby, way?
Method chaining is a convenient way to build up complex queries, which are then lazily executed when needed. Within the chain, a single object is updated and passed from one method to the next, until it's finally transformed into its output value.
||= is called a conditional assignment operator. It basically works as = but with the exception that if a variable has already been assigned it will do nothing. First example: x ||= 10. Second example: x = 20 x ||= 10. In the first example x is now equal to 10.
You could put your methods into an arry and then execute everything in this array
l= [] l << :method_a if a l << :method_b if b l << :method_c if c l.inject(object) { |obj, method| obj.send(method) }
Object#send
executes the method with the given name. Enumerable#inject
iterates over the array, while giving the block the last returned value and the current array item.
If you want your method to take arguments you could also do it this way
l= [] l << [:method_a, arg_a1, arg_a2] if a l << [:method_b, arg_b1] if b l << [:method_c, arg_c1, arg_c2, arg_c3] if c l.inject(object) { |obj, method_and_args| obj.send(*method_and_args) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With