Rails collection_select with join table - ruby-on-rails

My tables:
Person belongs_to and
Room has_many Person
My collection_select
<%= collection_select(:inspection, :person_id, Person.involving(current_user), :id, :room_id) %>
If I'm not wrong, in HTML it will be represented as the following code:
<select name="post[person_id]">
<option value="<%= person.id %>"><%= person.room_id %></option>
<% end %>
</select>
My point is that when a user submit the form I need send the Person Id value, but I need show on the drop down list the name of the rooms (in my example I showing the room.id) like that:
<select name="post[person_id]">
<option value="<%= person.id %>"><%= room.name %></option>
<% end %>
</select>
How can I do that?
As I see I think that I need join person table with room table? If it is the solution, how can I do that?
My person model:
scope :involving, -> (user) do
where("persons.id = ?", user.id)
end
My view
<%= form_for #inspection do |f| %>
<label>Select</label>
<%= collection_select(:inspection, :person_id, Person.involving(current_user), :id, :room.id) %>
<%= f.submit "Send" %>
I tried to make it as clear as I could.

Consider using select rather than collection_select. This method allows you finer grain control over what is used for id and name of each option.
In your case you'd want something like:
select(:inspection, :person_id, Person.involving(current_user).collect {|p| [ p.id, p.room.name ] }, { ...other method options... })
This allows you to specify the array of option id/name pairs. You get all the people involved using your scope, then iterate over those returning an array for each one found, where the first value in the array is the option value and the second is the displayed option text.
Check this documentation out for more details.

Related

Using datalist on a Ruby on Rails form to display name but pass the id param

I have a form where users can add an item to their stock. I would like the form to use datalist. My code is this:
<div class="form-group">
<%= form.label :item_id %>
<%= form.text_field :item_id, list: 'item_id' %>
<datalist id="item_id">
<%= options_for_select(current_user.items.map { | item | [item.name, item.id] }) %>
</datalist>
</div>
But when the user type their search and click on the autocompleted name (for example 'Apple'), the form then displays the id of the item (for example '7'). I would like that instead of changing it to the id, the form only displays the name. How can I achieve that?
This is not a good idea - at all. Unlike a select a text input is not label/value. What you see is what you get.
So while you could do:
<datalist id="item_id">
<% current_user.items.each do |i| >
<option><%= i.name %></option>
<% end %>
</datalist>
Which will fill the item_id input with the name. But you'll lose the id on the way. Which means that you would either need to lookup the item by name or use some sort of javascript trickery to hamster away that id and replace the input value before the user submits it.
At which point you could actually create a AJAX autocomplete with the same amount of effort thats less of a hacky mess.

How to search Data from select tag rails

I'm trying to develop a web app using rails, which has Course Category and location modules.Course is interrelated to Category and Location with 'has_many' relation.
In my Course form, I need to sort out the courses based on Category. Can anyone help me to sort this out?
course.html.erb:
<%= select_tag(:category_id, options_for_select(Category.pluck(:name, :id)), class: "form-control custom-select" )%>
You can use options_from_collection_for_select method to avoid using pluck. And if I'm not mistaken, you want to sort categories by name. So:
<%= select_tag :category_id,
options_from_collection_for_select(Category.order(:name), :id, :name),
class: "form-control custom-select" %>
UPDATE
So it looks like you need to send AJAX request on dropdown change and re-fill table content. Please, check this articles:
jQuery.ajax() or AJAX Introduction
jQuery .change() event or change event
We don't know what are you using to generate the table (simple partial, DataTable-plugin or something else) so we cannot suggest to you the best solution for your case. But, for example, you can get updated table content as an AJAX response and refill the table in HTML.
If I understand correctly, you want to sort the list of Courses you get as your search result.
So, try this:
#courses = Course.joins(:categories, :locations).where("categories.id LIKE ? and locations.id LIKE ?", "%#{params[:category_id]}%", "%#{params[:location_id]}%").order("categories.name ASC")
Solved by adding this code:
course_controller.rb
def index
#courses = #courses.where(category_id: params[:category_id]) if params[:category_id].present?
end
course index.html.erb
<%= form_tag courses_path, :method => 'get' do %>
<%= select_tag(:category_id, options_for_select(Category.order(:name).pluck(:name, :id) ,:selected =>params[:option]), onchange: 'this.form.submit();', class: "form-control custom-select" , include_blank: true )%>
<% end %>
You can always do something like this.
<input list="cites" class="form-control" name="cites">
<datalist id="cites">
<% cites.each do |city| %>
<option value="<%= city.name %>">
<% end %>
</datalist>

Saving a foreign key in my form when a user selects a name from the dropdown menu

I am a newbie to Ruby on Rails and am stumped. As part of my exercise I am creating an app that let's people put in their goal, a description, a deadline and assign it to a person.
I've got two models, a user model and a goal model. In my ERB form to create a new goal, I've created a dropdown menu of all the created users but now I have no idea how to convert that into the foreign key that gets saved.
<%= form_for(#goal) do |f| %>
<% if #goal.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#goal.errors.count, "error") %> prohibited this goal from being saved:</h2>
......
<div class="field">
<%= f.label :user_id, "Whose goal is it?" %><br>
<%= collection_select(:goals, :user_id, User.all, :id, :name, prompt: true ) %>
</div>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The above seems to create the dropdown menu I need. I just have no idea how to get from the :name generated in the dropdown to the :user_id associated with it to submit.
Will greatly appreciate your help.
Thanks!
Frist you should use singular as object in collection_select:
<%= collection_select(:goal, :user_id, User.all, :id, :name, prompt: true ) %>
Then your collection_select creates a select tag with name goal[user_id]. It will look like
<select name="goal[user_id]">
<option value="">Please select</option>
<option value="1" selected="selected">D. Heinemeier Hansson</option>
<option value="2">D. Thomas</option>
<option value="3">M. Clark</option>
</select>
The options have user IDs as value an the names as content. So the parameter
params[:goal][:user_id]
contains the ID of the selected user. This is exactly how Rails expects the foreign key.
See the documentation of collection_select
Adition: there are great gems to simplify form generation, i.e. simple_form which reduces your form to
<%= simple_form_for(#goal) do |f| %>
...
<%= f.association :user %>
<% end %>
Your question is already answered but I'd like to share an awesome tutorial I found:
Advanced forms
Just add to your 'new' controller
#user_options = User.all.map{|u| [ u.name, u.id ] }
Then in your form:
<%= f.select(:user_id, #user_options) %>

Collection Select Helper in Rails 3

I have a quick question in regards to the collection_select helper in Rails 3.
I would like to create a drop down field whereby a user can select a country from a list.
My code currently looks something like this:
<%= collection_select(:country,:id,SyncedCountry.order('name ASC'),:name,:name,{},{:class => "input-xlarge"}) %>
When I submit on the page I see something like this in the params for country:
"country"=>{"id"=>"Antilles"}
What I really want is the id of the country selected in the drop-down and not in a hash format. So the result would be more like:
"country"=> 1 (the id of a country selected)
Any ideas?
Replace
<%= collection_select(:country,:id,SyncedCountry.order('name ASC'),:name,:name,{},{:class => "input-xlarge"}) %>
with
<%= collection_select(:model_object,:country,SyncedCountry.order('name ASC'),:name,:name,{},{:class => "input-xlarge"}) %>
where model_object is the object passed to form. If its a form for user and your form looks like form_for(#user) then replace :model_object with :user.
So, params would look like "user"=>{"country"=>"Antilles"}, assuming that you are setting country for a user.
From the documentation:
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {}) public
...
The :value_method and :text_methodparameters are methods to be called
on each member of collection. The return values are used as the value
attribute and contents of each <option> tag, respectively. They can
also be any object that responds to call, such as a proc, that will be
called for each member of the collection to retrieve the value/text.
So try:
<%= collection_select(:country,:id,SyncedCountry.order('name ASC'),:id,:name,{},{:class => "input-xlarge"}) %>
The example in the documentation looks like this:
Sample usage (selecting the associated Author for an instance of Post,
#post):
collection_select(:post, :author_id, Author.all, :id,
:name_with_initial, prompt: true)
If #post.author_id is already 1, this would return:
<select name="post[author_id]">
<option value="">Please select</option>
<option value="1" selected="selected">D. Heinemeier Hansson</option>
<option value="2">D. Thomas</option>
<option value="3">M. Clark</option>
</select>
(this will return "author_id"=>"1")
Now, I'm not familiar with your model, but if you are selecting the country of your user, than I think this should work:
<%= collection_select(:user, :country_id,SyncedCountry.order('name ASC'),:id,:name,{},{:class => "input-xlarge"}) %>

Select input element using f.select() of items connected by a linking table (in Rails)

I have a form for an instance of a "project". Each project can have many clients. Each client is a unique pair of organization and individual (contact person).
So, Project has a many-to-many relationship with Client. Client has a many-to-one relationship with organization and a many-to-one relationship with Organization.
See an image of the model diagram: http://dl.dropbox.com/u/631919/erm.png
In the edit page for a project, I'd like to be able to change the organization for each client through a drop down select menu, but I'm having trouble getting the organizations to appear in the select input item.
Here's what I have:
<% form_for(#project) do |f| %>
<% #project.clients.each do |client| %>
<%= f.select("client.organization_id", Disclosure.all.collect {|d| [d.color.titlecase, d.id] }) %>
<% end %>
<% end %>
I know this is wrong, but I don't know how you get a select drop-down menu that I want, which is a select menu with the organization associated with each client as the default selection.
Any help?
Your schema seems somewhat strange to me...but anyhow..
If you want to list all the organizations in the select and have the current one be defaulted try this:
<%= f.select("client.organization_id", Organization.all.collect {|o| [o.name, o.id] }) %>
The client.organization_id that is current should be selected if this is a restful edit action. See below.
From the docs: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#M002302
Example with #post.person_id => 1:
select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { :include_blank => true })
could become:
<select name="post[person_id]">
<option value=""></option>
<option value="1" selected="selected">David</option>
<option value="2">Sam</option>
<option value="3">Tobias</option>
</select>
<% form_for(#project) do |f| %>
<% #project.clients.each do |client| %>
<% fields_for :client, client do |c| %>
<%= collection_select(client, :organization_id, ORganization.all, :id, :name) %>
<% end %>
<% end %>
<% end %>

Resources