ruby on rails how to use FormOptionHelpers to create dynamic drop down list - ruby-on-rails

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.

Related

rails form for model select box with 1-dimensional data

I want to limit the entry possibilities for a text field in my model to a previously defined array.
How do I make an options_for_select with just a 1-dimensional array like ["foo","bar","foobar"]?
I tried
form_for #mappings do |f|
f.select(:mapping_type, options_for_select(["foo","bar","foobar"]), class: "..."
end
But the select box comes out all messed up like this:
<select name="section_mapping[mapping_type]" id="section_mapping_mapping_type">
as opposed to what it should be:
<select name="mapping_type" >
EDIT:
I changed the f.select to select_tag and the form shows up without any errors but when I submit it, it leaves that field empty
EDIT 2:
f.collection_select(:mapping_type, options_for_select([...]), class: "..."
works as in it submits the form with the value correctly, but the HTML class is not applied. Why is that?
Basically, you want to be able to tie your collection select to a property of the object (in your case, #mappings)
Also, from the doc on rails collection_select, it will take options as follow:
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {}) public
Objet: the object you are binding the selected option to (#mappings [f]) in this case
method: The property/attribute of the object (in this case, mapping_type)
collection: The collection for select ( ["foo","bar","foobar"] )
value_method: The value you want to send back with the submit (Note that this is a method which means you should be able to call it on an object.) more on this later.
text_method: The value you want to show as text on the select option on the view (this is also a method as above, more on this later as well)
options: any additional option you want, (e.g: include_blank)
html_options: eg: id, class etc.
As concerning the value_method and text_method, these are methods that should be called on your collection, which means that your collection will be an array of objects.
To this end, you can have the following:
class CollectionArr
include ActiveModel::Model
attr_accessor :name
ARR = [
{"name" => "foo"},
{"name" => "bar"},
{"name" => "foobar"}
]
def self.get_collection
ARR.collect do |hash|
self.new(
name: hash['name']
)
end
end
end
From here, calling CollectionArr.get_collection will return an array of objects where you can cal .name to return either foo, bar, or foobar. This makes using the collection_select and easy deal from here:
<%= f.collection_select : mapping_type, CollectionArr.get_collection, :name, :name, {:include_blank => "Select one"} %>
And all is green...

Cannot retrieve lookup values correctly

I've built a lookup table in my Rails application.
It is a table that stores lookup text values for drop-down pickers or possibly check boxes. I want the lookup table to have a view associated so the values can be easily edited. I also may want to share lookup values among multiple models for a single field in the future.
So far I've managed to get it to work for the selection of values, but then displaying the text value again on a show or index view has been problematic.
This is how I built the lookup table
rails g scaffold Lookup field_name lookup_text table_name note
In the edit.html.erb where there is a lookup on a field, I've got code like this, which works and allows me to pick from a list.
<div class="field">
<%= f.label :status %><br />
<%= f.collection_select :status, Lookup.find(:all,:conditions => ["table_name = 'course' and field_name = 'status'"]), :id, :lookup_text, include_blank: true,:prompt => "Status" %>
</div>
That all works fine. When I try to display it back I cannot find the correct syntax. The best I have found is this:
(in the controller)
#status = Lookup.where(:id => #course.status).pluck(:lookup_text)
(in the view)
<p>
<b>Status:</b>
<%= #status %>
</p>
I think I am getting the entire object. It displays like this:
Status: ["Active"]
My questions are:
(1) How do I display the value only?
(2) Is this the best approach?
I've had a look at these and other SO questions, but none are really what I am looking for:
Rails Polymorphic with Lookup Table
Implementing a lookup table in Rails
EDIT
OK this works, but it doesn't look like it is the correct solution. Has anyone got a better way of doing this?
#status = Lookup.where(:id => #course.status).pluck(:lookup_text)[0]
Just another way to show the value is #status = Lookup.find(#course.status).lookup_text
Why not to try use classes for different lookups:
class CourseStatus < ActiveRecord::Base
set_table_name "lookups"
default_scope where("table_name = 'course' and field_name = 'status'")
end
class Course
belongs_to :course_status
end
You then can use:
CourseStatus.all # e.g. to fill select options
Course.first.course_status.lookup_text # => "Active" or smth else
Or without classes:
class Lookup
def self._by_table_and_field(table, field)
['table_name = ? and field_name = ?', table, field]
end
scope :by_table_and_field, lambda { |table, field|
where(Lookup._by_table_and_field(table, field))
}
end
class Course
belongs_to :status, class_name: 'Lookup', conditions: Lookup._by_table_and_field('course', 'status')
end
Lookup.by_table_and_field('course', 'status').all
Course.first.status.lookup_text

Combine multiple models in a Rails form to create a new object

I have two models, Story and Category. Using the form for Story#new, I'd like to be able to save the foreign key for Category.
To display the selection data from Category on the Story#new form page I've used:
<%= collection_select(:category , :category, Category.all , :id, :category, {:prompt => 'Select Category...'}) %>
How can I save category_id to the newly created Story object?
Story has attributes: industry_id and user_id, Category has attribute name
development.log tells me this: (it looks like it's trying to add a new category (99) to the Categories table
Started POST "/stories" for 127.0.0.1 at 2012-02-10 17:32:56 -0600
Processing by StoriesController#create as HTML
story"=>{"industry_id"=>"8", "user_id"=>"8"}, "category"=>{"category"=>"99"}, "commit"=>"Create Story"}
I think you need to change the parameters to collection_select. The first parameter is the name of the model. The second parameter is the name of the model attribute that the value will be assigned to. The fourth parameter is the method of the Category object to use as the text value of the select option.
I believe it should look like this:
<%= collection_select(:story , :category_id, Category.all , :id, :name, {:prompt => 'Select Category...'}) %>
You might also want to look at ActiveRecord nested attributes.

In Rails 3 how should I manage a model column with limited choices

In my Rails 3 application I have numerous models that have columns that have limited choices (IE a select box). It seems overkill in these cases to create another model and a relationship to the original model just to manage the choices.
One option I can think of is to just create a select box and have the choices in there, but that doesn't seem very DRY. Does anyone have a good suggestion how to handle this situation?
Thanks for looking.
You could create a constant in your model like so
# formatted as an array of options, option being an array of key, value
OPTIONS = [['Email', 'email'], ['Text', 'text'], ['Email and Text', 'both']]
validates_inclusion_of :field, :in => OPTIONS
Which can then be used to populate a select menu in a view very easily
Example using formtastic
<%= f.input :field, :as => :select, :collection => Model::OPTIONS %>
I usually do this with a constant list in the model.
class Model < ActiveRecord::Base
PROPERTY_OPTIONS = ['Option One', 'Option Two', ...]
validates_inclusion_of :property, :in => PROPERTY_OPTIONS
end
And in the view:
<%= f.select :property, Model::PROPERTY_OPTIONS %>
You can also use the enum_column plugin: https://github.com/electronick/enum_column
You can then render your select boxes in your views as follows:
<%= f.select :status, Model.columns_hash['status'].limit %>
(Where Model is an example model name, such as Book or Product, or whatever it is your application is really about.)
In some cases, I will just create a hash of options and use Class Methods to display and set them. For example, a Problem model with different statuses could be done like so:
def self.statuses
{:open => 1, :closed => 2}
end
Then you just store the integer value in the status_id of the model. You can configure getters/setters as well.

Basic rails collection select question

A card can have one of many card_types. There are two models, card and card_type, where card_type is an [id, card_type_desc] pairing.
When you define a new card, you have to pick a card-type from a drop down list.
I have the list rendering correctly with the below collection_select box, but the new card.card_type_id field is NULL. How do you set it to the value from the list?
<%= collection_select(:card_type, :id, #card_types, :id, :card_type_desc) %>
Thanks in advance.
I am guessing, It should be...
<%= collection_select(:card, :card_type_id, #card_types, :id, :card_type_desc) %>

Resources