How to set the "selected" choice in the selection box for an associated model? - ruby-on-rails

I have a Product model with many Versions:
class Product < ActiveRecord::Base
attr_accessible :name, :versions_attributes
has_many :versions
accepts_nested_attributes_for :versions, allow_destroy: true
end
class Version < ActiveRecord::Base
attr_accessible :available_q, :kind, :product_id
belongs_to :product
end
I would like to present the available_q attribute to the (admin) user as a select box with the choices of "Yes" or "No", and of course I would like the to have the select box show whatever is currently in the version database for this version, but can't seem to get it to do that. Here is the portion of the view code for the product form involving the select box for the associated model:
<%= form_for(#product) do |f| %>
…
<%= f.fields_for :versions do |version| %>
<%= version.select :available_q, options_for_select([['Yes', 't'],['No', 'f']], version.object.available_q) %><br />
…
<% end %>
…
Everything works well except that the current select box always shows yes even after updating the database with a 'No'. It's likely that I have forgotten to do something very simple, but would very much appreciate any help on this.

<%= version.select :available_q, options_for_select([['Yes', 't'],['No', 'f']], version.object.available_q == 't' ? 0 : 1) %>
You can try the solution above. The second parameter of options_for_select isn't the value to be shown, but the index of the value on the collection array [['Yes', 't'],['No', 'f']].

I have found a work-around: the difficulty I was having seems to have to do with using :available_q which has boolean data type. When I change it to string type, the problem goes away!

Related

Cocoon Show object instead value

My situation:
"app/models/aircraft.rb"
class Aircraft < ActiveRecord::Base
has_many :aircraft_crew_roles
has_many :crew_roles, through: :aircraft_crew_roles, class_name: 'CrewRole'
end
"app/models/aircraft_crew_role.rb"
aircraft_id
crew_role_id
class AircraftCrewRole < ActiveRecord::Base
belongs_to :aircraft
belongs_to :crew_role
accepts_nested_attributes_for :crew_role, reject_if: :all_blank
end
"app/models/crew_role.rb"
name
class CrewRole < ActiveRecord::Base
end
"app/views/aircrafts/_form.html.haml"
= simple_form_for(#aircraft) do |f|
= f.error_notification
= f.input :name
#crew
= f.simple_fields_for :aircraft_crew_roles do |cr|
= render 'aircrafts/aircraft_crew_role', :f => cr
= link_to_add_association 'add a Crew Role', f, :aircraft_crew_roles, partial: "aircrafts/aircraft_crew_role"
= f.button :submit
"app/views/aircrafts/_aircraft_crew_role.html.haml"
.nested-fields.crew-fields
#crew_from_list
= f.association :crew_role, as: :select, collection: CrewRole.all()
= link_to_add_association 'or create a new Role', f, :crew_role
= link_to_remove_association "remove Role", f
"app/views/aircrafts/_crew_role_fields.html.haml"
.nested-fields
= f.input :role
this is my current situation and almost everything work fine: I can add new crew members to the aircraft and this will create the corresponding entry in the aircraft_crew_role and crew_role tables and if I connect to the database I can see that all the entry are right ( I see all ID and the role in the crew_role table is the one I've used in the form) but if I try use the crew already saved with the previous aircraft the select is populated with object instead of string:
#<CrewRole:0x007fa90d2f8df8>
#<CrewRole:0x007fa90d2f8c90>
#<CrewRole:0x007fa90d2f8b28>
I've already used cocoon in many other places in the app and in all the other places it worked smoothly.
I've compared my code with the example on the cocoon repo but I can't find the problem
You are using simple_form's f.association which will try to guess how to present the CrewRole object. It looks for name, label or plain old to_s ... In your case it is a non-standard field role, so it will just convert the model to string (giving the result you got).
To solve this you would have to rename your column (a bit drastic, but maybe that is what you did when recreating the db?) or better, write something like
= f.association :crew_role, label_method: :role
See simple_form documentation for more info.
I have Absolutely no idea how but "simply" dropping and re creating the database now everything works smoothly.

Fields_for form fields not displaying in rails form

I have a class Rfsestimation shown below:
class Rfsestimation < ActiveRecord::Base
has_one :rfstaskset
has_one :rfsnote
enum request_type: [:front_end, :back_end, :front_end_and_back_end]
enum band_type: [:Simple, :Medium, :High, :Complex, :VComplex, :Outside_AD]
**accepts_nested_attributes_for :rfstaskset**
**accepts_nested_attributes_for :rfsnote**
validates_presence_of :number, :name, :date_of_estimation, :request_type_id, :band_id, :hours_per_day, :estimated_start_date, :estimated_end_date, :message => "Should be present"
validates_numericality_of :number
end
Please see the two lines for association above marked in bold. I am attempting to create the associated objects, Rfsnote and Rfstask through fields_for shown in below form:
<%= f.fields_for :rfstaskset do |rfs_task| %>
However the fields which are supposed to appear do not appear as expected. But if i use rfstasksets, as below, the form fields appear as expected.
What might be the reason for this?
<%= f.fields_for :rfstasksets do |rfs_task| %>
I think you are not building the associated object in your controller.
You new action need to look like this:
def new
#rfsestimation = Rfsestimation.new
#rfsestimation.build_rfstaskset
end

select_check_boxes with an has many through relation and :checked option

I am using collection_check_boxes to create object in a has_many through relation;
here some models:
#emotion.rb
class Emotion < ActiveRecord::Base
has_many :emotional_states
has_many :reports, :through => :emotional_states
end
#report.rb
class Report < ActiveRecord::Base
has_many :emotional_states
has_many :emotions, :through => :emotional_states
[... other "irrelevant" stuff here ...]
end
#emotional_states.rb
class EmotionalState < ActiveRecord::Base
belongs_to :report
belongs_to :emotion
end
As you may understand when I create a Report I also select with a collection_check_box a list of Emotions I want to bind to that report (through the model EmotionalState); Everything works on create (I retrieve the hash values and if #report.save I also create EmotionalStates with the #report.id and #emotion.id.)
But when it cames to edit the Report I would like to edit also the associated EmotionalStates (this means creating new EmotionalStates or deleting old one).
How can I populate the select_check_boxes with ALL the available Emotions having checked that emotions that are alredy associated through the EmotionalStates bojects?
If I write something like:
<%= collection_check_boxes(:report, :emotion_id, #report.emotional_states.map{|e| e.emotion}, :id, :name) %>
I'll get a unchecked checkbox for every alredy associated Emotion.
<%= collection_check_boxes(:report, :emotion_id, Emotion.all, :id, :name, :checked => #report.emotional_states.map{|e| e.emotion}) %>
While this code will correctly returns Emotion.all, but will not check the emotions alredy associated to #report through #report.emotional_states.
I've searched all around the wheb for examples on the usage of :checked options for collection_select_boxes without any results...
any hint?
I did the same once in this way.you can also try :
Emotions:
<% Emotion.all.each do |emotion| %>
<%= check_box_tag 'report[emotion_ids][]' , emotion.id, #report.emotion.include?(emotion) %><%= emotion.name %><br/>
<% end %>
In Controller add :emotion_ids=>[] into strong parameters.
And one line into controller update method:
params[:report][:emotion_ids] ||= []
After coming back to this bug I discovered that the problem was an incorrect use of the .map method, mapping a whole object (e.emotion) instead its id (e.emotion.id).
This easily fixed my problem:
<%= collection_check_boxes(:report, :emotion_id, Emotion.all, :id, :name, :checked => #report.emotional_states.map{|e| e.emotion.id}) %>
Thank you for your help!

Rails 4: How to display fields with error in red?

First question: how to validate a model relation and mark it in form when validation failed.
I have a subject model:
class Subject < ActiveRecord::Base
belongs_to :semester
validates_presence_of :semester
end
In my view (form):
<%= select_tag :semester, options_from_collection_for_select(#semesters,"id","name") %>
The validates_presence_of works fine. But when the validation fails (user forgot to enter semester ). The semester input is not marked in red.
Second question: how to validate an input field.
In my view, I also have a university input field, but model subject has no relationship with university, no field university in subject table. So how to validate it and mark it in red.
Thanks in advance.
If you want to get the fields with error displayed in red "out of the box", you must use a form builder. The code will looks like f.select ... instead of using select_tag.
With the form builder, the fields with errors are created inside a <div class="field_with_errors">...</div>. The css file generated by scaffolding displays these fields in red; if you're not using it, you must add the css rules to your css.
# app/models/subject.rb
class Subject < ActiveRecord::Base
belongs_to :semester
validates :semester, :university, presence: true # new syntax http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates
end
# app/views/subjects/_form.html.erb
<%= form_for #subject do |f| %>
Semestr: <%= f.collection_select :semester_id, Semestr.all, :id, :name, prompt: true %>
University: <%= f.text_field :univercity %>
<% end %>
For more information about building forms in rails (with validations enabled) you could find there http://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html
Those "red errors" that you hope for are probably coming from a form helper gem like formtastic, feel free to check that out.
I have literally no idea what your second question is asking, but if you're looking for a custom validation. Check out the rails docs on them for help.
If you'd like more help, (please) edit your question to be more clear (thanks)

Can't convert symbol to integer error with rails simple_form nested attributes

I've seen many similar questions, and looked at the answers, but nothing seems to be helping me and I've been working on this for a while now. The error is 'Can't convert symbol into integer'. My goal is to be able to create multiple sub_groups for each race. I'm just starting with trying to create one for the time being. Here's the relevant code...
** UPDATE **
VIEW
<%= simple_form_for(#race, :url => form_path, :method => form_method, :html => { :class =>
'form-horizontal form-compressed' }) do |f| %>
<fieldset>
<%= f.simple_fields_for :sub_groups do |g| %>
<%= g.input :name, requred: false %>
<%= g.collection_radio_buttons :discount_type,
[['dollars', '$'], ['percent', '%']], :first, :last %>
<%= g.input :discount_amount, :as => :integer, required: false %>
<% end %>
<hr/>
** RACE MODEL**
class Race < ActiveRecord::Base
has_many :sub_groups
accepts_nested_attributes_for :sub_groups
attr_accessible :sub_groups_attributes
** SUB_GROUP MODEL **
class SubGroup < ActiveRecord::Base
belongs_to :race
has_many :race_users
attr_accessible :discount_amount, :discount_type, :display_results, :name
end
PARAMS
after my code update...
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"VihBL4TDT/Lte4YBji/4fp4XvOri1UgUZ8B33wQuCko=", "race"=>
{"sub_group"=>{"name"=>"dfd", "discount_type"=>"dollars", "discount_amount"=>"2"}},
"commit"=>"Next", "wizard"=>"2", "id"=>"13-test5"}
CONTROLLER
class RacesController < ApplicationController
def new
#race = Race.new
#sub_groups = #race.sub_groups.build
#wizard_step = -1
#wizard_step_name = Race.wizard_step_name_from_id #wizard_step
#wizard_mode = true
render :layout => "race_wizard"
end
def update
#race = Race.find params[:id]
#wizard_step = params[:wizard].to_i + 1
#race.wizard_step = #wizard_step
#race.update_attributes(params[:race])
end
So I took advice from answer 1, and switched to using :sub_groups in the view. Now I have a new problem, which is the sub-group fields don't show up at all, despite the fact that I built a sub_groups thing in the #new method.
I'm really stumped on how I can make this happen. This is driving me bonkers. Any help is much appreciated. Thanks!
The way fields_for works is that if you supply a symbol it checks whether your model respond to {given_symbol}_attributes=. If it does the name of sub-fields is {given symbol}_attributes, otherwise just {given_symbol}.
What you need is to add accepts_nested_attributes_for :sub_groups to your Race model. This methods will create a default setter sub_groups_attributes=, which will make fields_for :sub_groups to generate fields with name sub_groups_attributes.
You can also write your own sub_groups_attributes= method, but you need to be sure you know what you're doing there as it might be a little tricky to debug.
Note, that fields_to :sub_groups won't display fields if there are no sub_group associated with given object - you will need to build one in your controller first.

Resources