2012-06-15 6 views
3

Вот что яЕсть ли элегантный лайнер для добавления областей, хранящихся в массиве, используя .send()?

в настоящее время, я делаю это:

current_account.send(object).search(params[:search]).user_id_equals_any(users).visibility_is_any(visibilities) 

, но это еще не очень гибок? Что, если я хочу условно не иметь одну из этих областей?

Я полагаю, что массив областей с условно добавленных элементов будет хорошим решением

Массив параметров, которые я хотел бы вызвать с помощью Пошлите()

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]) } 

но есть способ, чтобы добавить различные вызовы посыла в одной строке?

ответ

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.

+0

почему объект в Teh Inject ли блокировать 'response' – NullVoxPopuli

+1

@TheLindyHop:.. это была опечатка, что только что получил фиксированной Спасибо –

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) 
+0

почему третий параметр является блоком? Я думал, что send был просто '.send (name, par ams) ' – NullVoxPopuli

+0

@TheLindyHop: вы можете отправить блок в обернутый метод, это просто сделать его более общим, даже если он не используется в примере. – tokland

+0

Не могли бы вы привести пример того, как это будет использоваться? исходный .send не принимает блок http://ruby-doc.org/core-1.9.3/Object.html#method-i-send – NullVoxPopuli