繁体   English   中英

Rails ActiveRecord where子句

[英]Rails ActiveRecord where clause

我想从数据库中选择Cars ,其中where子句为我的问题寻找最佳DRY方法。

例如,我有这两个参数

params[:car_model_id] (int)
params[:transmission_id] (int)
params[:from_date]
params[:to_date]

但我不知道哪一个会为空

if params[:car_model_id].nil? && !params[:transmission_id].nil?
    if params[:from_date].nil? && params[:from_date].nil?
        return Car.where(:transmission_id => params[:transmission_id])
    else
        return Car.where(:transmission_id => params[:transmission_id], :date => params[:from_date]..params[:to_date])
    end
elseif !params[:car_model_id].nil? && params[:transmission_id].nil?
    if params[:from_date].nil? && params[:from_date].nil?
        return Car.where(:car_model_id=> params[:car_model_id])
    else
        return Car.where(:car_model_id=> params[:car_model_id], :date => params[:from_date]..params[:to_date])
    end
else
   return Car.where(:car_model_id=> params[:car_model_id], :transmission_id => params[:transmission_id], :date => params[:from_date]..params[:to_date])
end

什么是避免这种不良代码的最佳方法,并检查参数是否为内联(在where

你可以做:

car_params = params.slice(:car_model_id, :transmission_id).reject{|k, v| v.nil? }

然后:

Car.where(car_params)

说明:因为,您正在检查特定键,即:car_model_idtransmission_id存在于params 当你刚才使用:transimission_id代码时,上面的代码将是这样的:transimission_id in params

Car.where(:transmission_id => '1')

或者你有:car_model_id in params

Car.where(:car_model_id => '3')

或者当你有两个时:

Car.where(:transmission_id => '1', :car_model_id => '3')

注意:仅当您将params键作为要为其运行查询的列名称时,此选项才有效。 如果您打算在params中使用与列名称不匹配的其他键,那么我建议您在slice之前将其更改为控制器本身中列名的键。

更新 :因为OP已经编辑了他的问题并且现在引入了更多if.. else条件。 解决这个问题并始终牢记一件事的一种方法是让你的user_params正确的值,你想在模型类上运行你的查询,这里是Car 所以,在这种情况下:

car_params = params.slice(:car_model_id, :transmission_id).reject{|k, v| v.nil? }
if params[:from_date].present? && params[:from_date].present?
  car_params.merge!(date: params[:from_date]..params[:to_date])
end

然后:

Car.where(car_params)

什么是避免这种不良代码的最佳方法,并检查参数是否为内联(在哪里)

好问题 !

我将使用两个额外的布尔变量( transmission_id_is_validcar_model_id_is_valid )进行实现

transmission_id_is_valid = params[:car_model_id].nil? && !params[:transmission_id].nil?
car_model_id_is_valid = !params[:car_model_id].nil? && params[:transmission_id].nil?

if transmission_id_is_valid
   return Car.where(:transmission_id => params[:transmission_id])
elseif car_model_id_is_valid
   return Car.where(:car_model_id=> params[:car_model_id])
....
end

我认为现在更具人性化。

首先,我将此代码更改为Car模型,我认为没有必要检查params是否不存在。

# using Rails 4 methods
class Car < ActiveRecord::Base

  def self.find_by_transmission_id_or_model_id(trasmission_id, model_id)
     if transmission_id
       find_by trasmission_id: trasmission_id
     elsif model_id
       find_by model_id: model_id
     end
  end
end

在控制器中:

def action
   car = Car.find_by_transmission_id_or_model_id params[:trasmission_id], params[:car_model_id]
end

编辑:

只有两个参数时,此代码很好。 对于许多条件参数,请查看ransack gem。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM