Arel AND子句和空条件

MId*_*hna 6 ruby activerecord ruby-on-rails arel

请考虑以下代码片段:

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
Run Code Online (Sandbox Code Playgroud)

filter_by_merchant商家ID变空的方法中,Arel必须返回的值才能忽略AND子句效果?还有,有更好的方法来处理这种情况吗?

Jos*_*hua 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
Run Code Online (Sandbox Code Playgroud)

  • 就我而言,我必须返回 `Arel.sql('TRUE')`,否则会引发 `unsupported: TrueClass` 错误。 (2认同)

Wal*_*man 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
Run Code Online (Sandbox Code Playgroud)

它非常笨重,但它可以完成工作。