Rails HABTM order with select boxes - ruby-on-rails

I have two models (code redacted for clarity):
class App < ActiveRecord::Base
has_and_belongs_to_many :products
end
class Product < ActiveRecord::Base
has_and_belongs_to_many :apps
end
I want to be able to add multiple products to each app. Also, the order of the products in the app is important, and where I'm having trouble.
I'm using simple_form and I've tried using the association method:
<%= simple_form_for(#app) do |form| %>
<%= form.input :name %>
<%= form.association :products %>
<%= form.button :submit %>
<% end %>
It works wonderfully, but the select box it creates is not orderable. My attempt at a solution was to create multiple <select> boxes and order them somehow. This so far isn't working. As a test I tried this:
<%= form.collection_select('product_ids', Product.all, :id, :name, {}, {name: 'app[product_ids][]'}) %>
<%= form.collection_select('product_ids', Product.all, :id, :name, {}, {name: 'app[product_ids][]'}) %>
<%= form.collection_select('product_ids', Product.all, :id, :name, {}, {name: 'app[product_ids][]'}) %>
<%= form.collection_select('product_ids', Product.all, :id, :name, {}, {name: 'app[product_ids][]'}) %>
It actually does make the association in the database, but it 'selects' all the products for each select tag which ends up just selecting the last product on all of them:
<select id="app_product_ids" name="app[product_ids][]">
<option selected="selected" value="1">Golf Club</option>
<option value="20">Music Disc</option>
<option selected="selected" value="17">Magic Wand</option>
<option value="15">Nike Running Shoes</option>
<option selected="selected" value="19">Watch</option>
<option selected="selected" value="16">Wooden Spoon</option> // this is what is selected in the browser
</select>
Eventually, I'll make the adding and removal of these dynamic.
So my question is, how can I make this work? One way would be to have each <select> associate to the particular product instead of all the products. Maybe there's a better way all together.

Related

Rails collection_select with join table

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.

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) %>

how do i get the id of the selected item in dropdown

<%= form_for(:offer,:url=>{:controller=>'offers',:action=>'combo'}) do |f|%>
<%= f.select :catId_get, options_from_collection_for_select(#categories, "id", "name"), prompt: "Select Category" %>
I am new in rails.I have a dropdown where all categories are there.When i select a category from this dropdown i want to get its category id in my controller,so that i can use that id for it's child dropdown.
Select
Each select option in HTML has two values -- the value and the label:
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
It's only the value which is passed to your controller. This means if you are able to create the select tag in your Rails app with the correct value / label setup, it will pass the correct data you require.
Rails
Here's how I'd handle it:
<%= form_for :offer, offers_combo_path do |f|%>
<%= f.collection_select :cat_id, #categories, :id, :name, prompt: "Select Category" %>
This will pass the following params to your categories_controller:
#app/controllers/categories_controller.rb
class CategoriesController < ApplicationController
def combo
params[:offer][:cat_id]
end
end
Recommendation
I'd actually recommend you use the form_tag helper for this, rather than form_for. Reason being that form_for is mainly for ActiveRecord objects, and although you can use :symbols in the helper, you will really need to use a much less elaborate system
I'd just replace your form_for with the following:
<%= form_tag offer_combo_path do %>
<%= collection_select :cat_id, #categories, :id, :name, prompt: "Select Category" %>
<% end %>
Your id should be accessible by
params[:offer][:catId_get]
in your controller.

Get association for the nested model in simple_form

I don't know have to get select box for the association and value from the other model.
For example i have a table course_names to record course name.
I have other table which has other table course which has more columns with course_name_id
class Course < ActiveRecord::Base
belongs_to :course_name
end
Now, i have to create student_profile and have association for courses table like this.
class Student < ActiveRecord::Base
belongs_to :course
...
end
And in the view with the simple form i have to create a select box for to select course.
<%= simple_form_for(#student_profile) do |f|%>
<% f.error_notification %>
<div class="form-inputs">
<%= f.association :course %>
But this association don't show course name.
<select class="select optional form-control" id="student_course_id" name="student[course_id]"><option value=""></option>
<option value="3">#<Course:0x00000105c23818></option></select>
But i want the output as (course-name for the option from course_names)
<select class="select optional form-control" id="student_course_id" name="student[course_id]">
<option value=""></option>
<option value="3">course-name</option>
</select>
How, do i achieve this.
one, solution is
<%= f.association :course,collection:Course.all.includes(:course_name).map{|a|[a.course_name.name,a.id]} %>
but this doesn't seem right? How do i tell association go get course name from the association.
have you tried to use this : label_method like that :
<%= f.association :course, label_method: :course_name %>
Or as course belongs to course_name, maybe you want this:
<%= f.association :course, label_method: lambda { |course| "#{course.course_name.name}"} %>
Edit To avoid all the queries, you should preload the data
courses = Course.includes(:course_name)
And then use it as follow
<% f.association :course, collection: courses, label_method: lambda { |course| "#{course.course_name.name}" } %>

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