Rails“where”查询被忽略

时间:2013-08-31 21:30:38

标签: ruby-on-rails ruby ruby-on-rails-3 sqlite rails-activerecord

我遇到查询问题。我的模型中有一个范围列表:

class Drawing < ActiveRecord::Base
  has_many :revisions

  scope :by_description, lambda { |description| where('description LIKE ?', "%#{description}%") unless description.nil? }
  scope :by_drawing_number, lambda { |drawing_number| where('drawing_number LIKE ?', "%#{drawing_number}%") unless drawing_number.nil? }
  scope :by_item_number, lambda { |item_number| where('item_number LIKE ?', "%#{item_number}%") unless item_number.nil? }
  scope :by_pump_model, lambda { |pump_model| where('pump_model LIKE ?', "%#{pump_model}%") unless pump_model.nil? }
  scope :by_frame_size, lambda { |frame_size| where('frame_size LIKE ?', "%#{frame_size}%") unless frame_size.nil? }
  scope :by_part_type, lambda { |part_type| where('part_type LIKE ?', "%#{part_type}%") unless part_type.nil? }
  scope :by_created_before, lambda { |created_before| where('created_at <= ?', created_before) unless created_before.nil? }
  scope :by_created_after, lambda { |created_after| where('created_at >= ?', created_after) unless created_after.nil? }

我在控制器中的索引操作中调用它们:

  def index

    @drawings = Drawing.by_description(params[:drawings][:description]).by_drawing_number(params[:drawings][:drawing_number]).\
      by_item_number(params[:drawings][:item_number]).by_pump_model(params[:drawings][:pump_model]).by_frame_size(params[:drawings]\
      [:frame_size]).by_part_type(params[:drawings][:part_type]).by_created_before(params[:drawings][:created_before]).\
      by_created_after(params[:drawings][:created_after]).all  

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @drawings }
    end
  end

所有查询都有效,我可以使用它们来过滤任何给定变量的搜索,但by_created_before和by_created_after范围除外。 params哈希显示已输入搜索的日期,但输出的查询不包括这两个范围。这是日志的片段:

Started GET "/drawings?utf8=%E2%9C%93&drawings%5Bdescription%5D=&drawings%5Bdrawing_number%5D=&drawings%5Bitem_number%5D=&drawings%5Bpump_model%5D=&drawings%5Bframe_size%5D
e%5D=&drawings%5Bcreated_before%281i%29%5D=&drawings%5Bcreated_before%282i%29%5D=&drawings%5Bcreated_before%283i%29%5D=&drawings%5Bcreated_after%281i%29%5D=2013&drawings%5B
%5D=5&drawings%5Bcreated_after%283i%29%5D=2&commit=Search" for 127.6.43.1 at 2013-08-31 16:49:56 -0400                                                                      
Processing by DrawingsController#index as HTML                                                                                                                              
  Parameters: {"utf8"=>"✓", "drawings"=>{"description"=>"", "drawing_number"=>"", "item_number"=>"", "pump_model"=>"", "frame_size"=>"", "part_type"=>"", "created_before(1i
re(2i)"=>"", "created_before(3i)"=>"", "created_after(1i)"=>"2013", "created_after(2i)"=>"5", "created_after(3i)"=>"2"}, "commit"=>"Search"}                                
  Drawing Load (0.6ms)  SELECT "drawings".* FROM "drawings" WHERE (description LIKE '%%') AND (drawing_number LIKE '%%') AND (item_number LIKE '%%') AND (pump_model LIKE '%
IKE '%%') AND (part_type LIKE '%%')                                                                                                                                         
  Rendered drawings/index.html.erb within layouts/application (11.4ms)                                                                                                      
Completed 200 OK in 291ms (Views: 86.7ms | ActiveRecord: 0.6ms)  

我也尝试过使用

lambda {|created_before| where(:created_at <= created_before)...}

感谢您的任何建议!

3 个答案:

答案 0 :(得分:1)

这是因为您的created_atcreated_before参数通过多个参数进入 - 请参阅日志中的Parameters:部分。月,日和年有特殊的(2i)(3i)(1i)参数。这是date_select助手的典型特征。当使用质量分配时,rails会将这个日期重新组合成一个单独的字符串,就像你在这里期待的那样......但是在这里你必须自己做。

快速建议:

如果这是您从表单中使用日期的唯一方法,请使用select_date instead of date_select,因为参数更容易理解并再次解析为单个日期字符串。或者,如果可能的话,只使用text_field。与日期选择的用户界面(日历界面或其他任何东西)相结合,这并不像看起来那么糟糕 - 并且它的优点是似乎不允许无效日期,例如2月31日。

总而言之,你只需要弄清楚哪些参数是哪个,然后在进入你的范围之前将它们插入到一个看日期的字符串中,你应该设置它。

答案 1 :(得分:0)

“params hash显示已输入搜索的日期”。

它在哪里显示?

如果我在URL解码器中解码参数,我会得到“/ drawings?utf8 =✓&amp; drawings [description] =&amp; drawings [drawing_number] =&amp; drawings [ite m_number] =&amp; drawings [pump_model] =&amp; drawings [frame_size] e] =&amp; drawings [created_before(1i)] =&amp; drawings [created_before(2i)] =&amp; drawings [created _before(3i)] =&amp; drawings [created_after(1i) ] = 2013&amp; drawings [] = 5&amp; drawings [created_after(3i)] = 2&amp; commit = Search“

修复输入后,您必须在数据库中进行比较之前将字符串转换为日期。像Datetime.parse params [:drawings] [:created_before]

之类的东西

答案 2 :(得分:0)

这是我能够解决问题的方法。 pdobb是正确的,不得不将3个参数放入一个字符串,或单独处理它们。这是我更新的模型:

class Drawing < ActiveRecord::Base
  has_many :revisions

  scope :by_description, lambda { |description| where('description LIKE ?', "%#{description}%") unless description.nil? }
  scope :by_drawing_number, lambda { |drawing_number| where('drawing_number LIKE ?', "%#{drawing_number}%") unless drawing_number.nil? }
  scope :by_item_number, lambda { |item_number| where('item_number LIKE ?', "%#{item_number}%") unless item_number.nil? }
  scope :by_pump_model, lambda { |pump_model| where('pump_model LIKE ?', "%#{pump_model}%") unless pump_model.nil? }
  scope :by_frame_size, lambda { |frame_size| where('frame_size LIKE ?', "%#{frame_size}%") unless frame_size.nil? }
  scope :by_part_type, lambda { |part_type| where('part_type LIKE ?', "%#{part_type}%") unless part_type.nil? }
  scope :by_created_before, lambda { |x,y,z| 
    d=Date.new(x.to_i, y.to_i, z.to_i)
    d.to_s
    where('created_on <= ?', d) unless d.nil? } 

  scope :by_created_after, lambda { |x,y,z| 
    d=Date.new(x.to_i, y.to_i, z.to_i)
    d.to_s
    where('created_on >= ?', d) unless d.nil? }

以及整体查询的最终操作:

  def index

    @drawings = Drawing.by_description(params[:drawings][:description]).by_drawing_number(params[:drawings][:drawing_number]).\
      by_item_number(params[:drawings][:item_number]).by_pump_model(params[:drawings][:pump_model]).by_frame_size(params[:drawings]\
      [:frame_size]).by_part_type(params[:drawings][:part_type]).by_created_before(params[:drawings]['created_before(1i)'], params[:drawings]['created_before(2i)'], params[:drawings]['created_before(3i)']).\
      by_created_after(params[:drawings]['created_after(1i)'], params[:drawings]['created_after(2i)'], params[:drawings]['created_after(3i)']).all  

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @drawings }
    end
  end

我知道这不是最优雅的查询,因为我最终得到了很长的网址,但它的工作正确地查询了我的模型。