### Install Documentation Dependencies
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/documentation.md
Install Docusaurus and other necessary packages for local documentation development.
```bash
yarn install
```
--------------------------------
### Controller Setup with Includes and Pagination
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Use this controller setup for sorting on associated table columns without `distinct: true`. It includes preloading associated records and pagination.
```ruby
def index
@q = Person.ransack(params[:q])
@people = @q.result.includes(:articles).page(params[:page])
end
```
--------------------------------
### Install Development Dependencies
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
Installs the necessary gems for development. Specify a Rails version if not using the latest.
```sh
bundle install
```
```sh
RAILS='6-1-stable' bundle install
```
--------------------------------
### Start Local Development Server
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/documentation.md
Launch a local development server to preview documentation changes in real-time. Changes are typically reflected live without needing a server restart.
```bash
yarn start
```
--------------------------------
### Basic Controller Setup - Ransack Simple Mode
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Use this in your controller to initialize a Ransack search object with distinct results. Ensure `params[:q]` is available.
```ruby
def index
@q = Person.ransack(params[:q])
@people = @q.result(distinct: true)
end
```
--------------------------------
### Starts With Predicate
Source: https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching
Use the `start` predicate to find records where a field begins with a specific string. This is case-sensitive.
```ruby
>> User.ransack(first_name_start: 'Rya').result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE 'Rya%')
```
--------------------------------
### Controller Setup for Ransack Search
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/associations.md
In your controller, initialize a Ransack search object with parameters and eager load associated records for performance.
```ruby
class SupervisorsController < ApplicationController
def index
@q = Supervisor.ransack(params[:q])
@supervisors = @q.result.includes(:department, :employees)
end
end
```
--------------------------------
### Ransack Console Examples for Authorization
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/other-notes.md
Demonstrates how `ransackable_attributes` behaves with and without an `auth_object` in the Rails console.
```ruby
> Article
=> Article(id: integer, person_id: integer, title: string, body: text)
> Article.ransackable_attributes
=> ["title", "body"]
> Article.ransackable_attributes(:admin)
=> ["id", "person_id", "title", "body"]
> Article.ransack(id_eq: 1).result.to_sql
=> SELECT "articles".* FROM "articles" # Note that search param was ignored!
> Article.ransack({ id_eq: 1 }, { auth_object: nil }).result.to_sql
=> SELECT "articles".* FROM "articles" # Search param still ignored!
> Article.ransack({ id_eq: 1 }, { auth_object: :admin }).result.to_sql
=> SELECT "articles".* FROM "articles" WHERE "articles"."id" = 1
```
--------------------------------
### Ransack Search with Scopes
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/other-notes.md
Example of performing a Ransack search using defined scopes. The second example demonstrates passing an `auth_object` to filter scopes.
```ruby
Employee.ransack({ activated: true, hired_since: '2013-01-01' })
```
```ruby
Employee.ransack({ salary_gt: 100_000 }, { auth_object: current_user })
```
--------------------------------
### Ransacker with Arguments
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Use ransackers with arguments to perform complex attribute searches. This example searches for articles where the title contains 'Guide' and the body length is within a specified range.
```ruby
Person.ransack(
conditions: [{
attributes: { '0' => { name: 'max_article_title_by_body_length', ransacker_args: [10, 100] } },
predicate_name: 'cont',
values: ['Guide']
}]
)
```
--------------------------------
### Usage of Custom Predicates
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Demonstrates how to use custom Ransack predicates in queries. Includes examples for null-safe greater-than-or-equal-to and JSONB containment.
```ruby
# Usage
```
```ruby
Product.ransack(price_gteq_or_null: 100).result.to_sql
```
```ruby
# => SELECT "products".* FROM "products" WHERE ("products"."price" >= 100 OR "products"."price" IS NULL)
```
```ruby
# JSONB contains usage
```
```ruby
Person.ransack(data_jcont: '{"group": "experts"}').result.to_sql
```
```ruby
# => SELECT "persons".* FROM "persons" WHERE "persons"."data" @> '{"group": "experts"}'
```
--------------------------------
### Controller Setup for Ransack Authorization
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/other-notes.md
In your controller, initialize Ransack with a potential `auth_object` derived from the current user.
```ruby
class ArticlesController < ApplicationController
def index
@q = Article.ransack(params[:q], auth_object: set_ransack_auth_object)
@articles = @q.result
end
private
def set_ransack_auth_object
current_user.admin? ? :admin : nil
end
end
```
--------------------------------
### Add Ransack to Gemfile
Source: https://github.com/activerecord-hackery/ransack/blob/main/README.md
To install Ransack, add the gem to your Gemfile.
```ruby
gem 'ransack'
```
--------------------------------
### Configure Routes for Advanced Search
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/advanced-mode.md
Define a collection route for 'search' that accepts both GET and POST requests. This is necessary for advanced searches that may exceed GET request size limits.
```ruby
resources :people do
collection do
match 'search' => 'people#search', via: [:get, :post], as: :search
end
end
```
--------------------------------
### Basic Ransack Controller and View Setup
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
In the controller, call `.ransack(params[:q])` on your model. In the view, use `search_form_for` and `sort_link` helpers to build the search form and sortable table headers.
```ruby
# app/controllers/people_controller.rb
def index
@q = Person.ransack(params[:q])
@people = @q.result(distinct: true).includes(:articles).page(params[:page])
end
```
```erb
<%# app/views/people/index.html.erb %>
<%= search_form_for @q do |f| %>
<%= f.label :name_cont, "Name contains" %>
<%= f.search_field :name_cont %>
<%= f.label :name_or_email_cont, "Name or email contains" %>
<%= f.search_field :name_or_email_cont %>
<%= f.label :articles_title_start, "Article title starts with" %>
<%= f.search_field :articles_title_start %>
<%= f.submit "Search" %>
<% end %>
| <%= sort_link(@q, :name, "Full Name", default_order: :asc) %> |
<%= sort_link(@q, :email) %> |
<%= sort_link(@q, :age) %> |
<% @people.each do |person| %>
| <%= person.name %> |
<%= person.email %> |
<%= person.age %> |
<% end %>
```
--------------------------------
### Usage of Ransackers
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Examples demonstrating how to query using defined ransackers for concatenated names, string-casted IDs, and other custom attributes.
```ruby
# Usage examples
```
```ruby
Person.ransack(full_name_cont: 'john doe').result.to_sql
```
```ruby
# => ... WHERE (LOWER(concat_ws(' ', first_name, last_name)) LIKE '%john doe%')
```
```ruby
Person.ransack(id_cont: '42').result.to_sql
```
```ruby
# => ... WHERE (to_char(id, '9999999') LIKE '%42%')
```
--------------------------------
### Usage of Ransacker with Arguments
Source: https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers
Demonstrates how to pass arguments to a ransacker using `ransacker_args` when performing a search. This example searches for people whose maximum article title meets certain criteria.
```ruby
Person.ransack(
conditions: [{
attributes: {
'0' => {
name: 'author_max_title_of_article_where_body_length_between',
ransacker_args: [10, 100]
}
},
predicate_name: 'cont',
values: ['Ransackers can take arguments']
}]
)
=> SELECT "people".* FROM "people" WHERE (
(SELECT MAX(articles.title)
FROM articles
WHERE articles.person_id = people.id
AND CHAR_LENGTH(articles.body) BETWEEN 10 AND 100
GROUP BY articles.person_id
)
LIKE '%Ransackers can take arguments%')
ORDER BY "people"."id" DESC
```
--------------------------------
### Configure Ransack Globally
Source: https://github.com/activerecord-hackery/ransack/wiki/Configuration
Set global Ransack configuration options in an initializer file. This example shows how to change the default search key, disable ignoring unknown conditions, and hide sort order indicators.
```ruby
Ransack.configure do |config|
# Change default search parameter key name.
# Default key name is :q
config.search_key = :query
# Raise errors if a query contains an unknown predicate or attribute.
# Default is true (do not raise error on unknown conditions).
config.ignore_unknown_conditions = false
# Globally display sort links without the order indicator arrow.
# Default is false (sort order indicators are displayed).
# This can also be configured individually in each sort link (see the README).
config.hide_sort_order_indicators = true
end
```
--------------------------------
### OR Queries on Associated Models
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/using-predicates.md
Search across attributes of associated models using a combined predicate syntax. This example searches 'foo' or 'bar' on the associated 'account' model.
```ruby
>> User.ransack(account_foo_or_account_bar_cont: 'val').result.to_sql
=> SELECT "users".* FROM "users" INNER JOIN accounts ON accounts.user_id = users.id WHERE ("accounts.foo LIKE '%val%' OR accounts.bar LIKE '%val%')
```
--------------------------------
### Silent Failure Example
Source: https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching
Attempting to use a predicate for a non-existent attribute will result in a silent failure, returning no SQL WHERE clause.
```ruby
>> User.ransack(name_cont: 'Rya').result.to_sql
=> "SELECT \"users\".* FROM \"users\"
```
--------------------------------
### Ransacker for Price Existence Check (PostgreSQL)
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/ransackers.md
Creates a ransacker to check for the existence of a related record (e.g., 'prices' for a 'book'), returning a boolean. This example uses PostgreSQL syntax.
```ruby
ransacker :price_exists do |parent|
# SQL syntax for PostgreSQL -- others may differ
# This returns boolean true or false
Arel.sql("(select exists (select 1 from prices where prices.book_id = books.id))")
end
```
--------------------------------
### Ransacker for Concatenated Full Name with Quoted Space (Arel >= 6)
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/ransackers.md
Similar to the previous example, but correctly quotes the space separator for Arel version 6 and above.
```ruby
ransacker :full_name do |parent|
Arel::Nodes::InfixOperation.new('||',
Arel::Nodes::InfixOperation.new('||',
parent.table[:first_name], Arel::Nodes.build_quoted(' ')
),
parent.table[:last_name])
end
```
--------------------------------
### Ransack Search with Tenant Scoping
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/acts-as-taggable-on.md
Filter Ransack searches using the `for_tenant` method when multitenancy is configured for tags. This example shows selecting tags for a specific tenant ('fr').
```erb
<%= f.label :projects_name, 'Project' %>
<%= f.select :projects_name_in, ActsAsTaggableOn::Tag.for_tenant('fr').distinct.order(:name).pluck(:name) %>
```
--------------------------------
### Handle Distinct Selects with Joins and Includes
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/other-notes.md
When using `distinct: true` with joins, Ransack might generate invalid SQL. This example shows how to resolve this by adding `includes` and `joins` to the result.
```ruby
def index
@q = Person.ransack(params[:q])
@people = @q.result(distinct: true)
.includes(:articles)
.joins(:articles)
.page(params[:page])
end
```
--------------------------------
### jQuery AJAX Request with Ransack Parameters
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Example of sending Ransack search parameters via a jQuery AJAX request. Ensure the data is structured as a nested hash under the 'q' key.
```javascript
// jQuery AJAX example
$.ajax({
url: "/users.json",
data: {
q: {
first_name_cont: "pete",
last_name_cont: "jack",
s: "created_at desc"
}
},
success: function(data) {
console.log(data);
}
});
```
--------------------------------
### Add Custom Ransack Predicate
Source: https://github.com/activerecord-hackery/ransack/wiki/Custom-Predicates
Configure a new custom predicate named 'equals_diddly' using Ransack. This example demonstrates setting the Arel predicate, a custom formatter, a validator, and options for compounds, type casting, and case insensitivity.
```ruby
Ransack.configure do |config|
config.add_predicate 'equals_diddly',
arel_predicate: 'eq',
formatter: proc { |v| "#{v}-diddly" },
validator: proc { |v| v.present? },
compounds: true,
type: :string,
case_insensitive: true
end
```
--------------------------------
### Generate sortable column header links
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Use the `sort_link` helper to create links for sorting columns. It supports custom labels, default sort orders, and multi-column sorting. To get a sort URL string instead of a link tag, use `sort_url`.
```erb
<%# Basic sort link %>
<%= sort_link(@q, :name) %>
```
```erb
<%# Custom label and default direction %>
<%= sort_link(@q, :name, 'Last Name', default_order: :desc) %>
```
```erb
<%# Block form for complex markup %>
<%= sort_link(@q, :name) do %>
Player Name
<% end %>
```
```erb
<%# Multi-column sort: clicking sorts by last_name then first_name asc always %>
<%= sort_link(@q, :last_name, [:last_name, 'first_name asc'], 'Last Name') %>
```
```erb
<%# Multi-column with per-field default orders %>
<%= sort_link(@q, :last_name, %i(last_name first_name),
default_order: { last_name: 'asc', first_name: 'desc' }) %>
```
```erb
<%# Hide the sort indicator arrow on this link only %>
<%= sort_link(@q, :name, hide_indicator: true) %>
```
```erb
<%# Sort URL (returns URL string, not a link tag) %>
<%= sort_url(@q, :name, default_order: :desc) %>
```
```erb
<%# Scope-based sort for computed/virtual fields — define scopes in model:
scope :sort_by_reverse_name_asc, -> { order("REVERSE(name) ASC") }
scope :sort_by_reverse_name_desc, -> { order("REVERSE(name) DESC") }
%>
<%= sort_link(@q, :reverse_name) %>
```
--------------------------------
### Navigate to Docs Directory
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/documentation.md
Change the current directory to the 'docs' folder to begin working with the documentation.
```bash
cd docs
```
--------------------------------
### Build Static Documentation
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/documentation.md
Generate the static content for the documentation, which will be placed in the 'build' directory. This output can be hosted on any static content platform.
```bash
yarn build
```
--------------------------------
### Deploy Documentation via SSH
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/documentation.md
Deploy the built documentation using SSH. This command assumes the necessary SSH keys and configurations are in place.
```bash
USE_SSH=true yarn deploy
```
--------------------------------
### Ransack Authorization Demonstration (Rails Console)
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Demonstrates how Ransack authorization works by showing the results of `ransackable_attributes` with and without an `auth_object`, and the SQL generated for authorized and unauthorized queries.
```ruby
# Rails console demonstration
Article.ransackable_attributes # => ["title", "body", "published_at"]
Article.ransackable_attributes(:admin) # => ["id", "author_id", "title", "body", "published_at"]
Article.ransack(id_eq: 1).result.to_sql
# => SELECT "articles".* FROM "articles" (id_eq ignored — not authorized)
Article.ransack({ id_eq: 1 }, { auth_object: :admin }).result.to_sql
# => SELECT "articles".* FROM "articles" WHERE "articles"."id" = 1
```
--------------------------------
### Create MySQL Database
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
Commands to connect to MySQL and create a database named 'ransack'.
```sh
mysql -u root
mysql> create database ransack;
```
--------------------------------
### Search Fixed JSONB Key with Ransacker
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Define a ransacker to search a fixed key within a JSONB column. This example searches for 'link_type' in the 'properties' column.
```ruby
class Contact < ApplicationRecord
# Search a fixed key in JSONB
ransacker :link_type do |parent|
Arel::Nodes::InfixOperation.new('->>', parent.table[:properties],
Arel::Nodes.build_quoted('link_type'))
end
# Cast entire JSONB column to text for string matching (slow; no index use)
ransacker :within_json do |parent|
Arel.sql("contacts.json_data::text")
end
def self.ransackable_attributes(auth_object = nil)
_ransackers.keys
end
end
```
```ruby
# Search fixed JSONB key
Contact.ransack(link_type_eq: 'twitter').result.to_sql
# => SELECT "contacts".* FROM "contacts" WHERE "contacts"."properties" ->> 'link_type' = 'twitter'
```
```ruby
# Full-text JSON cast search
Contact.ransack(within_json_cont: 'experts').result
# => SELECT "contacts".* FROM "contacts" WHERE contacts.json_data ILIKE '%experts%'
```
```ruby
# Using jcont (requires custom predicate setup + ActiveRecordExtended gem):
# Ransack.configure { |c| c.add_predicate 'jcont', arel_predicate: 'contains', formatter: proc { |v| JSON.parse(v) } }
Person.ransack(data_jcont: '{"group": "experts"}').result.to_sql
# => SELECT "persons".* FROM "persons" WHERE "persons"."data" @> '{"group": "experts"}'
```
--------------------------------
### Basic Ransack Search Controller
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Sets up a Ransack search object in the controller and renders the results. Requires a corresponding view.
```ruby
def search
index
render :index
end
def index
@q = Person.ransack(params[:q])
@people = @q.result
end
```
--------------------------------
### Sort Link for Scoped Sorting
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Uses the `sort_link` helper to sort by a virtual field defined by a model scope. This example sorts by a scope named 'reverse_name'.
```erb
<%= sort_link(@q, :reverse_name) %>
```
--------------------------------
### Define Ransackable Scopes on a Model
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/other-notes.md
Define `ransackable_scopes` on your model to whitelist scopes that Ransack can use. This example shows how to conditionally allow access to scopes based on an `auth_object`.
```ruby
class Employee < ActiveRecord::Base
scope :activated, ->(boolean = true) { where(active: boolean) }
scope :salary_gt, ->(amount) { where('salary > ?', amount) }
def self.hired_since(date)
where('start_date >= ?', date)
end
def self.ransackable_scopes(auth_object = nil)
if auth_object.try(:admin?)
# allow admin users access to all three methods
%i(activated hired_since salary_gt)
else
# allow other users to search on `activated` and `hired_since` only
%i(activated hired_since)
end
end
end
```
--------------------------------
### Configure Model for Multitenancy with Acts As Taggable On
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/acts-as-taggable-on.md
Enable tag scoping based on another model field, such as 'language', by using `acts_as_taggable_tenant`. This adds a second level of keying for tags.
```ruby
class Task < ApplicationRecord
acts_as_taggable_on :projects
acts_as_taggable_tenant :language
end
```
--------------------------------
### Create PostgreSQL Database
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
Command to create a PostgreSQL database named 'ransack', assuming OS X and Homebrew.
```sh
createdb ransack
```
--------------------------------
### Ransack Built-in Predicates: Start/End
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Use `_start` for searches that begin with a value and `_end` for searches that end with a value.
```ruby
# start / end — starts with / ends with
User.ransack(first_name_start: 'Rya').result.to_sql
# => SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE 'Rya%')
```
--------------------------------
### Define Ransack Alias for Associations
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/other-notes.md
Use `ransack_alias` to create shorter, more readable search parameters for attributes involving associations. This example abbreviates a combined author name search.
```ruby
class Post < ActiveRecord::Base
belongs_to :author
# Abbreviate :author_first_name_or_author_last_name to :author
ransack_alias :author, :author_first_name_or_author_last_name
end
```
--------------------------------
### Run All Checks and Tests
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
A comprehensive command to run RuboCop for style checks, the default Ransack test suite, and tests with PostgreSQL and MySQL.
```sh
bundle exec rubocop && bundle exec rake spec && DB=pg bundle exec rake spec && DB=mysql bundle exec rake spec
```
--------------------------------
### Ransacker for Integer to String Type Conversion
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/ransackers.md
Convert an integer database field to a string to enable string-based searches like 'contains' on integer fields. This example uses PostgreSQL.
```ruby
# in the model:
ransacker :id_as_string, type: :string do
Arel.sql('id::text')
end
```
--------------------------------
### Define Ransacker for Concatenated Full Name
Source: https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers
Define a ransacker to search on a concatenated full name from first and last names. This example shows basic concatenation and how to include a space.
```ruby
ransacker :full_name do |parent|
Arel::Nodes::InfixOperation.new('||',
parent.table[:first_name],
parent.table[:last_name])
end
```
```ruby
ransacker :full_name do |parent|
Arel::Nodes::InfixOperation.new('||',
Arel::Nodes::InfixOperation.new('||',
parent.table[:first_name],
' '
),
parent.table[:last_name]
)
end
```
--------------------------------
### Global Ransack Configuration
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Configure Ransack globally via an initializer. Options include changing the search key, error handling, sort indicators, whitespace stripping, and PostgreSQL sort behavior.
```ruby
# config/initializers/ransack.rb
Ransack.configure do |config|
# Change the default :q search param key
config.search_key = :query
# Raise an error for unknown predicates/attributes (default: true = ignore)
config.ignore_unknown_conditions = false
# Hide sort order arrow indicators globally
config.hide_sort_order_indicators = true
# Disable automatic whitespace stripping on string searches (default: true)
config.strip_whitespace = false
# PostgreSQL NULL sort ordering
config.postgres_fields_sort_option = :nulls_last # or :nulls_first, :nulls_always_first, :nulls_always_last
# Custom sort link arrows
config.custom_arrows = {
up_arrow: '',
down_arrow: '',
default_arrow: ''
}
# Disable boolean sanitization for custom scope arguments
config.sanitize_custom_scope_booleans = false
end
```
--------------------------------
### URL Parameter Structure for Ransack
Source: https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching
Demonstrates how to construct URL parameters for Ransack searches, including nested search conditions and sorting. This is useful when not using form helpers.
```plaintext
/users.json?q[first_name_cont]=pete&q[last_name_cont]=jack&q[s]=created_at+desc
```
--------------------------------
### Translate Predicate and Attribute Labels with I18n
Source: https://github.com/activerecord-hackery/ransack/wiki/Form-Customization
Use translation files to customize the display names for predicates and attributes in Ransack forms. Refer to the locale files in Ransack::Locale for more examples.
```yml
# locales/en.yml
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
```
--------------------------------
### Run Ransack Tests with PostgreSQL or MySQL
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
Configures and runs the Ransack test suite using PostgreSQL or MySQL databases. Ensure the 'ransack' database exists.
```sh
DB=pg bundle exec rake spec
```
```sh
DB=mysql bundle exec rake spec
```
--------------------------------
### Search JSONB Column Using Custom 'jcont' Predicate
Source: https://github.com/activerecord-hackery/ransack/wiki/PostgreSQL-JSONB-searches
Example of using the custom 'jcont' predicate to find records where a JSONB column contains a specific key-value pair. This is efficient with a GIN index.
```ruby
Person.ransack(data_jcont: '{"group": "experts"}').result.to_sql
```
--------------------------------
### Programmatic Sorting with Globalized Attributes and Joins
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/other-notes.md
For programmatic sorting on globalized attributes, let Ransack establish the initial sorting joins, then add any necessary additional joins.
```ruby
# Let Ransack handle the sorting joins first
search = Book.ransack({ s: ['category_translations_name asc'] })
results = search.result.joins(:translations)
# Or use includes for complex scenarios
search = Book.ransack({ s: ['category_translations_name asc'] })
results = search.result.includes(:translations, category: :translations)
```
--------------------------------
### Ransacker for Checking Row Existence in Another Table
Source: https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers
Defines a ransacker to check for the existence of a row in another table via a join. This example uses PostgreSQL syntax to return a boolean value indicating existence.
```ruby
# in the model:
ransacker :price_exists do |parent|
# SQL syntax for PostgreSQL -- others may differ
# This returns boolean true or false
Arel.sql("(select exists (select 1 from prices where prices.book_id = books.id))")
end
```
--------------------------------
### Sort Link for Polymorphic Associations
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
When dealing with polymorphic associations, explicitly specify the attribute name to avoid 'uninitialized constant' errors. This example sorts by an attribute of a polymorphic association named 'xxxable' of type 'Ymodel'.
```erb
<%= sort_link(@q, :xxxable_of_Ymodel_type_some_attribute, 'Attribute Name') %>
```
--------------------------------
### Configure PostgreSQL NULLS ALWAYS FIRST
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Forces null values to always be treated as the lowest value in PostgreSQL sorting.
```ruby
Ransack.configure do |c|
c.postgres_fields_sort_option = :nulls_always_first
end
```
--------------------------------
### View Helper for Existence Ransacker
Source: https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers
Provides a Haml view helper to create a select dropdown for the `price_exists` ransacker, allowing users to filter by 'Any', 'No', or 'Yes'.
```haml
%td= f.select :price_exists_true, [["Any", 2], ["No", 0], ["Yes", 1]]
```
--------------------------------
### Interactive Rebase and Force Push
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
Performs an interactive rebase on the last 10 commits for cleanup and then force pushes the changes to the remote branch.
```sh
git rebase -i HEAD~10
git push -f
```
--------------------------------
### OR Grouping in Ransack Queries
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
By default, Ransack conditions are ANDed. Pass `m: 'or'` to group all conditions with OR logic. This can be toggled via URL parameters or applied directly in console examples. It also works across associations, automatically generating LEFT OUTER JOINs.
```ruby
# controller — allow toggling OR mode from params
def index
@q = Artist.ransack(params[:q].try(:merge, m: 'or'))
@artists = @q.result
end
# console example
artists = Artist.ransack(name_cont: 'foo', style_cont: 'bar', m: 'or')
artists.result.to_sql
# => SELECT "artists".* FROM "artists"
# WHERE (("artists"."name" ILIKE '%foo%' OR "artists"."style" ILIKE '%bar%'))
# OR across associations (generates LEFT OUTER JOINs automatically)
Artist.ransack(name_cont: 'foo', musicians_email_cont: 'bar', m: 'or').result.to_sql
# => SELECT "artists".* FROM "artists"
# LEFT OUTER JOIN "memberships" ON "memberships"."artist_id" = "artists"."id"
# LEFT OUTER JOIN "musicians" ON "musicians"."id" = "memberships"."musician_id"
# WHERE (("artists"."name" ILIKE '%foo%' OR "musicians"."email" ILIKE '%bar%'))
```
--------------------------------
### Configure PostgreSQL NULLS FIRST
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Configures Ransack to use 'NULLS FIRST' for PostgreSQL sorting, ensuring null values appear before non-null values.
```ruby
Ransack.configure do |c|
c.postgres_fields_sort_option = :nulls_first
end
```
--------------------------------
### Sorting by Model Scopes
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Demonstrates how to sort by virtual fields defined as scopes in the model. The scope names should correspond to the virtual field names used in `sort_link`.
```ruby
class Person < ActiveRecord::Base
scope :sort_by_reverse_name_asc, lambda { order("REVERSE(name) ASC") }
scope :sort_by_reverse_name_desc, lambda { order("REVERSE(name) DESC") }
...
end
```
--------------------------------
### Run Ransack Test Suite
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
Executes the Ransack test suite using Rake. The default database is SQLite3.
```sh
bundle exec rake spec
```
--------------------------------
### Configure Ransack Search Key
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Change the default search parameter key from `:q` to another name, like `:query`, by setting `search_key` in an initializer.
```ruby
Ransack.configure do |c|
c.search_key = :query
end
```
--------------------------------
### Configure Custom Sort Arrows
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Globally customizes the sort order indicator arrows by defining HTML for up, down, and default arrows in an initializer file.
```ruby
Ransack.configure do |c|
c.custom_arrows = {
up_arrow: '',
down_arrow: 'U+02193',
default_arrow: ''
}
end
```
--------------------------------
### AJAX Request with Ransack Parameters
Source: https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching
Shows how to send Ransack search parameters via an AJAX request using jQuery. The `q` object mirrors the URL parameter structure.
```javascript
$.ajax({
url: "/users.json",
data: {
q: {
first_name_cont: "pete",
last_name_cont: "jack",
s: "created_at desc"
}
},
success: function (data){
console.log(data);
}
});
```
--------------------------------
### Register Custom Ransack Predicates
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Configures custom search predicates in an initializer. Supports value formatting, validation, and type casting for extended search capabilities.
```ruby
# config/initializers/ransack.rb
```
```ruby
Ransack.configure do |config|
```
```ruby
# Simple custom predicate with value formatting
```
```ruby
config.add_predicate 'equals_diddly',
arel_predicate: 'eq',
formatter: proc { |v| "#{v}-diddly" },
validator: proc { |v| v.present? },
compounds: true,
type: :string,
case_insensitive: false
```
```ruby
# Date equals — cast user string input and DB datetime to date
```
```ruby
config.add_predicate 'date_equals',
arel_predicate: 'eq',
formatter: proc { |v| v.to_date },
validator: proc { |v| v.present? },
type: :string
```
```ruby
# JSONB contains (requires ActiveRecordExtended gem)
```
```ruby
config.add_predicate 'jcont',
arel_predicate: 'contains',
formatter: proc { |v| JSON.parse(v) }
```
```ruby
end
```
```ruby
# Monkey-patch a custom Arel predicate not in the standard set
```
```ruby
module Arel
```
```ruby
module Predications
```
```ruby
def gteq_or_null(other)
```
```ruby
gteq(other).or(eq(nil))
```
```ruby
end
```
```ruby
end
```
```ruby
end
```
```ruby
Ransack.configure do |config|
```
```ruby
config.add_predicate 'gteq_or_null', arel_predicate: 'gteq_or_null'
```
```ruby
end
```
--------------------------------
### Configure Git User Information
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
Sets the global Git configuration for the contributor's name and email address, which is used in commit history.
```sh
git config --global user.name "Your Name"
git config --global user.email "contributor@example.com"
```
--------------------------------
### Ransack i18n Configuration for Labels
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Configure human-readable labels for Ransack predicates and model/attribute names using standard Rails I18n locale files.
```yaml
# config/locales/en.yml
en:
ransack:
asc: ascending
desc: descending
predicates:
cont: contains
not_cont: does not contain
start: starts with
end: ends with
eq: equals
not_eq: not equals
gt: greater than
lt: less than
blank: is blank
null: is null
models:
person: Passenger
attributes:
person:
name: Full Name
email: Email Address
article:
title: Article Title
body: Main Content
activerecord:
attributes:
namespace/article:
title: AR Namespaced Title
```
--------------------------------
### ApplicationController Search Methods
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/saving-queries.md
Defines helper methods in ApplicationController to abstract search parameter handling and provide a way to clear search parameters.
```ruby
class ApplicationController < ActionController::Base
def search_params
params[:q]
end
def clear_search_index
if params[:search_cancel]
params.delete(:search_cancel)
if(!search_params.nil?)
search_params.each do |key, param|
search_params[key] = nil
end
end
end
end
end
```
--------------------------------
### Case-Insensitive Containment (All Values)
Source: https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching
Use `i_cont_all` to find records where a field contains all specified substrings, ignoring case. This is useful for multi-term searches.
```ruby
>> User.ransack(city_i_cont_all: %w(Grand Rapids)).result.to_sql
=> SELECT "users".* FROM "users" WHERE ((LOWER("users"."city") LIKE '%grand%' AND LOWER("users"."city") LIKE '%rapids%'))
```
--------------------------------
### Index Action with Ransack Search
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/saving-queries.md
This code snippet shows a typical index action in a Rails controller that initializes a Ransack search object and sets a default sort column.
```ruby
def index
@search = ComponentDefinition.search(search_params)
# make name the default sort column
@search.sorts = 'name' if @search.sorts.empty?
@component_definitions = @search.result().page(params[:page])
end
```
--------------------------------
### Ransack Built-in Predicates: Null/Blank Checks
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Use `_null` to check for NULL values and `_not_null` to check for non-NULL values. `_present` checks for non-NULL and non-empty string, while `_blank` checks for NULL or empty string.
```ruby
# null / not_null — IS NULL / IS NOT NULL
User.ransack(first_name_null: 1).result.to_sql
# => SELECT "users".* FROM "users" WHERE "users"."first_name" IS NULL
# present / blank — not null and not empty string
User.ransack(first_name_present: '1').result.to_sql
# => SELECT "users".* FROM "users" WHERE (("users"."first_name" IS NOT NULL AND "users"."first_name" != ''))
```
--------------------------------
### Ransack Built-in Predicates: Equality
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Use `_eq` for exact equality and `_not_eq` for inequality.
```ruby
# eq / not_eq — exact equality
User.ransack(first_name_eq: 'Ryan').result.to_sql
# => SELECT "users".* FROM "users" WHERE "users"."first_name" = 'Ryan'
```
--------------------------------
### Run Specific Ransack Test File
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
Executes the Ransack test suite for a particular file. Replace `` with the actual file path.
```sh
bundle exec rspec spec/ransack/search_spec.rb
```
--------------------------------
### Polymorphic Search with Namespaced Models
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/polymorphic-search.md
Shows how to perform polymorphic searches when the associated model is namespaced. Use a quoted string with Ruby module notation for the type.
```ruby
Location.ransack('locatable_of_Residences::House_type_number_eq' => 100).result
```
--------------------------------
### Release to RubyGems
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/release_process.md
Commands to build and release the Ransack gem to RubyGems. Ensure you are signed in to RubyGems.
```bash
gem signin
rake build
rake release
```
--------------------------------
### Basic Sort Link
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Generates a sortable link for the specified attribute. Clicking this link will toggle the sort order for the 'name' attribute.
```erb
<%= sort_link(@q, :name) %>
```
--------------------------------
### Ransack Search: Match Exact Key Combinations
Source: https://github.com/activerecord-hackery/ransack/wiki/How-to-search-on-ActsAsTaggableOn-fields
Use `_eq` predicate to match exact combinations of tags. This is useful when searching for a specific set of tags and no others.
```erb
<%= f.text_field :projects_name_eq %>
```
--------------------------------
### Add Sorting Links to View
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/sorting.md
Use the `sort_link` helper within your table headers to create clickable links for sorting. This requires the Ransack search object `@q` to be available in the view.
```erb
| <%= sort_link(@q, :title, "Title") %> |
<%= sort_link(@q, :category, "Category") %> |
<%= sort_link(@q, :created_at, "Created at") %> |
<% @posts.each do |post| %>
| <%= post.title %> |
<%= post.category %> |
<%= post.created_at.to_s(:long) %> |
<% end %>
```
--------------------------------
### Programmatic Sorting with Globalized Attributes
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/i18n.md
When sorting programmatically on translated attributes of associations, let Ransack handle the initial joins. Add any additional required joins afterward or use `includes` to ensure translations are loaded.
```ruby
# Instead of joining translations first, let Ransack handle the joins:
search = Book.ransack({ s: ['category_translations_name asc'] })
results = search.result.joins(:translations)
# Or use the includes method to ensure all necessary translations are loaded:
search = Book.ransack({ s: ['category_translations_name asc'] })
results = search.result.includes(:translations, category: :translations)
# For more complex scenarios, you can manually specify the joins:
search = Book.ransack({ s: ['category_translations_name asc'] })
results = search.result
.joins(:translations)
.joins(category: :translations)
```
--------------------------------
### Configure PostgreSQL NULLS LAST
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Configures Ransack to use 'NULLS LAST' for PostgreSQL sorting, ensuring null values appear after non-null values.
```ruby
Ransack.configure do |c|
c.postgres_fields_sort_option = :nulls_last
end
```
--------------------------------
### Run Single Test in Ransack File
Source: https://github.com/activerecord-hackery/ransack/blob/main/CONTRIBUTING.md
Runs a specific test case within a Ransack test file. Use the `-e` flag followed by the test name.
```sh
bundle exec rspec spec/ransack/search_spec.rb -e "accepts a context option"
```
--------------------------------
### Use Bleeding Edge Ransack from GitHub
Source: https://github.com/activerecord-hackery/ransack/blob/main/README.md
To use the latest updates not yet published to RubyGems, specify the GitHub repository and branch in your Gemfile.
```ruby
gem 'ransack', :github => 'activerecord-hackery/ransack', :branch => 'main'
```
--------------------------------
### Set Multiple Default Sort Orders in Controller
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/sorting.md
Configure multiple default sort orders by passing an array of sort strings to the `sorts` attribute. Ransack will apply them in the order provided.
```ruby
class PostsController < ActionController::Base
def index
@q = Post.ransack(params[:q])
@q.sorts = ['title asc', 'created_at desc'] if @q.sorts.empty?
@posts = @q.result(distinct: true)
end
end
```
--------------------------------
### Sort Link with Multiple Default Orders
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Configures sorting by multiple fields with specific default orders. Initially, 'last_name' will be sorted ascending and 'first_name' descending.
```erb
<%= sort_link(@q, :last_name, %i(last_name first_name),
default_order: { last_name: 'asc', first_name: 'desc' }) %>
```
--------------------------------
### Set Default Multiple Sort Orders in Controller
Source: https://github.com/activerecord-hackery/ransack/wiki/Sorting-in-the-Controller
Configure multiple default sort fields and orders if no sorts are already specified. This allows for more complex default sorting logic.
```ruby
@search = Post.ransack(params[:q])
@search.sorts = ['name asc', 'created_at desc'] if @search.sorts.empty?
@posts = @search.result.paginate(page: params[:page], per_page: 20)
```
--------------------------------
### Generated SQL for Merged Searches
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/merging-searches.md
This SQL demonstrates how the Ransack gem constructs a query to find records matching multiple, potentially complex, conditions by using joins and an OR clause.
```sql
SELECT "people".*
FROM "people"
LEFT OUTER JOIN "people" "parents_people"
ON "parents_people"."id" = "people"."parent_id"
LEFT OUTER JOIN "people" "children_people"
ON "children_people"."parent_id" = "people"."id"
WHERE (
("parents_people"."name" = 'A' OR "children_people"."name" = 'B')
)
ORDER BY "people"."id" DESC
```
--------------------------------
### Ransack Built-in Predicates: Numeric Comparisons
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Use `_lt` (less than), `_lteq` (less than or equal to), `_gt` (greater than), and `_gteq` (greater than or equal to) for numeric comparisons.
```ruby
# lt / lteq / gt / gteq — numeric comparisons
User.ransack(age_lt: 25).result.to_sql
# => SELECT "users".* FROM "users" WHERE ("users"."age" < 25)
User.ransack(age_lteq: 25).result.to_sql
# => SELECT "users".* FROM "users" WHERE ("users"."age" <= 25)
```
--------------------------------
### Ransacker for Querying Associated Model by Name
Source: https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers
Demonstrates how to query a `SalesAccount` model based on the name of its associated `sales_rep` user. This requires joining the `sales_rep` association.
```ruby
# in the model:
class SalesAccount < ActiveRecord::Base
belongs_to :user
belongs_to :sales_rep, class_name: :User
# in the controller:
# The line below would lead to errors thrown later if not for the
# "joins(:sales_reps)".
@q = SalesAccount.includes(:user).joins(:sales_rep).ransack(params[:q])
@sales_accounts = @q.result(distinct: true)
```
--------------------------------
### Add Controller Action for Advanced Search
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/advanced-mode.md
Implement a 'search' action in your controller that calls the 'index' method and then renders the 'index' view. This action is invoked by the custom route defined for advanced search.
```ruby
def search
index
render :index
end
```
--------------------------------
### Configure PostgreSQL NULLS ALWAYS LAST
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Forces null values to always be treated as the highest value in PostgreSQL sorting.
```ruby
Ransack.configure do |c|
c.postgres_fields_sort_option = :nulls_always_last
end
```
--------------------------------
### Ransack Built-in Predicates: String Contains
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Use `_cont` for LIKE '%value%' searches and `_i_cont` for case-insensitive LIKE searches using LOWER().
```ruby
# cont / not_cont — LIKE '%value%'
User.ransack(first_name_cont: 'Rya').result.to_sql
# => SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%')
# i_cont — case-insensitive LIKE (uses LOWER())
User.ransack(first_name_i_cont: 'rya').result.to_sql
# => SELECT "users".* FROM "users" WHERE (LOWER("users"."first_name") LIKE '%rya%')
```
--------------------------------
### Generate Sort URL with Multiple Default Orders
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/getting-started/simple-mode.md
Generates a sort URL with multiple default sort orders specified, mirroring the behavior of `sort_link` with multiple default orders.
```erb
<%= sort_url(@q, :last_name, %i(last_name first_name),
default_order: { last_name: 'asc', first_name: 'desc' }) %>
```
--------------------------------
### Ransack Built-in Predicates: Raw LIKE Pattern
Source: https://context7.com/activerecord-hackery/ransack/llms.txt
Use `_matches` for raw LIKE pattern matching without auto-added wildcards, and `_does_not_match` for the inverse.
```ruby
# matches / does_not_match — raw LIKE pattern (no auto-wildcards)
User.ransack(first_name_matches: 'Ryan').result.to_sql
# => SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE 'Ryan')
```
--------------------------------
### Handle Distinct Selects with Group and Includes (PostgreSQL)
Source: https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/other-notes.md
For PostgreSQL, an alternative to `distinct: true` is to use `.group` on the primary key along with `.includes` to avoid duplicate rows.
```ruby
def index
@q = Person.ransack(params[:q])
@people = @q.result
.group('persons.id')
.includes(:articles)
.page(params[:page])
end
```