这就是我所拥有的
目前,我正在这样做:
current_account.send(object).search(params[:search]).user_id_equals_any(users).visibility_is_any(visibilities)
但那不是很灵活吗?如果我想有条件地没有其中一个范围怎么办?
我想一个带有条件添加元素的范围数组将是一个很好的解决方案
我将使用.send()
调用的参数数组scopes = []
scopes = << [:user_id_equals_any, users] if filter_users
scopes = << [:visibility_is_any, visibilities] if filter_visibility
所以,我可以有一些未知的数字范围。
要执行范围,我需要调用.send(:scope_name, scope_param)
但是我如何为scopes
数组中的任意数量的范围执行此操作?
作为一个循环,我认为它会像
result = current_account.send(object).search(params[:search])
scopes.each do |scope|
result.send(scope[0], scope[1])
end
return result
循环可以简化为
scopes.each {|s| result.send(s[0], s[1]) }
但有没有办法在一行中附加不同的发送电话?
答案 0 :(得分:3)
您可以使用inject
:
scopes = []
# Note that in your example, the assignment is invalid syntax
scopes << [:user_id_equals_any, users] if filter_users
scopes << [:visibility_is_any, visibilities] if filter_visibility
# initial result
result = current_account.send(object).search(params[:search])
# applying the scopes
result = scopes.inject(result) do |result, (method, param)|
result.send(method, param)
end
return result
在每个循环中,前一个块执行的最后一个返回值传递给块的第一个参数,在本例中为result
。第一个循环得到初始结果(即方括号中的参数到inject
调用。返回最后一个循环的返回值。
有关详细信息,请查看the documentation。
答案 1 :(得分:1)
随意构建自己的抽象,以便您的代码反映出您对问题的看法:
class Object
def send_if(condition, *args, &block)
condition ? send(*args, &block) : self
end
end
current_account.send(object).search(params[:search]).
send_if(filter_user, :user_id_equals_any, users).
send_if(filter_visibility, :visibility_is_any, visibilities)