2015-06-20 103 views
6

考慮下面的代碼片段:阿雷爾AND子句和空狀態

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 

在方法時,商戶ID變空filter_by_merchant,應該是什麼,必須返回阿雷爾忽略AND子句效應的價值? 另外,有沒有更好的方法來處理這種情況?

+1

到目前爲止,我所知道的,沒有,你可以傳遞給'和'使得它什麼也不做任何參數。 –

+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,這不回答這個問題。此外,如果我還必須通過另一個參數進行過濾,比如說'operator_name'?我已經更新了這個問題。 –

6

您應該返回true。當你運行.and(true)時,它最終會在sql中轉換爲'AND 1'。

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