2015-06-20 13 views
6

Rozważmy następujący fragment kodu:Arel i klauzula i pusty stan

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 

W metodzie filter_by_merchant gdy id kupiec staje się pusta, jaka powinna być wartość, która musi zostać zwrócony do AREL zignorować i skutku klauzuli? Czy istnieje lepszy sposób na obsługę tego przypadku?

+1

O ile mogę powiedzieć, że nie ma żadnych argumentów, które można przekazać do 'and' które sprawiają, że nic nie robią. –

+0

Czy próbowałeś "return billing_requests.all"? – peter

Odpowiedz

1

Nie wydaje się być możliwe przekazanie argumentów do and, które powodują, że nie robi nic. Jednakże, można po prostu zadzwonić and warunkowo:

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 

to bardzo niezgrabne, ale dostaje zadanie.

+0

@wally_altman, próbowałem zgodnie z tym, o czym wspomniałeś. Ale oto, co otrzymuję. https://gist.github.com/midhunkrishna/985523a2041305eb817b –

+0

Hej, masz rację, to nie działa! Zaktualizowałem moje rozwiązanie. –

+0

@wally_altman, to nie odpowiada na pytanie. Poza tym, co jeśli muszę też filtrować według innego parametru, na przykład "nazwa operatora"? Zaktualizowałem pytanie. –

6

Powinieneś zwrócić wartość true. Po uruchomieniu .and (true) w końcu zostanie przekonwertowany na "AND 1" w sql.

def filter_by_merchant 
    return true if @merchant_id.blank? 

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

Podoba mi się to, dzięki! – rkrdo

+0

W moim przypadku musiałem zwrócić 'Arel.sql ('TRUE')', w przeciwnym razie spowodowałoby to błąd '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