def chain_maybe(klass, condition, *args)
args[1..-1].reduce(klass.send(args.first)) { |r,m| (condition && r.send(m)) || r }
end
or:
def chain_maybe(klass, condition, *args)
first, *others = args
others = [] unless condition
others.reduce(klass.send(first)) { |r,m| r.send(m) }
end
For:
class Klass
def foo
puts 'foo'
self
end
def bar
puts 'bar'
self
end
def baz
puts 'baz'
self
end
end
c = Klass.new
chain_maybe(c, true, :foo, :bar, :baz)
foo
bar
baz
#=> #<Klass:0x007fccea8da388>
chain_maybe(c, false, :foo, :bar, :baz)
foo
#=> #<Klass:0x007fccea8da388>
chain_maybe(c, true, :foo, :bar)
foo
bar
#=> #<Klass:0x007fccea8da388>
chain_maybe(c, true, :bar, :baz)
bar
baz
#=> #<Klass:0x007fccea8da388>
If there is to be a condition for each argument, this can be generalized to:
def chain_maybe(klass, conditions, args)
return nil if conditions.empty?
first, *others = args.zip(conditions).select(&:last).map(&:first)
others.reduce(klass.send(first)) { |r,m| r.send(m) }
end
args = [:foo, :bar, :baz]
chain_maybe(c, [true, true, true], args)
foo
bar
baz
#=> #<Klass:0x007fccea8da388>
chain_maybe(c, [false, true, true], args)
bar
baz
#=> #<Klass:0x007fccea8da388>
chain_maybe(c, [true, false, true], args)
foo
baz
#=> #<Klass:0x007fccea8da388>