Ransack 简单模式使用指南:快速实现搜索与排序功能

Ransack 简单模式使用指南:快速实现搜索与排序功能

ransack Object-based searching. ransack 项目地址: https://gitcode.com/gh_mirrors/ra/ransack

什么是 Ransack?

Ransack 是一个强大的 Ruby 库,专门为 ActiveRecord 模型提供搜索和排序功能。它允许开发者通过简单的配置快速实现复杂的数据查询功能,而无需编写大量 SQL 查询语句。

简单模式 vs 高级模式

Ransack 提供两种工作模式:

  1. 简单模式:适用于不需要复杂布尔逻辑的搜索场景
  2. 高级模式:支持复杂的布尔逻辑组合查询

对于大多数基础搜索需求,简单模式已经完全够用。本文将重点介绍简单模式的使用方法。

控制器配置

基础查询

在控制器中设置 Ransack 查询非常简单:

def index
  @q = Person.ransack(params[:q])
  @people = @q.result(distinct: true)
end

这里的 distinct: true 参数确保返回的结果不包含重复记录。

关联表查询

如果需要基于关联表进行排序(同时预加载关联数据并使用分页):

def index
  @q = Person.ransack(params[:q])
  @people = @q.result.includes(:articles).page(params[:page])
end

安全注意事项

从 Ransack 4.0 版本开始,默认情况下不允许对模型的任何列进行搜索和排序。这是重要的安全改进,防止意外暴露敏感数据。开发者需要显式声明哪些属性是可搜索的(通过授权白名单机制)。

视图层实现

搜索表单

Ransack 提供了 search_form_for 辅助方法来替代 Rails 标准的 form_for

<%= search_form_for @q do |f| %>
  <%= f.label :name_cont %>
  <%= f.search_field :name_cont %>
  
  <%= f.label :articles_title_start %>
  <%= f.search_field :articles_title_start %>
  
  <%= f.submit %>
<% end %>

搜索字段的命名遵循特定模式: 属性名[_or_属性名]..._谓词

常用搜索谓词包括:

  • cont:包含(contains)
  • start:以...开头(starts with)
  • eq:等于(equals)
  • gt:大于(greater than)
  • lt:小于(less than)

排序链接

Ransack 的 sort_link 辅助方法可以轻松创建可排序的表头:

<%= sort_link(@q, :name) %>

可以自定义链接文本和默认排序方向:

<%= sort_link(@q, :name, 'Last Name', default_order: :desc) %>

对于复杂的排序需求,比如基于 SQL 函数结果的排序,可以在模型中定义相应的作用域:

class Person < ActiveRecord::Base
  scope :sort_by_reverse_name_asc, -> { order("REVERSE(name) ASC") }
  scope :sort_by_reverse_name_desc, -> { order("REVERSE(name) DESC") }
end

然后在视图中使用:

<%= sort_link(@q, :reverse_name) %>

高级配置

自定义搜索参数键名

默认使用 :q 作为搜索参数键名,可以在初始化文件中修改:

Ransack.configure do |c|
  c.search_key = :query
end

字符串搜索处理

默认会去除查询字符串两端的空白字符,可以禁用此行为:

Ransack.configure do |c|
  c.strip_whitespace = false
end

PostgreSQL 特定配置

对于 PostgreSQL 数据库,可以配置 NULL 值的排序方式:

Ransack.configure do |c|
  c.postgres_fields_sort_option = :nulls_first  # 或 :nulls_last
end

还可以实现不区分大小写的排序:

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

class User < ActiveRecord::Base
  include RansackObject
end

最佳实践

  1. 安全性:始终明确指定可搜索的字段,避免开放所有字段
  2. 性能:对于关联表查询,使用 includes 预加载关联数据避免 N+1 问题
  3. 用户体验:为排序链接添加清晰的视觉指示,帮助用户理解当前排序状态
  4. 数据库优化:对于大型数据集,考虑为常用搜索字段添加数据库索引

通过合理使用 Ransack 的简单模式,开发者可以快速实现强大的搜索和排序功能,同时保持代码的简洁和可维护性。

ransack Object-based searching. ransack 项目地址: https://gitcode.com/gh_mirrors/ra/ransack

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宫文琼Perfect

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值