簡體   English   中英

Rails 4 ActiveRecord查詢:在order子句中綁定變量

[英]Rails 4 ActiveRecord Query: bind variables in order clause

我試圖在我的mysql查詢中建立一個動態順序,以便某些匹配在頂部被優先處理。

Ticket.where(
  "id LIKE :search || name LIKE :search", 
  {search: "%#{params[:search]}]%"}
).order(
  "id = :exact DESC, name = :exact DESC, id LIKE :search DESC, name LIKE :search DESC", 
  {exact: params[:search], search: "%#{params[:search]}%"}
)

假設params [:search] ='search_value',查詢應以這種方式結束:

SELECT * FROM tickets
WHERE id LIKE "%search_value%" || name LIKE "%search_value%"
ORDER BY id = 'search_value' DESC, name = 'search_value' DESC, id LIKE "%search_value%" DESC, name LIKE "%search_value%" DESC;

每當我執行此操作時,都會收到ActiveRecord :: QueryMethods.validate_order_args的錯誤消息,指示方向應為:asc或:desc。

除了手動清理搜索然后直接將其插值到訂單字符串之外,還有沒有辦法使它像where子句的綁定變量那樣起作用?

因此,經過一些挖掘,我想我已經找到了解決方案,盡管我希望Rails有更好的方法。

我已經將其包含在我的Rails項目中

class ActiveRecord::Base
  def self.corder *array
    statement = array.shift
    while (i=array.shift).present?
      case i
      when Hash
        i.each do |k,v|
          statement.gsub!(':' + k.to_s, ActiveRecord::Base.sanitize(v))
        end
      when String
        statement.sub!('?', ActiveRecord::Base.sanitize(i))
      else
        raise "Unknown type: #{i} -- #{i.class}"
      end
    end
    self.order(statement)
  end

  def corder *array
    statement = array.shift
    while (i=array.shift).present?
      case i
      when Hash
        i.each do |k,v|
          statement.gsub!(':' + k.to_s, sanitize(v))
        end
      when String
        statement.sub!('?', sanitize(i))
      else
        raise "Unknown type: #{i} -- #{i.class}"
      end
    end
    self.order!(statement)
  end
end

就我的目的而言,雖然可以輕松擴展,但效果很好。 兩者是完全相同的重復項(在類和實例上需要它的簡單解決方案)。

此時,您可以:

Model.where(
  'id LIKE :search || name LIKE :search', 
  {search: "%#{params[:search]}%"}
).order(
  'id = :exact DESC, name = :exact DESC, id LIKE :rough DESC, name LIKE :rough DESC', 
  {exact: params[:search], rough: "%#{params[:search]}%"}
)

假設params [:search] =='ibm'的SQL:

SELECT * FROM model WHERE id LIKE '%ibm%' || name LIKE '%ibm%' ORDER BY id = 'ibm' DESC, name = 'ibm' DESC, id LIKE '%ibm%' DESC, name LIKE '%ibm%' DESC;

或者是“?” 綁定變量也可以正常工作,例如:

Model.where(
  'id LIKE ? || name LIKE ?', 
  "%#{params[:search]}%", "%#{params[:search]}%"
).order(
  'id = ? DESC, name = ? DESC, id LIKE ? DESC, name LIKE ? DESC', 
  params[:search], params[:search], "%#{params[:search]}%", "%#{params[:search]}%"
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM