如何在Ruby中简化活动记录查询

时间:2019-03-18 10:03:26

标签: ruby activerecord ruby-on-rails-5

我想根据国家,城市,州,角色和价目表进行过滤。如果用户选择任何单一方法或任何组合,则它应该起作用。这是我的有效搜索记录:

if params[:role].present?
  if params[:role] == 'role1'
    if params[:city_name].present?
      @matching_c = @matching_c.where(city_name: params[:city_name])
    elsif params[:state].present?
      @matching_c = @matching_c.where(state: params[:state])
    elsif params[:country].present?
      @matching_c = @matching_c.where(country: params[:country])
    end
    if params[:rate_card].present?
      @matching_c = @matching_c.joins(:rate_card).where("rate_cards.rate_card_type = ?", "#{params[:rate_card]}")
    end
    @matching_f = nil
  end
  if params[:role]  == 'role2'
    if params[:city_name].present?
      @matching_f = @matching_f.where(city_name: params[:city_name])
    elsif params[:state].present?
      @matching_f = @matching_f.where(state: params[:state])
    elsif params[:country].present?
      @matching_f = @matching_f.where(country: params[:country])
    end
    if params[:rate_card].present?
      @matching_f = @matching_f.joins(:rate_card).where("rate_cards.rate_card_type = ?", "#{params[:rate_card]}")
    end
    @matching_c = nil
  end
else
  if params[:city_name].present?
    @matching_f = @matching_f.where(city_name: params[:city_name])
    @matching_c = @matching_c.where(city_name: params[:city_name])
  elsif params[:state].present?
    @matching_f = @matching_f.where(state: params[:state])
    @matching_c = @matching_c.where(state: params[:state])
  elsif params[:country].present?
    @matching_c = @matching_c.where(country: params[:country])
    @matching_f = @matching_f.where(country: params[:country])
  end
  if params[:rate_card].present?
    @matching_c = @matching_c.joins(:rate_card).where("rate_cards.rate_card_type = ?", "#{params[:rate_card]}")
    @matching_f = @matching_f.joins(:rate_card).where("rate_cards.rate_card_type = ?", "#{params[:rate_card]}")
  end
end

这可行,但我希望将其简化。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:3)

您应该链接范围,而不是相互排斥它们:

@matching_c = @matching_c.where(city_name: params[:city_name]) if
  params[:city_name].present?
@matching_c = @matching_c.where(state: params[:state]) if 
  params[:state].present?
@matching_c = @matching_c.where(country: params[:country]) if
  params[:country].present?

答案 1 :(得分:2)

def add_where(query, params)
  # FROM HERE
  field = %i(city_name state country).find { |x| params[x].present? }
  if field
    query = query.where(field => params[field])
  end
  # TO HERE

  if params[:rate_card].present?
    query = query.joins(:rate_card).where("rate_cards.rate_card_type = ?", params[:rate_card])
  end

  query
end

@matching_c = params[:role] != 'role2' ? add_where(@matching_c, params) : nil
@matching_f = params[:role] != 'role1' ? add_where(@matching_f, params) : nil

它将仅接受(城市,州,国家/地区)之一,例如您的代码。如果要接受任何组合,请使用此代码代替标记的代码:

%i(city_name state country).each { |field|
  query = query.where(field => params[field]) if params[field].present?
end