Ransack Documentation

repository·main·Indexed 26 days ago

https://github.com/activerecord-hackery/ransack

A searching tool for Rails applications that enables complex searching capabilities using standard Ruby and ERB without external infrastructure. It provides features such as Simple and Advanced search modes, a wide array of search matchers (predicates), sortable headers via sort_link, and integration with Hotwire/Turbo through turbo_search_form_for.

Tokens
16.6K
Snippets
71
Records
95
Agent score
90%

What's inside Ransack

  1. Sort on Globalized/Translated Attributes

    main

    When using internationalization gems like Globalize, sorting on translated attributes requires specific handling to ensure joins are correctly established.

    Using View Helpers

    You can use sort_link directly with the translation attribute:

    <%= sort_link @q, :translations_name %>
    <%= sort_link @q, :category_translations_name %>

    Programmatic Sorting

    When setting sorts in the controller, you must ensure the necessary joins are included in the ActiveRecord relation to prevent errors.

    Basic approach:

    @q = Book.ransack(s: 'category_translations_name asc')
    @books = @q.result.joins(:translations)

    Complex scenarios (multiple translations/nested associations): Use .includes to ensure all join dependencies are loaded:

    @q = Book.ransack(s: 'category_translations_name asc')
    @books = @q.result.includes(:translations, category: :translations)
    @q = Book.ransack(s: 'category_translations_name asc')
    @books = @q.result.includes(:translations, category: :translations)
  2. Add custom search functions using ransackers

    main

    Ransack allows you to create custom search functions called ransackers using Arel. A ransacker method is defined in your model and must return an Arel node that supports standard predicate methods (like eq, cont, matches, etc.).

    Note: Ransackers are an expert feature. For better performance and scalability, prefer searching on dedicated database search fields whenever possible rather than converting/ransacking data on the fly.

    # in the model:
    ransacker :reversed_name, formatter: proc { |v| v.reverse } do |parent|
      parent.table[:name]
    end
  3. Set default sorting in the Controller

    main

    To ensure a consistent sort order when no user-provided sorting is present, you can manually assign values to the @q.sorts attribute in your controller's index action. This should be done if @q.sorts is empty.

    For a single sort field:

    @q.sorts = 'title asc'

    For multiple sort fields:

    @q.sorts = ['title asc', 'created_at desc']
    # app/controllers/posts_controller.rb
    class PostsController < ActionController::Base
      def index
        @q = Post.ransack(params[:q])
        @q.sorts = 'title asc' if @q.sorts.empty?
    
        @posts = @q.result(distinct: true)
      end
    end
  4. Convert integer fields to strings for 'contains' searches

    main

    If you want to use the cont (contains) predicate on an integer field (like id), you must first convert the integer to a string using a ransacker.

    PostgreSQL

    # in the model:
    ransacker :id do
      Arel.sql("to_char(id, '9999999')")
    end

    MySQL

    # in the model:
    ransacker :id do
      Arel.sql("CONVERT(#{table_name}.id, CHAR(8))")
    end

    Usage in View

    <%= f.search_field :id_cont, placeholder: 'Id' %>
    <%= sort_link(@search, :id) %>
    # PostgreSQL version
    ransacker :id do
      Arel.sql("to_char(id, '9999999')")
    end
    
    # View usage
    <%= f.search_field :id_cont, placeholder: 'Id' %>
    <%= sort_link(@search, :id) %>
  5. Search tagged fields with Ransack

    main

    When searching for tags in a Ransack form, use the plural name of the tagging field followed by the desired predicate. For a field named :projects, use :projects_name_<predicate>.

    Available search strategies:

    • Exact Match (_in): Matches keys exactly. Supports comma-separated values (e.g., Home, Personal) to return records containing those specific tags. Useful for distinguishing similar names like 'Home' from 'Homework'.
    • Exact Combination (_eq): Matches all provided keys exactly. Searching for Home will return nothing if the record has multiple tags (e.g., Home, Personal), but Home, Personal will match.
    • Substring Match (_cont): Matches any part of the tag name. Searching for Home will match both Home and Homework.
    • Select List: Use a select dropdown populated with distinct tags from the database.
    <%= search_form_for @search do |f| %>
      <%# Option A: Exact Match %>
      <%= f.text_field :projects_name_in   %> 
    
      <%# Option B: Match combinations %>
      <%= f.text_field :projects_name_eq   %> 
    
      <%# Option C: Substring match %>
      <%= f.text_field :projects_name_cont %> 
    
      <%# Option D: Select from list %>
      <%= f.select :projects_name_in, ActsAsTaggableOn::Tag.distinct.order(:name).pluck(:name) %>
    <% end %>
  6. Customise Ransack predicate and attribute labels via I18n

    main

    You can customize the labels used for predicates and attributes in Ransack forms by adding entries to your application's translation files (e.g., locales/en.yml).

    To customize predicates, use the ransack.predicates key. To customize attribute labels specifically for Ransack, use the ransack.attributes.[model_name].[attribute_name] key.

    en:
      ransack:
        asc: ascending
        desc: descending
        predicates:
          cont: contains
          not_cont: not contains
          start: starts with
          end: ends with
          gt: greater than
          lt: less than
        attributes:
          person:
            name: Full Name
          article:
            title: Article Title
            body: Main Content
  7. Export Ransack search results to CSV

    main

    To export data to CSV while preserving the current Ransack search parameters, you can generate a link that merges the existing search parameters (params[:q]) with the desired :csv format.

    In your view, check if params[:q] exists. If it does, pass the specific search attributes from params[:q] into the URL helper along with format: :csv. If no search is active, simply link to the index path with format: 'csv' to export the full collection.

    <% if params[:q] %>
      <%= link_to 'Export 1', dashboard_index_path({name: params[:q][:name_cont]}.merge({format: :csv})) %>
    <% else %>
      <%= link_to 'Export 2', dashboard_index_path(format: 'csv') %>
    <% end %>
  8. Configure Ransack translations for predicates, models, and attributes

    main

    You can customize the labels used for Ransack predicates, model names, and attribute names in your application's locale files. Ransack looks for translations under the ransack key.

    Available translation files can be found in Ransack::Locale. You can define:

    • ransack.predicates: Custom names for search predicates (e.g., cont to contains).
    • ransack.models: Custom names for models.
    • ransack.attributes: Custom names for specific model attributes.

    Additionally, you can use standard Rails attribute translations under attributes or activerecord.attributes to influence how Ransack displays names.

    en:
      ransack:
        asc: ascending
        desc: descending
        predicates:
          cont: contains
          not_cont: not contains
          start: starts with
          end: ends with
          gt: greater than
          lt: less than
        models:
          person: Passenger
        attributes:
          person:
            name: Full Name
          article:
            title: Article Title
            body: Main Content
      attributes:
        model_name:
          model_field1: field name1
          model_field2: field name2
      activerecord:
        attributes:
          namespace/article:
            title: AR Namespaced Title
          namespace_article:
            title: Old Ransack Namespaced Title
  9. Display sort links in the View

    main

    Use the sort_link helper within your view templates to generate links that allow users to toggle sorting for specific columns. The helper takes the Ransack search object (@q), the attribute name to sort by, and an optional label string.

    Example usage in an ERB template:

    <th><%= sort_link(@q, :title, "Title") %></th>
    <th><%= sort_link(@q, :category, "Category") %></th>
    <th><%= sort_link(@q, :title, "Title") %></th>