Using Predicates
The primary method of searching in Ransack is by using what is known as predicates.
Predicates are used within Ransack search queries to determine what information to
match. For instance, the cont
predicate will check to see if an attribute called
"first_name" contains a value using a wildcard query:
>> User.ransack(first_name_cont: 'Rya').result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%')
You can also combine predicates for OR queries:
>> User.ransack(first_name_or_last_name_cont: 'Rya').result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%'
OR "users"."last_name" LIKE '%Rya%')
The syntax for OR
queries on an associated model is not immediately obvious, but makes sense. Assuming a User
has_one
Account
and the Account
has attributes
foo
and bar
:
>> 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%')
Below is a list of the built-in predicates of Ransack and their opposites. You may already be familiar with some of the predicates, as they also exist in the ARel library.
If you want to add your own, please see the [[Custom-Predicates|Custom Predicates]] page.
Please note: any attempt to use a predicate for an attribute that does not exist will
silently fail. For instance, this will not work when there is no name
attribute:
>> User.ransack(name_cont: 'Rya').result.to_sql
=> "SELECT "users".* FROM "users"
eq (equals)
The eq
predicate returns all records where a field is exactly equal to a given value:
>> User.ransack(first_name_eq: 'Ryan').result.to_sql
=> SELECT "users".* FROM "users" WHERE "users"."first_name" = 'Ryan'
Opposite: not_eq
matches
The matches
predicate returns all records where a field is like a given value:
>> User.ransack(first_name_matches: 'Ryan').result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE 'Ryan')
On Postgres, the case-insensitive ILIKE will be used.
Opposite: does_not_match
Note: If you want to do wildcard matching, you may be looking for the cont
/not_cont
predicates instead.
lt (less than)
The lt
predicate returns all records where a field is less than a given value:
>> User.ransack(age_lt: 25).result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."age" < 25)
Opposite: gteq
(greater than or equal to)
lteq (less than or equal to)
The lteq
predicate returns all records where a field is less than or equal to a given value:
>> User.ransack(age_lteq: 25).result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."age" <= 25)
Opposite: gt
(greater than)
in
The in
predicate returns all records where a field is within a specified list:
>> User.ransack(age_in: 20..25).result.to_sql
=> SELECT "users".* FROM "users" WHERE "users"."age" IN (20, 21, 22, 23, 24, 25)
It can also take an array:
>> User.ransack(age_in: [20, 21, 22, 23, 24, 25]).result.to_sql
=> SELECT "users".* FROM "users" WHERE "users"."age" IN (20, 21, 22, 23, 24, 25)
Opposite: not_in
cont
The cont
predicate returns all records where a field contains a given value:
>> User.ransack(first_name_cont: 'Rya').result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%')
Opposite: not_cont
cont_any (contains any)
The cont_any
predicate returns all records where a field contains any of the given values:
>> User.ransack(first_name_cont_any: %w(Rya Lis)).result.to_sql
=> SELECT "users".* FROM "users" WHERE (("users"."first_name" LIKE '%Rya%' OR "users"."first_name" LIKE '%Lis%'))
Opposite: not_cont_any
cont_all (contains all)
The cont_all
predicate returns all records where a field contains all of the given values:
>> User.ransack(city_cont_all: %w(Grand Rapids)).result.to_sql
=> SELECT "users".* FROM "users" WHERE (("users"."city" LIKE '%Grand%' AND "users"."city" LIKE '%Rapids%'))
Opposite: not_cont_all
i_cont
The i_cont
case-insensitive predicate returns all records where a field contains a given value and ignores case:
>> User.ransack(first_name_i_cont: 'Rya').result.to_sql
=> SELECT "users".* FROM "users" WHERE (LOWER("users"."first_name") LIKE '%rya%')
Opposite: not_i_cont
i_cont_any
The i_cont_any
case-insensitive predicate returns all records where a field contains any of the given values and ignores case:
>> User.ransack(first_name_i_cont_any: %w(Rya Lis)).result.to_sql
=> SELECT "users".* FROM "users" WHERE ((LOWER("users"."first_name") LIKE '%rya%' OR LOWER("users"."first_name") LIKE '%lis%'))
Opposite: not_i_cont_any
i_cont_all
The i_cont_all
case-insensitive predicate returns all records where a field contains all of the given values and ignores case:
>> 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%'))
Opposite: not_i_cont_all
start (starts with)
The start
predicate returns all records where a field begins with a given value:
>> User.ransack(first_name_start: 'Rya').result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE 'Rya%')
Opposite: not_start
end (ends with)
The end
predicate returns all records where a field ends with a given value:
>> User.ransack(first_name_end: 'yan').result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%yan')
Opposite: not_end
true
The true
predicate returns all records where a field is true. The '1' indicates that
to Ransack that you indeed want to check the truthiness of this field. The other truthy
values are 'true', 'TRUE', 't' or 'T'.
>> User.ransack(awesome_true: '1').result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."awesome" = 't')
Note: different database systems use different values to represent truth. In the above example, we are using SQLite3.
Opposite: not_true
false
The false
predicate returns all records where a field is false.
>> User.ransack(awesome_false: '1').result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."awesome" = 'f')
Opposite: not_false
Note: the false
predicate may be considered the opposite of the true
predicate if the field does not contain null
values. Otherwise, use not_false
.
present
The present
predicate returns all records where a field is present (not null and not a
blank 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" != ''))
Opposite: blank
null
The null
predicate returns all records where a field is null:
>> User.ransack(first_name_null: 1).result.to_sql
=> SELECT "users".* FROM "users" WHERE "users"."first_name" IS NULL
Opposite: not_null
URL parameter structure
The search parameters are passed to ransack as a hash. The URL representation of this hash uses the bracket notation: hash_name[key]=value
. The hash_name is the parameter which is defined in the controller, for instance q
. The key is the attribute and search predicate compound, for instance first_name_cont
, the value is the search parameter. When searching without using the search form helpers this URL structure needs to be created manually.
For example, the URL layout for searching and sorting users could looks like this:
/users.json?q[first_name_cont]=pete&q[last_name_cont]=jack&q[s]=created_at+desc
Note that the sorting parameter s
is nested within the q
hash.
When using JavaScript to create such a URL, a matching jQuery request could look like this:
$.ajax({
url: "/users.json",
data: {
q: {
first_name_cont: "pete",
last_name_cont: "jack",
s: "created_at desc"
}
},
success: function (data){
console.log(data);
}
});