链条中间或尾部的状况

时间:2011-12-30 09:43:41

标签: ruby

很容易在链条的头部有一个条件并分享其余部分:

if condition
    get_this
else
    get_that
end
.foo.bar.baz

但通常情况下,我想在链条的中间或尾部出现条件。我能想到的最好的就是使用instance_eval

foo.bar
.instance_eval{
    if condition
        get_this
    else
        get_that
    end
}
.baz

但是我担心调用instance_eval很重,所以我实际上最终没有这样做。值得这样做吗?有没有更好的方法,或者我应该简单地写一下:

if condition
    foo.bar.get_this
else
    foo.bar.get_that
end
.baz

3 个答案:

答案 0 :(得分:3)

如何使用Object#send有条件地调用方法:

foo.bar.send(condition? ? :get_this : :get_that).baz

在一个更复杂的情况下,使用多个/不同的参数,可以使用splat operator将数组展开为参数:

foo.bar.send(
  * case conditional
    when qux
      [:get_this, param1]
    when quux
      [:get_that, param1, param2]
    else
      [:get_other, param1, param2]
    end
).baz

答案 1 :(得分:3)

为什么不在bar上提供一个接受布尔值然后相应行为的方法?这封装了逻辑,甚至可以屏蔽复杂的逻辑或多个条件,而不会太乱。

class Bar
  def get_what(condition)
    case condition
      when qux; get_this(param1)
      when quux; get_that(param1, param2)
      else get_other(param1)
    end
  end
end

# assuming `bar` is an instance of `Bar`
foo.bar.get_what(cond).baz

PS:根据用例,我经常尝试避免过长的消息链之类的东西(因为根据Law of Demeter (Wikipedia)这可能被认为是不好的做法:)),尽管在ruby中使用哈希和数组时这很有用。所以我想你有一个使用长消息链的有效用例。

答案 2 :(得分:2)

有时,低技术解决方案是最好的:

my_bar = foo.bar
if condition
  my_thing = my_bar.get_this
else
  my_thing = my_bar.get_that
end
my_thing.baz

说真的,我认为源代码的含义对于每个人(包括你自己在未来的某个时间)都是100%明确的,而不是被一两行缩短。