Get association for the nested model in simple_form - ruby-on-rails

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}" } %>

Related

Rails 5 fields_for nesting under a collection

So I have a model with this structure:
document {
structure {
id,
...
},
fields {
field {
id,
...
},
value {
...
}
}
}
And I'm trying to put together a form for the fields, where the fields would look like:
<input type="hidden" name="document[fields][0][field][id]" />
<input type="text" name="document[fields][0][value]" />
<input type="hidden" name="document[fields][1][field][id]" />
<input type="text" name="document[fields][1][value]" />
...
This is what I'm currently doing:
<%= document.fields.each_with_index do |df, i| %>
<%= f.fields_for "fields[]", df do |builder| %>
<p>
<%= builder.label df.field.name %>
<%= builder.fields_for :field do |field_builder| %>
<%= field_builder.hidden_field :id, value: df.field.id %>
<% end %>
<%= builder.fields_for :value do |value_builder| %>
<%= render df.field.edit_view, field: df.field, builder: value_builder %>
<% end %>
</p>
<% end %>
<% end %>
But the resulting field names are:
document[fields][field][id]
document[fields][value][value]
In other words, the indices are missing.
Using <%= builder.hidden_field :id, value: df.field.id %> results in the correct format but no index (because the field object has no id yet): document[fields][][id] but that is not an option for value, as there could be multiple fields involved.
Is there a way to do this using the form helpers, or is what I'm doing just too wonky?
Edit: Here are the models involved:
The idea is to have a configurable set of fields for document. The structure determines fields available, and a document_field is a relation between a document and a field with a value contained.
class Field < ApplicationRecord
belongs_to :structure
end
class Document < ApplicationRecord
belongs_to :structure
has_many :document_fields
class DocumentField < ApplicationRecord
belongs_to :document
belongs_to :field
class Structure < ApplicationRecord
has_many :fields
You should configure a nested attributes setup on your models, build those nested relations on the controller, and instantiate an object in you form_for block instead of passing a referencing symbol.

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 to create a check_box_tag in rails 3

I have model restaurant and lunch. Where restaurant has_many :lunches and lunch belongs_to :restaurant. Having these relations, I want to show all the available restaurants as checkboxes.
lunch.rb looks like this:
attr_accessible :date, :email, :name, :restaurant_id
belongs_to :restaurant
but I am finding it hard to do it. Can someone explain all the params that are there for in check_box_tag?
I got a snippet of code and modified accordingly, but it doesnt work.
<div class="form_row">
<label for="restaurant_id[]">Restaurants:</label>
<% for restaurant in Restaurant.find(:all) do %>
<br><%= check_box_tag 'restaurant_id[]', restaurant.id %>
<%= restaurant.name.humanize %>
<% end %>
</div>
but when I see the log the restaurant_id is nil.
Here you have the involved form helper doc:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-check_box
<%= check_box_tag(:restaurant, restaurant.id) %>
outputs:
<input id="restaurant" name="restaurant" type="checkbox" value=restaurant.id />
The first parameter to check_box_tag, of course, is the name of the input. The second parameter, naturally, is the value of the input. This value will be included in the form data (and be present in params) when the checkbox is checked.
http://guides.rubyonrails.org/form_helpers.html
Source code:
http://apidock.com/rails/ActionView/Helpers/FormHelper/check_box
# File actionpack/lib/action_view/helpers/form_helper.rb, line 929
def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
Tags::CheckBox.new(object_name, method, self, checked_value, unchecked_value, options).render
end
You can't use checkbox tag if you have this association :
restaurant has_many :lunches
lunch belongs_to :restaurant
You should use select tag (singel select) or radio button tag on lunch form because lunch have only one restaurant.
Example using select :
<%= f.label :restaurant_id, 'Restaurant Name' %>
<%= f.collection_select(:restaurant_id, Restaurant.all, :id, :name, :prompt => 'Please select restaurant') %>

Rails HABTM order with select boxes

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.

Resources