2015-06-20 4 views
6

Рассмотрим следующий фрагмент кода:Арел И положение и Empty условие

def sql 
    billing_requests 
    .project(billing_requests[Arel.star]) 
    .where(
    filter_by_day 
     .and(filter_by_merchant) 
     .and(filter_by_operator_name) 
) 
    .to_sql 
end 

def filter_by_day 
    billing_requests[:created_at].gteq(@start_date).and(
    billing_requests[:created_at].lteq(@end_date) 
) 
end 

def filter_by_operator_name 
    unless @operator_name.blank? 
    return billing_requests[:operator_name].eq(@operator_name) 
    end 
end 

def filter_by_merchant 
    unless @merchant_id.blank? 
    return billing_requests[:merchant_id].eq(@merchant_id) 
    end 
end 

private 

def billing_requests 
    @table ||= Arel::Table.new(:billing_requests) 
end 

В методе filter_by_merchant когда коммерсант идентификатор становится пустым, что должно быть значение, которое должно быть возвращено для Arel игнорировать и эффект дизъюнкцию? Кроме того, есть ли лучший способ справиться с этим делом?

+1

Насколько я могу судить, нет никаких аргументов, которые вы можете передать в 'and', которые делают его не делать ничего. –

+0

вы попробовали «return billing_requests.all»? – peter

ответ

1

Невозможно дать какие-либо аргументы and, которые заставляют его ничего не делать. Тем не менее, вы можете просто позвонить and условно:

def sql 
    billing_requests 
    .project(billing_requests[Arel.star]) 
    .where(filter_by_day_and_merchant_and_operator_name) 
    .to_sql 
end 

def filter_by_day 
    billing_requests[:created_at].gteq(@start_date).and(
    billing_requests[:created_at].lteq(@end_date) 
) 
end 

def filter_by_merchant 
    billing_requests[:merchant_id].eq(@merchant_id) 
end 

def filter_by_operator_name 
    billing_requests[:operator_name].eq(@operator_name) 
end 

def filter_by_day_and_merchant 
    if @merchant_id.blank? 
    filter_by_day 
    else 
    filter_by_day.and(filter_by_merchant) 
    end 
end 

def filter_by_day_and_merchant_and_operator_name 
    if @operator_name.blank? 
    filter_by_day_and_merchant 
    else 
    filter_by_day_and_merchant.and(filter_by_operator_name) 
    end 
end 

private 

def billing_requests 
    @table ||= Arel::Table.new(:billing_requests) 
end 

Это очень неуклюжим, но он получает работу.

+0

@wally_altman, я пробовал в соответствии с тем, что вы упомянули. Но вот что я получаю. https://gist.github.com/midhunkrishna/985523a2041305eb817b –

+0

Эй, ты прав, это не работает! Я обновил свое решение. –

+0

@wally_altman, это не отвечает на вопрос. Кроме того, что, если мне также придется фильтровать по другому параметру, скажем «имя_оператора»? Я обновил вопрос. –

6

Вы должны вернуть true. Когда вы запустите .and (true), он в конечном итоге преобразуется в «AND 1» в sql.

def filter_by_merchant 
    return true if @merchant_id.blank? 

    billing_requests[:merchant_id].eq(@merchant_id) 
end 
+0

Мне это нравится, спасибо! – rkrdo

+0

В моем случае мне пришлось возвращать 'Arel.sql ('TRUE')', иначе он поднимет ошибку 'unsupported: TrueClass'. – justis

1
def sql 
    billing_requests 
    .project(billing_requests[Arel.star]) 
    .where(conditions) 
    .to_sql 
end 

def conditions 
    ret = filter_by_day 
    ret = ret.and(filter_by_merchant) unless @merchant_id.blank? 
    ret = ret.and(filter_by_operator_name) unless @operator_name.blank? 
    ret 
end 

def filter_by_day 
    billing_requests[:created_at].gteq(@start_date).and(
    billing_requests[:created_at].lteq(@end_date) 
) 
end 

def filter_by_operator_name 
    billing_requests[:operator_name].eq(@operator_name) 
end 

def filter_by_merchant 
    billing_requests[:merchant_id].eq(@merchant_id) 
end 

private 

def billing_requests 
    @table ||= Arel::Table.new(:billing_requests) 
end