conditional chaining in ruby

2019-01-22 03:35发布

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?

标签: ruby chaining
9条回答
Deceive 欺骗
2楼-- · 2019-01-22 03:58

I use this pattern:

class A
  def some_method_because_of_a
     ...
     return self
  end

  def some_method_because_of_b
     ...
     return self
  end
end

a = A.new
a.some_method_because_of_a().some_method_because_of_b()
查看更多
萌系小妹纸
3楼-- · 2019-01-22 03:59

Maybe your situation is more complicated than this, but why not:

my_object.method_a if a
my_object.method_b if b
my_object.method_c if c
查看更多
太酷不给撩
4楼-- · 2019-01-22 04:01

I ended up writing the following:

class Object

  # A naïve Either implementation.
  # Allows for chainable conditions.
  # (a -> Bool), Symbol, Symbol, ...Any -> Any
  def either(pred, left, right, *args)

    cond = case pred
           when Symbol
             self.send(pred)
           when Proc
             pred.call
           else
             pred
           end

    if cond
      self.send right, *args
    else
      self.send left
    end
  end

  # The up-coming identity method...
  def itself
    self
  end
end


a = []
# => []
a.either(:empty?, :itself, :push, 1)
# => [1]
a.either(:empty?, :itself, :push, 1)
# => [1]
a.either(true, :itself, :push, 2)
# => [1, 2]
查看更多
登录 后发表回答