I would like to create a dropdown menu for a list of countries in my signup page with devise. I understand that I need to create a migration
rails g migration add_countries_to_user country:string
and then I have to use create the form in my view page
<%= f.select :countries, options_for_select(%w[Alfganistan, Albania, Algeria...]) %>
I would like to know if my form correct and where can I put the countries list in because it is not right to write 200+ countries in the view page right?
Thanks.
As suggested, you can use country_select. Or, you can do it on your own as:
Create an initializer which contains list of countries (or anything in particular you want) config/initializers/countries.yml
countries:
- Afghanistan
- United States
- ...
Load it in database by creating a rake task as:
lib/tasks/load_countries.rb
namespace :db do
desc "Loads countries in database"
task :load_countries => :environment do |t|
countries_list = YAML.load("#{Rails.root}/config/initializers/countries.yml")['countries']
countries.each do |country|
Country.find_or_create_by_name(country)
end
end
end
Whenever you add any countries in yml, you can populate it by invoking this rake task: rake db:load_countries.
Maintain a model Country :
class Country < ActiveRecord::Base
validates :name, presence: true, uniqueness: { case_insensitive: true }
end
I am considering that a user belongs_to 1 country above, and a country has_many users. In your view, :
f.select :country, options_from_collection_for_select(Country.all, :id, :name)
Note: I am using association approach above, since it will make it easier to make queries against this field in future, unlike saving an actual string in user.
Use the country_select gem.
# Gemfile
gem 'country_select'
form:
country_select("user", "country")
Apart from gem and Countries read from YML.
One more option is creating a method in your helper
File : app/helpers/country_helper.rb
def get_countries
{:1=>Africa,:2=>"America"}
end
In Views you can use this way
<%= options_from_collection_for_select(get_countries, :id, :name) %>
Look up rails cast #88 revised dynamic select menus. What you need is method call grouped_collection_select in which you will map out the item you need based on how they corresponded to one another
You could do this as a helper method. eg, in your users_helper.rb you could list the selections:
def country_options
[
['Afghanistan'],
['Albania'],
...
['Zimbabwe']
]
end
Then, your selector pulls from that helper method:
<%= f.select :country, options_for_select(country_options), { prompt: 'Choose Country' } %>
Related
I have a roles table with an attribute :name in it.
I'm trying to use a list of role names in a collection select. Instead of listing the :name in the way it is recorded in the database, I want to present it neatly.
For example, :name has an instance stored as :admin in the database. I want to present that in the collection select as 'Administrator'.
I tried to write a roles helper that says:
module RolesHelper
def text_for_role(name)
case name
when 'guest'
'Guest - Trial Account'
when 'admin'
'Administrator'
when 'representative'
'Representative'
etc, etc
but this option isn't going to work in this context, because I want to list all the roles, but refer to them written nicely.
I have this collection select:
<%= select_tag "roles", options_from_collection_for_select(#roles, "id", "<%= text_for_role(name)%>"), :multiple => true, :class => 'chosen-select form-control' %>
Can anyone see how I can write a helper or a presenter that can be used on the whole list of collection select options?
create a class level variable like:
class MyClass
ROLES = [
['Guest - Trial Account' ,'guest' ],
['Administrator' , 'admin'],
['Representative' , 'representative']
]
end
Then access them on the view:
<%= select_tag 'roles', MyClass::ROLES %>
More Info : Here
I'm working on a code base that I'm not very familiar with, specifically Haml. I need to set-up a select dropdown to select a user.
I have the following code in my controller:
def edit
#franchise = Franchise.find params[:id]
#ab_reps = User.where role: "admin-ab"
authorize! :update, #franchise
end
I have the following code in my form (that doesn't currently work):
= f.select :ab_rep, options_for_select(#ab_reps, f.object.ab_rep), {prompt: "AB Representative"}, {label: false, right_class: "col-sm-10", class: "ab-rep-field"}
Couple questions:
1.) #ab_reps is an array of user objects. I have the following method in my user model:
def name
[first_name, last_name].compact.join(" ")
end
How do I get the select to display the user names instead of the user objects (which it currently does) ?
2.) Is my current set-up even close to being correct?
Thanks for your help!
You are close, you need to provide the methods for the option value and the option text, as well as the collection which in your case is #ab_reps. Additionally you can provide a hash for prompts and for html_options such as class names, which you've done.
Rails has a few different helpers you can use for select tags including options_from_collection_for_select. I've used collection_select often, http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select
= f.collection_select :ab_rep, #ab_reps, :id, :name, {prompt: "AB Representative"}
I am trying to use collection_select tag for the default _form.html.erb using a concern/module, I need to set a hash including some department names.
Here is my app/models/concerns/SetDepartment.rb
module Set_Department
extend ActiveSupport :: Concern
def department
department {
1=>"Amatitlán",
2=>"Chinautla",
3=>"Chuarrancho"
}
end
end
Here is the model where I want to call the department method:
class Aplicante < ActiveRecord::Base
include SetDepartment
validates :titulo_id, :primer_nombre,
:primer_apellido, :dpi, :direccion_linea_1,:zona, :department_id, :username,
presence: true
validates :dpi,:username, uniqueness: true
has_secure_password
end
Now, I need to include this hash in a collection_select tag on my app/views/applicants/_form.html.erb
#...
<div class="field">
<%= f.label :department_id %><br>
<%= f.collection_select :department_id, Aplicante.department, Aplicante.department %>
</div>
#...
Obviously, this does not work but I can not think on anything else.
I have searched through the internet but I just get tough explinations and none of them involves a module... is it even possible?
Solved!
I was using the wrong method..
We can not use a collection_select helper with a hash, instead, we need to use the regular select method.
Collection_select is used when you have two models and you want to combine their different values in a drop down menu.
Information about how to use the select tag with a hash here:
http://apidock.com/rails/ActionView/Helpers/FormTagHelper/select_tag
I am creating a scaffold -
rails g scaffold Contact email:string email_provider:string
but I want the email provider to be a drop down (with gmail/yahoo/msn as options) and not a text field. How can I do this ?
You can take a look at the Rails documentation . Anyways , in your form :
<%= f.collection_select :provider_id, Provider.order(:name),:id,:name, include_blank: true %>
As you can guess , you should predefine email-providers in another model -Provider , to have where to select them from .
Or for custom options
<%= f.select :desired_attribute, ['option1', 'option2']%>
You create the collection in the Contact controller -
app/controllers/contacts_controller.erb
Adding
#providers = Provider.all.by_name
to the new, create and edit methods, using a scope for the by_name in the Provider model - app/models/provider.rb - for the ordering by name
scope by_name order(:name)
Then in the view - app/views/contacts/_form.html.erb - you use
<%= f.collection_select :provider_id, #providers, :id, :name, include_blank: true %>
For rails forms, I also strongly recommend you look at a form builder like simple_form - https://github.com/plataformatec/simple_form - which will do all the heavy lifting.
This is a long way round, but if you have not yet implemented then you can originally create your models this way. The method below describes altering an existing database.
1) Create a new model for the email providers:
$ rails g model provider name
2) This will create your model with a name string and timestamps. It also creates the migration which we need to add to the schema with:
$ rake db:migrate
3) Add a migration to add the providers ID into the Contact:
$ rails g migration AddProviderRefToContacts provider:references
4) Go over the migration file to check it look OK, and migrate that too:
$ rake db:migrate
5) Okay, now we have a provider_id, we no longer need the original email_provider string:
$ rails g migration RemoveEmailProviderFromContacts
6) Inside the migration file, add the change which will look something like:
class RemoveEmailProviderFromContacts < ActiveRecord::Migration
def change
remove_column :contacts, :email_provider
end
end
7) Once that is done, migrate the change:
$ rake db:migrate
8) Let's take this moment to update our models:
Contact: belongs_to :provider
Provider: has_many :contacts
9) Then, we set up the drop down logic in the _form.html.erb partial in the views:
<div class="field">
<%= f.label :provider %><br>
<%= f.collection_select :provider_id, Provider.all, :id, :name %>
</div>
10) Finally, we need to add the provders themselves. One way top do that would be to use the seed file:
Provider.destroy_all
gmail = Provider.create!(name: "gmail")
yahoo = Provider.create!(name: "yahoo")
msn = Provider.create!(name: "msn")
$ rake db:seed
<%= f.select :email_provider, ["gmail","yahoo","msn"]%>
Please have a look here
Either you can use rails tag Or use plain HTML tags
Rails tag
<%= select("Contact", "email_provider", Contact::PROVIDERS, {:include_blank => true}) %>
*above line of code would become HTML code(HTML Tag), find it below *
HTML tag
<select name="Contact[email_provider]">
<option></option>
<option>yahoo</option>
<option>gmail</option>
<option>msn</option>
</select>
Rails drop down using has_many association for article and category:
has_many :articles
belongs_to :category
<%= form.select :category_id,Category.all.pluck(:name,:id),{prompt:'select'},{class: "form-control"}%>
In your model,
class Contact
self.email_providers = %w[Gmail Yahoo MSN]
validates :email_provider, :inclusion => email_providers
end
In your form,
<%= f.select :email_provider,
options_for_select(Contact.email_providers, #contact.email_provider) %>
the second arg of the options_for_select will have any current email_provider selected.
I wanted to display one thing (human readable) but store another (an integer id).
Small example
Here's a small example that helped:
<%= form.select(:attribute_name, {cat: 5, dog: 3} )%>
The {cat: 5, dog: 3} will display "cat" and "dog", but save 5 and 3.
Real world example
Here's the actual use case. It displays the names of sellers (that humans can read), but saves the sellers' id (an integer):
<div class="field">
<%= form.label :seller_id %>
<%= form.select :seller_id, seller_names_and_ids(), {include_blank: true}, {required: true, class: "form-control"} %>
</div>
And the helper is defined as:
def seller_names_and_ids
# We want this to produce a hash of keys (the thing to display) and values (the thing to save,
# in thise case the seller_id integer)
sellers = Seller.all
h = {}
sellers.each do |seller|
thing_to_display = seller.name + " (" + seller.id.to_s + ")"
thing_to_save_in_db = seller.id
h.store(thing_to_display, thing_to_save_in_db)
end
h
end
I have checked some tutorials but I got confused by the parameters in this method
collection_select (object, attribute, collection, value_method, text_method, options = {}, html_options ={})
I have a map model includes: :area, :system, :file
and I want to read :area from database to a drop down list, and let user choose one
I already did #map = Map.all in the view
what the method should be?
especially the parameter "attribute". In a lot tutorials, people put "id" here. But I don't know what "id" is, and in my situation I don't need any other value, just the "area".
Im not exactly sure what you are asking here but if you are trying to make a dropdown selection for use in an html form will this example help you at all?
<% nations = {'United States of America' => 'USA', 'Canada' => 'Canada', 'Mexico' => 'Mexico', 'United Kingdom'=> 'UK'} %>
<% list = nations.sort %>
<%= f.select :country, list, %>
Here nations is a hash of countries then list becomes the sorted copy of that hash. An html dropdown is then created as a part of the form "f". ":country" is the part of the model that the data is connected to while list is the options to populate the dropdown with
It's not clear from your question what the model is that's being populated with the area.
Typically, collection_select is used between related models.
eg.
class Category < ActiveRecord::Base
has_many :products
end
class Product < ActiveRecord::Base
belongs_to :category
end
When selecting the 'category' for a product, your view would have something like:
<%= f.collection_select(:category_id, :id, Category.all, :name, include_blank: true) %>
What this does is specify the Product.category_id as the attribute being populated with the value of Category.id. The values come from the Category.all collection, and with Category.name being the item displayed in the select. The last (optional) parameter says to include a blank entry.
Something like the following is probably what you need:
<%= f.collection_select(:map_id, :id, #map, :area) %>
However, if the model you're trying to populate has an area attribute (instead of an ID linking to the map), you might need to use:
<%= f.collection_select(:area, :area, #map, :area) %>
This specifies that the area attribute of the receiving table will be populated with Map's area attribute, which is also being used as the "description" in the select.