【问题标题】:Ransack gem - Case insensitive sort (Rails 4)Ransack gem - 不区分大小写的排序(Rails 4)
【发布时间】:2025-12-16 06:40:01
【问题描述】:

使用 Ransack gem,我正在尝试对索引页面上的简单列表进行排序。但是,排序字段name 中同时存在大写和小写值。为了使它们排序有用,排序应该不区分大小写。

这是模特Vendor

name:string, email:string, address:string, phone:string, fax:string

这是控制器:

class VendorsController < ApplicationController

def index
  @search = Vendor.search(params[:q])
  @vendors = @search.result
end

还有观点:

/index.html.slim
tr
  th = sort_link @search, :name, "Name"
  th = sort_link @search, :email, "Company Email"
  th = sort_link @search, :address, "Address"

任何建议将不胜感激。

【问题讨论】:

  • sorted_list = vendors.sort {|a,b| a.name.downcase &lt;=&gt; b.name.downcase} # 试试看,如果有帮助请告诉我
  • @hd1 感谢您的快速回复!你能再给我一点吗?我尝试将它放在控制器的搜索和结果中,但没有运气。还是个新手。
  • 尝试向您的模型添加一个访问器,它以小写形式返回名称并在该字段上进行搜索? def lowercase_name name.downcase! end 并配置 ransack 以使用 @search.sorts 在您的 controller 中搜索 lowercase_name 字段
  • 试过了,但这对我这个级别的人来说是另一个挑战。获取虚拟属性的值很简单,但使用它进行排序似乎需要一些技巧。如果有一个很好的方法来完成这个,请与我分享一些代码......再次感谢。
  • @hd1,多亏了你的第一个建议,我至少得到了它的工作......添加答案以便有代码可以看到......

标签: sorting ruby-on-rails-4 ransack


【解决方案1】:

您正在寻找的是一个自定义的“Ransacker”:

class Vendor < ActiveRecord::Base

    ransacker :name_case_insensitive, type: :string do
      arel_table[:name].lower
    end

end

查看:

th = sort_link(@q, :name_case_insensitive)

【讨论】:

  • 您介意解释一下它的作用或工作原理吗?我对“arel_table”的使用感到特别困惑。
【解决方案2】:

10 个月,也许为时已晚!

这解决了我的 posgresql 问题

sort_link @search, 'lowercase(name)', "Name"

【讨论】:

  • 在使用关联时似乎不起作用,例如 **sort_link @search, 'lowercase(patient.last_name)', "Name"
【解决方案3】:

您可以使用这种方法一次性解决模型的所有字符串列的问题:

# lib/ransack_object.rb

module RansackObject

  def self.included(base)
    base.columns.each do |column|
      if column.type == :string
        base.ransacker column.name.to_sym, type: :string do
          Arel.sql("lower(#{base.table_name}.#{column.name})")
        end
      end
    end
  end

end

然后在你的模型中包含 ransack 对象:

class UserWithManyAttributes < ActiveRecord::Base

  include RansackObject

end

【讨论】:

  • 这会降低数据库端的大小,而不是搜索词。如果搜索词已经是小写,则此方法有效。
  • 我想问一个问题,我从前端发送"q"=&gt;{"s"=&gt;"price asc"},在我的查询中它会自动发送ORDER BY "products"."price" ASC。这是由于上面的代码吗?我有来自其他人的代码库,其中包含此代码,但我无法弄清楚它是如何根据条件附加 ORDER BY "products"."price" ASC 的原因。价格 desc 等甚至标题 asc desc 等也是如此。请您帮忙解释一下原因。谢谢!
  • 抱歉,我已经有几年没有使用 Rails ans Ransack 了。但听起来很可能将这个条件发送给 Ransack 会导致匹配的查询。
【解决方案4】:

Ransack 现在有一个case_insensitive 选项 您可以使用case_insensitive: false 自定义谓词

参考:https://github.com/activerecord-hackery/ransack/wiki/Custom-Predicates

【讨论】:

    【解决方案5】:

    感谢 hd1 发布上述方法。 我在这里发布实际代码 - 这并不理想,因为它似乎是一个冗长的解决方法。 仍然愿意接受更清洁的建议。

    def index
      @search = Vendor.search(params[:q])
      @vendors = @search.result
    
      if params[:q].present?
        params[:q].each do |k, v| 
          if v == 'name asc'
            @vendors = @search.result.sort { |p1, p2| p1.name.downcase <=> p2.name.downcase }
          elsif v == 'name desc'
            @vendors = @search.result.sort { |p2, p1| p1.name.downcase <=> p2.name.downcase }
          end
        end
      end
    end
    

    【讨论】: