Reputation: 155
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
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
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
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