Cocoon how to remove associations - ruby-on-rails

I am trying to use the Cocoon gem to add/remove assets on asset_profiles. Everything up to this point works, I am just having a problem with link_to_remove_association. When the button is clicked, the field is removed. But if the field had been filled in and saved previously, I am unable to remove said association. The button just hides the field until I hit update. Is there a way to actually remove the association from the database through link_to_remove_association? Any help is much appreciated. Thanks in advance.
Here is the code I am referring to:
Asset.show
= simple_form_for([#asset_profile, #asset]) do |f|
= f.input :max_users, as: :hidden
#assets_users
= f.simple_fields_for :assets_users do |assets_user|
= render "assets_user_fields", f: assets_user
.links
= link_to_add_association "Add Another User", f, :assets_users
= f.submit
Asset._assets_users_fields
.nested-fields
= f.input :user_id, collection: #users.order(:last_name), :label => "User"
= link_to_remove_association "Remove", f
Screenshot of page pre-remove:
Screenshot of post-remove:
Screenshot of post-update(page reload):
I would much rather, after the update, the page be reloaded and looking like below, which is the form for initially adding users to an asset:

When using strong parameters, you have to make sure to permit :id and :_destroy, as documented by the way (see documentation ).
It is not unlogical: cocoon sets the _destroy if something needs to be removed, rails then needs the id to know what to remove.

Im my case, i forget for allow_destroy: true.
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

Did you permit the nested parameter _destroy in either permit (strong_parameters) or attr_acceptible?
Your asset_profile_params should look like
def asset_profile_params
params.require(:asset_profile).permit(:max_users, :asset_users_attributes => {:user_id, :_destroy})
end

Related

Rails Form_For Select With Dual Purpose

I have form for adding a new job. On my form I have a select drop-down list. I need to associate the new job to a customer. The following works great.
<%= f.collection_select :customer_id, Customer.all, :id, :business_name %>
But, what if I want to also be able to send in a customer_id to the new form? Can I have the form's select drop-down show all the possible customers, as above, but have it auto select the customer_id I pass into the form, if a customer_id is passed in?
url = ...jobs/new
OR
url = ...jobs/new?customer_id=5
I apologize if I did not explain this well enough.
Thanks in advance.
--jc
I think you do what you're trying to achieve this by populating the customer_id field on the job you're creating in your controller if customer_id is present in the request params. This should make that particular customer be the initially selected option in the form.
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select
e.g. Something like.
if params[:customer_id].present?
job.customer_id = params[:customer_id]
end
If you declaring the instance variable #customer in your controller action then you can use selected option as:
<%= f.collection_select :customer_id, Customer.all, :id, :business_name, {:selected => #customer.id} %>

How do I generate a bunch of checkboxes from a collection?

I have two models User and Category that have a HABTM association.
I would like to generate checkboxes from a collection of Category items on my view, and have them associated with the current_user.
How do I do that?
Thanks.
P.S. I know that I can do the equivalent for a dropdown menu with options_from_collection_for_select. I also know that Rails has a checkbox_tag helper. But not quite sure how to do both of them. I know I can just do it manually with an each loop or something, but am wondering if there is something native to Rails 3 that I am missing.
Did you check out formtastic or simple_form
They have helpers to write your forms more easily, also to handle simple associations.
E.g. in simple_form you can just write
= simple_form_for #user do
= f.association :categories, :as => :check_boxes
In form_tastic you would write
= simple_form_for #user do
= f.input :categories, :as => :check_boxes
Hope this helps.
You can use a collection_select and feed it the options. Assuming you have a form builder wrapped around a user instance, you can do something like this:
form_for current_user do |f|
f.collection_select(
:category_ids, # the param key, so params[:user][:category_ids]
f.object.categories, # the collection of items in the list
:id, # option value
:name # option string
)
end
You may want to pass the :multiple => true option on the end if needed.

Selecting a default picture with radio button in a new nested attributes form

I've got a Rails project which has a car model and it has multiple pictures. I've created a nested form so I can input the cars details and pictures all at the same time. I would like a radio button to select the picture to display in the gallery.
%table
= simple_form_for [#car] :html => {:multipart => true} do |f|
= f.error_messages
= f.input :make
= f.input :model
= f.input :engine
= f.input :price
= f.simple_fields_for :car_pictures do |builder|
.picture
= builder.input :caption
= builder.input :picture
.thumb= image_tag builder.object.picture(:thumb)
= f.button :submit
Is it possible to use a radio button in the 'fields_for' section to select the default/main picture? Or is there a better way?
Update
By putting the following under the fields_for all the radio buttons work independently, which is not what I want.
= builder.radio_button(:favourite, "test")
Each radio button is getting a unique name.
Update
What if I used the object_id as the value, how would I go about linking this in the create method?
= f.radio_button(:favourite_pic, builder.object_id)
Yes, your last guess was correct. I made a test application in which the customer can select a favorite photo: https://github.com/eicca/attrs_test (see commit changes marked by "added favorite example").
There are two main points (according to your situation):
= f.radio_button(:favorite_pic_id, builder.object.id)
and
#models/car
has_one :favorite_pic, :class_name => "CarPicture"
And you need to add favorite_pic_id field to your cars table.
Why not? :) Only selected radio button will be sent to the server. So, only thing you've got to do - is to give it proper name/value and make sure that you have an accessor for it to support mass-assignment.

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

Accessing objects in semantic_fieds_for loop / formtastic

Model has accepts_nested_attributes_for for the relation and the form is as follows:
= semantic_form_for #obj, :url => path do |f|
= f.inputs do
= f.input :name
= f.semantic_fields_for :photos do |p|
= p.inputs :desc
= f.buttons
The form works well and everything is fine. However, I would like to display each photo near the field, so the user could se which picture she is going to annotate. Is there anyway, to access photo.id inside the fields_for loop?
Edit:
Is there any way to alter the order in which photos fields will be rendered in this example. As far as I can tell till now, that order is pretty random.
Well this was easy enough, the object is accesible by:
p.object
:-)
Second part of the question is solved with:
default_scope order(...)

Resources