Mai Nguyen
Mai Nguyen

Reputation: 45

Use ransack to find objects whose array attribute contain a specific string

Model A has attribute "languages", which is an array contains element such as "English", "French". My site has a form which allows user to select a language and it will display all object whose "languages" includes that language.

How to design my controller and view to do that? From the docs, there are ways to check if an element is in a query array, not the other way round.

Upvotes: 1

Views: 2980

Answers (2)

ga6ix
ga6ix

Reputation: 41

Another way, maybe more easier is with scope, for example:

First all, define a scope in your model:

scope_languages_include, -> (*languages) {where("languages && '{#{languages.to_s.delete("[]")}}'")}

It's important define the argument with *

Second in the same model, you need define a private method that permit to ransack use scopes.

def self.ransackable_scopes(auth_object = nil)
  %w(lenguages_include)
end

In the last step define the search_form_for:

 <%= search_form_for @q, url: some_path  do |f| %>
   <% LANGUAGE::ALL.each do |lang| %>
     <%= check_box_tag 'q[scope_languages_include][]', lang %>
     <%= lang %>
   <% end %>
 <% end %>

This code is in Rails 5.

Happy coding ;)

Upvotes: 3

Lucas Moulin
Lucas Moulin

Reputation: 2530

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.

Upvotes: 2

Related Questions