很容易在链条的头部有一个条件并分享其余部分:
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
答案 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%明确的,而不是被一两行缩短。