How to search array through ransack gem?
I met the same problem as you do. I'm using Rails 5, and I need to search an array of roles
in User
table
It seems that you have already add postgres_ext gem
in your gemfile, but it has some problems if you are using it in Rails 5 application.
So it is a choice for you to add a contain
query in Arel Node by yourself instead of using postgres_ext gem
And if you are using other version of Rails, I think it works well too.
I have an User
model, and an array attribute roles
. What I want to do is to use ransack
to search roles
. It is the same condition like yours.
ransack
can't search array.
But PostgresSQL
can search array like this:
User.where("roles @> ?", '{admin}').to_sql)
it produce the sql query like this:
SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND (roles @> '{admin}')
So what I want to do is to add a similar contains query in Arel Nodes
You can do it this way:
# app/config/initializers/arel.rb
require 'arel/nodes/binary'
require 'arel/predications'
require 'arel/visitors/postgresql'
module Arel
class Nodes::ContainsArray < Arel::Nodes::Binary
def operator
:"@>"
end
end
class Visitors::PostgreSQL
private
def visit_Arel_Nodes_ContainsArray(o, collector)
infix_value o, collector, ' @> '
end
end
module Predications
def contains(other)
Nodes::ContainsArray.new self, Nodes.build_quoted(other, self)
end
end
end
Because you can custom ransack predicate,
so add contains
Ransack predicate like this:
# app/config/initializers/ransack.rb
Ransack.configure do |config|
config.add_predicate 'contains',
arel_predicate: 'contains',
formatter: proc { |v| "{#{v}}" },
validator: proc { |v| v.present? },
type: :string
end
Done!
Now, you can search array:
User.ransack(roles_contains: 'admin')
The SQL query will be like this:
SELECT \"users\".* FROM \"users\" WHERE \"users\".\"deleted_at\" IS NULL AND (\"users\".\"roles\" @> '{[\"admin\"]}')
Yeah!
Search an array of values with Ransack
I ended up using a custom Ransacker
for this case:
ransacker :rep_code_list do
Arel.sql("array_to_string(rep_code_list, ',')")
end
This will turn the array into a string so that Ransack can search with the cont
predicate. Not sure if this is the best way to do it but it worked for my case.
How does ransack search works on an array list?
If you want to search the entire list of users, you could do something like this:
@q = User.ransack(params[:q])
@users = @q.result.page(params[:page])
You want to call ransack
on your model prior to adding pagination. Once you have the ransack result, you can add pagination. This section of the documentation shows you how to handle pagination with ransack. In its most basic form, this is how you can use ransack.
Also, it looks like you have some odd code in your example. Apologies if I'm misunderstanding what you're trying to do.
When you call emails.map{|a| User.where(email: a).first}
, you're making a where query 3 times in this case and returning an array of 3 models. Ransack won't operate on that array.
I would change it to something like this in your case:
emails = ["abc@abc.com", "a@a.com", "b@b.com"]
@q = User.where(email: emails).ransack(params[:q])
@checked_in_users = @q.result.page(params[:page])
Just know that you'd be searching from an array of users with emails of "abc@abc.com", "a@a.com", and "b@b.com". If you search with your ransack form for "bob@example.com", you wouldn't get any search results. This may not be what you want.
Rails Ransack gem: search for multiple values with one condition
If you look over Ransack's Search Matchers you will see one with *_in - match any values in array
, which is what you need if you want to search in arrays.
Because your event_ids
can come in either as a string or an array and *_in
requires and array, we have to make sure we always feed it an array.
[event_ids].flatten # returns an array all the time
The query below should works properly now.
ransack("job_name_cont" => job_name, "event_id_in" => [event_ids].flatten).result
Use ransack to find objects whose array attribute contain a specific string
I just answered this on another question, I will add the answer here too for future reference.
As discussed on this issue you need to add the gem postgres_ext to your project:
# Gemfile
gem 'postgres_ext'
And add this to an initializer:
# config/initializers/ransack.rb
Ransack.configure do |config|
%w[
contained_within
contained_within_or_equals
contains
contains_or_equals
overlap
].each do |p|
config.add_predicate p, arel_predicate: p, wants_array: true
end
end
After that you'll be able to use contains
in a serialized array.
Ransack exact match with array values
I am answering my own question.
It may vary to the requirement.
I had to take the user params and search in the database if any exact data matches then put the user in same group else make a new group with the searched data and at the end save each searched data for respective user also.
As all the fields were multi select dropdowns checkboxes etc all params was coming as an array of strings.
My workaround for the problem:
1. sorted the array params and joined it with comma and made string.
ex:
a = [1,2,3,4,5,6]
a.sort.join(',')
"1,2,3,4,5,6"
I stored this string in the database column which is in text.
No when user searches for a group I take its params and convert it again in comma separated string and using where clause query to database is done.
In UI I convert this string to array again and show it to user.
I dont know its a correct way of doing it or not but it is working for me.
still any good solutions are welcome.
Related Topics
Bundle Install/Error in Installing Libv8 (3.3.10.4) on Rails (Running on Lion)
Get All Variables Defined Through 'Attr_Accessor' Without Overriding 'Attr_Accessor'
How to Convert a Nested Hash into Xml Using Nokogiri
Open-Uri Returning Ascii-8Bit from Webpage Encoded in Iso-8859
You Don't Have Write Permissions into the /Var/Lib/Gems/1.9.1 Directory
Serialize Ruby Object to JSON and Back
Rails Routes: Get Without Param :Id
Ruby 1.9.2 - Read and Parse a Remote CSV
Clicking a Button with Ruby Mechanize
Split a String into Chunks of Specified Size Without Breaking Words
How to Set Environment Variable Using Chef
Activerecords Select(:Id).Collect VS. Pluck(:Id) Methods: Why Is Pure Ar "Pluck" Slower
Configuration in Allure to Cucumber in Ruby
Rbenv Installed Ruby 2.1.2 Cannot Load Such File -- Zlib on MAC Osx 10.9.2
How to Stub a Method of an Included Module with Rspec
Ruby Not Finding New Version of Openssl