user3735111
user3735111

Reputation: 155

Rails country select dropdown for search: how to show priority countries at the top

I want to perform a custom search and want to pass the country as one of the options to perform the search. My controller action for the search looks like this:

@articles = Article.filter(params.slice(:category, :country, :src_url, :date, :lang, :keywords, :title))
.where(is_active: true)
.paginate(:page => params[:page])

And my model contains all these scopes (example: scope :country, -> (country) { where country: country }

So I've tried a few options, and so far didn't find one that I would be satisfied with completely.

Option 1:

<%= select_tag :country, options_from_collection_for_select(ISO3166::Country.countries.sort_by(&:name), 'name', 'name', params[:country]), :include_blank => true %>

Pros: Almost what I want - clean and short.

Cons: Can't figure out how is it working, really. I found it somewhere and modified a little using trial and error. But I didn't manage to find any documentation that would point on why and how it works, and with trial and error I can only go as far. From this comes the issue - I can't modify it to show particular countries on top of the list and rest sorted below.

Option 2:

<%= country_select(nil, :country, { priority_countries: %w(RU BR IN CN ZA), include_blank: true, selected: params[:country] }, {}) %>

Pros: It does exactly what I want with 1 exception.

Cons: It requires something called "user" as first argument, which I have set to as nil, and it leads to weird behavior in GET - it passes '%5Bcountry%5D=' instead of simply 'country=' and I don't like it. I didn't find a way to get rid of it or work around it.

Any suggestions of how to do it better / cleaner?

Upvotes: 0

Views: 3929

Answers (3)

Reco Daley
Reco Daley

Reputation: 129

Am using rails 5.1.6 and this is the solution that worked for me.

Put the following in your Gemfile:

# country list
gem 'country_select'

On the command line, Install as a gem using:

gem install country_select

In your form view write:

<%= form.country_select :country, ([ "GB", "FR", "DE" ]), iso_codes: true, id: :element_id, class:"col-lg-12 col-md-12 col-sm-12 col-12" %>

In my model I added:

def country_name
 country = Country[country_code]
 country.translations[I18n.locale.to_s] || country.name
end

Upvotes: 1

Alexander Luna
Alexander Luna

Reputation: 5449

You can use the country_select gem and use it in your form like this:

<%= form_for @article do |f| %>
  <%= f.country_select :country_code %>
<% end %>

If you don't want to use a gem, you can create a Ruby object that stores a list of all the countries with their abbreviation. Here is a ruby hash that you can use in your views:

https://github.com/karmi/localized_country_select/blob/master/locale/en.rb

Just copy it into your project and use it in your view. I suggest you read Rails documentation about forms or else you might have problems in the future:

http://guides.rubyonrails.org/form_helpers.html

Upvotes: 0

ichigolas
ichigolas

Reputation: 7725

In option 1 you are passing a collection ISO3166::Country.countries.sort_by(&:name) to options_from_collection_for_select. As you can see you have applied a sorting by name to the collection. It would be a matter of sorting your options as you want using sort_by.

PRIORITY_COUNTRIES = %w[RU BR IN CN ZA]

countries = ISO3166::Country.countries.sort_by do |country|
  priority_index = PRIORITY_COUNTRIES.index(country.alpha2)
  priority_index.present? ? priority_index.to_s : country.name
end

Note that I convert the index to string to be able to compare that to the country name.

https://ruby-doc.org/core-2.4.1/Enumerable.html#method-i-sort_by

Upvotes: 0

Related Questions