HashWithIndifferentAccess in related models - ruby-on-rails

I've got a rails app where I'm linking fields across two databases. The database stuff all seems to be fine.
However, I have one form where I am mapping a description from the remote database to a product in the local database.
The form the used to create the product and select the description works fine
#_form.rb
semantic_form_for #products do |f|
f.input :name
semantic_fields_for :description_maps do |description|
description.input :desciption_map_id, :input_html=>{:name=>"product[description_map][description_id]}, :collection => #descriptions
end
end
#product.rb
class Product < ActiveRecord::Base
attr_accessible :name, :description_map_attributes, :description_map
has_one :description_map
accepts_nested_attributes_for :description_map
when I submit the form, I get an error
DescriptionMap(#...) expected, got ActiveSupport::HashWithIndifferentAccess(#othernumber)
I can't seem to figure out why this is happening.
the parameters being posted look fine
"product"=>{"name"=>"test name",
"description_map"=>{"description_id"=>"1"}}

turns out this was an issue with how formtastic was naming the description map.
In the question, i had specified
description.input :desciption_map_id, :input_html=>{:name=>"product[description_map][description_id]}, :collection => #descriptions
but the 'description_map' needed to be 'description_map_attributes' like this
description.input :desciption_map_id, :input_html=>{:name=>"product[description_map_attributes][description_id]}, :collection => #descriptions
Hopefully this answer helps somebody else having the same issue.

You should use: :description_map (without "S") cause is a has_on relation
semantic_fields_for :description_map do |description|
description.input :desciption_map_id, :input_html=>{:name=>"product[description_map] [description_id]}, :collection => #descriptions
end

Related

Rails Simple Form Select from Array - polymorphic associations

I am making an app in Rails 4. I use Simple Form for forms.
I have a profile model and an organisation model.
The associations are:
profile.rb
has_one :organisation, as: :orgable
organisation.rb
has_many :profiles
In my organisation table, I have an attribute called :org_type.
In my organisation form, I ask users to select from an array of types of organisation:
<%= f.input :org_type, :label => "Organisation type", collection: [ "University", "Research Organisation", "Company"] %>
In my profile form, I want to ask users which uni they study at.
I want to use the array of universities created within the organisation model.
I have a scope in my organisation model to filter out the universities:
scope :all_uni, -> { where(org_type: 'University') }
In my profile form I have:
<%= f.input :institution, :label => "Graduated from" %>
But this just has a text field.
I have tried to replace that line with an attempt at making a select function in my form which refers to my organisation model scope for all_uni. It looks like this:
<%= f.select(:institution, #organisation.all_uni.title.map { |value| [ value, value ] }) %>
It gives this error:
undefined method `all_uni' for nil:NilClass
I don't understand what this error message means, but I'm also not sure I'm on the right track with the form select field either. Any tips for where to look to get this working. I'm not sure how to go about setting up the select field in the first place?
ANOTHER ATTEMPT:
I have also tried using this in my profile form:
<%= f.select(:institution, #organisation.all_uni.title) %>
But I get the same error. I must be way off track - i've exhausted every option I can find.
ANOTHER ATTEMPT
I found this post
Rails Simple Form custom association select field
Taking the example in that solution, I tried:
<%= f.input :institution do %>
<%= f.select :institution, Profile.Organisation.all_uni.map{ |l| [l.title {:title => l.title.titlecase}] } %>
<% end %>
But, I get this syntax error. I've tried removing the => but keep getting more syntax errors.
syntax error, unexpected =>, expecting '}' ...i.map{ |l| [l.title {:title => l.title.titlecase}] } );#out... ... ^
Not a complete answer but according to what I know is, If you got 2 models then instead of using
profile.rb
has_one :organisation, as: :orgable
organisation.rb
has_many :profiles
You can simply use
profile.rb
belongs_to :organisation
organisation.rb
has_many :profiles

Set multiple attributes on basis of results of a :select in rails form

I have a select box on my form which retreives an object with the following attributes:
:id, :v2_read_code, :v2_term
The select code is:
f.inputs "Tests" do
f.has_many :eqa_material_tests, :allow_destroy => true, :heading => 'Tests In EQA Material' do |cf|
cf.input :test_id, :as => :select, :collection => Hash[Test.all.order(default: :asc).map{|b| [b.v2_term,b.id]}]
end
end
Where I am storing the test id in a model/table with the following structure:
eqa_material_tests
id, test_id, eqa_material_id
In addition to storing the test_id, I'd also like to store the v2_read_code and v2_term as I'd like to keep a copy of these items if possible.
Is this possible?
After a nights sleep I've realised I'm approaching this wrong. I can do this using an active record callback like after_create

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 3 best_in_place Edit Nested Model

Given
<% #incidents.each_with_index do |incident,i| %>
I can't figure out how to in place edit attributes on incident and parent associations such as incident.user or incident.contact
This works for example:
best_in_place incident, :notes, type: :input, nil: 'Add Note'
But I can't figure out how to do incident.customer to get a drop down of Customer.all (incident belongs_to :customer)
I get various errors each way I try it.
If I understand you correctly, in your controller's show action, or wherever's relevant:
#customer = Customer.all.map { |c| [c.id, c.customer_name] } # or whatever the customer name attribute is
In your view:
= best_in_place incident, :notes, :type => :select, :collection => #customer
This produces the [[a,b], [c,d]] format that the docs say is needed.
It would be less wordy with Customer.pluck(:id, :name) but that's only in Edge Rails at the time of writing (link to guides).

an example of a nested form in simple form?

I am still struggling both writing the controller and the actual form to be able to nest one form in another with an optional model?
I have Message which has many contacts
When submitting a message, I want to add a contact optionally.
I have this as an example:
= simple_form_for Message.new, :remote => true do |f|
#message_form
= f.error_messages
%p
= f.input :account_name, :url => autocomplete_account_name_messages_path, :size => 40, :as => :autocomplete
%p
= f.input :topic, :required => true,
:input_html => {:size => 30}
#add_contact_btn
= link_to "Add Contact"
#contact_form
= f.simple_fields_for :contactd do |fc|
= fc.input :email
= fc.input :first_name
= fc.input :last_name
= f.submit 'Give'
= f.submit 'Request'
For Message.rb model, I have the following:
has_many :contacts
accepts_nested_attributes_for :contacts, :reject_if =>:all_blank
Note: When I used :contacts in the simple_fields_for it didn't work, so it is singular. But the reverse for accepts_nested_attributess_for.
In my create controller for message, I included message.contacts.build
But right now I am still generating nil contacts.
Here is what I see passed as form data from google chrome:
message%5Baccount_name%5D:McKesson
message%5Btopic%5D:testing a contact
message%5Bbody%5D:testing this
sender_id:
receiver_id:23
message%5Bcontacts%5D%5Bemail%5D:888#gmail.com
message%5Bcontacts%5D%5Bfirst_name%5D:Ang
message%5Bcontacts%5D%5Blast_name%5D:Name
The correct method name is simple_fields_for (notice the plural)
Also, you need to keep the f. to call it on the simple_form object
I have a small project where I demonstrate how to use nested forms in simple-form, combined with cocoon (a gem I created to add/remove nested elements dynamically).
The project is on github.
Hope this helps.
In my create controller for message, I included message.contacts.build
But right now I am still generating nil contacts.
Make sure you put in your Message.rb model the ability for it to accept the attributes too.
class Message < ActiveRecord::Base
attr_accessible :contacts_attributes
has_many :contacts
accepts_nested_attributes_for :contacts
I know it doesn't answer your question fully but it may have just been this. When it comes to my project, it would return nil if i didn't include the :contacts_attributes, in my case it deals with products. Hope this helps even if I'm not using simple form as of now!
I faced similar issues working with nested forms. As suggested by JustinRoR you need to define
attr_accessible: contacts_attributes.
You should be able to test the hash in the ruby console ( I am not sure if you have tried this). I suggest you to print the params[:message] and use this to create message from console like Message.new(params[:message]). (Note params[:message] is what you get by printing the params[:message] hash).
Once it works in console it should work like charm

Resources