Rails 4 ActiveRecord查询:在order子句中绑定变量

时间:2015-01-22 20:25:37

标签: mysql ruby-on-rails-4 rails-activerecord

我试图在我的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收到错误,说明Direction应该是:asc或:desc。

除了手动清理搜索然后将其直接插入到顺序字符串中之外,有没有办法让它像where子句的绑定变量一样运行?

1 个答案:

答案 0 :(得分:0)

所以经过一番挖掘后我觉得我已经找到了解决方案,虽然我希望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]}%"}
)

SQL假设params [:search] ==' ibm':

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]}%"
)