Rails Jquery How to submit multiple forms via ajax - ruby-on-rails-3

I have a form with a has_many association and I would like to submit multiple forms via ajax so the parent form's show page can be updated dynamically.
I have the following models (they are in mongoid but i don't think it matters between mongoid and activerecord):
class User
include Mongoid::Document
include Mongoid::Timestamps
has_many :tasks
end
class Task
include Mongoid::Document
include Mongoid::Timestamps
belongs_to :user, inverse_of: :tasks
end
I have a form which renders n partials of the form:
<%= form_for #task, remote: true do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
for new tasks on the show.html.erb for user via ajax.
How can i write a single submit button on the show.html.erb to submit all of the tasks at once while associating them with the parent user?

Based on the second answer to this question: Rails 3: How to trigger a form submission via javascript?
Say you have a button with an id called #multiSubmit, then you can submit each form when it is clicked using the following JavaScript:
$(function() {
$("#multiSubmit").click( function() {
$('form').each(function(i, item) {
$(item).trigger('submit.rails');
});
});
});

Related

How do I create a form that will update the value of a field for selected records?

I am using a link from an index page that has a group of nested records (row) that I need to update all at once. The link goes to an edit action that I need to make update the attributes of nested records (prisms).
I tried using the simple_form gem methods for nested models. It gives me a field for all of the objects, when I only want one field to enter a value to them all. The builder from that looks usable, but I don't know how to use it to update the fields. Either way, the form isn't right.
I have tried every variation of form_for and fields_for I could find on Google to develop the edit form. It looks like I'm the only one on Earth trying to solve this problem.
This is how I have my routes set up:
resources :gardens, shallow: true do
resources :prisms
resources :rows
Here is how my garden model is now:
class Garden < ApplicationRecord
mount_uploader :picture, ImageUploader
belongs_to :user
has_one :photo
has_many :rows, :dependent => :destroy
has_many :prisms
geocoded_by :address
after_validation :geocode
after_commit :populate_garden!
def id
self[:id]
end
def populate_garden!
# row 0
(0..length-1).each do |i|
Row.create(row_num: i, garden_id: id)
end
end
end
The garden model creates my rows through the populate_garden! method.
Here is the row model:
class Row < ApplicationRecord
belongs_to :garden
has_many :prisms, :dependent => :destroy
accepts_nested_attributes_for :prisms
after_commit :populate_rows
def id
self[:id]
end
def populate_rows
# row 0
(0..garden.width-1).each do |i|
Prism.create(:row_id => self.id, :row_num => self.row_num, :col_num => i, :garden_id => self.garden_id)
end
end
end
The row model creates prisms in the populate_rows method.
Here is the prism model:
class Prism < ApplicationRecord
belongs_to :row
belongs_to :garden
include RankedModel
ranks :column_order
end
Here is the table from my index.html.erb that I click to open the edit action.
<table>
<% #rows.each_with_index do |gardenrow, index| %>
<% #rows.select { | row | row.row_num == index}.each do |row| %>
<td class="prism-cols">
<%= link_to 'Edit Row', edit_row_path(row), class:"dark-link" %>
<br /><i class="fas fa-arrow-down"></i>
</td>
<% end %>
<% end %>
</table>
The row passes nicely into the edit action, and I currently have this incorrect form:
<h1>The row brought into this form page is: </h1>
<%= #row.inspect %>
<div class="container">
<%= simple_form_for #row do |m| %>
<%= m.simple_fields_for :prisms do |p| %>
<%= p.input :crop_name %>
<% end %>
<%= m.button :submit %>
<% end %>
</div>
The rows_controller update method looks like this:
def update
#row = Row.find(params[:row_id])
#row.prisms.build
redirect_to root_path
end
I need one form field for crop_name that will change all of the prisms in the selected row with a single submit. I don't have any problems updating one prism at a time through an edit action on the prism. The difficulty I'm having is working through the nesting of prisms inside of a specific row.
With the help of my mentor below I was able to develop a form that works with the controller to make this work. Here is the updated code for later use with this type of problem.
Here is the form data:
<%= form_tag({controller: "rows", action: "update"}, method: "patch") %>
<%= label_tag(:crop_name, "Crop Name") %>
<%= text_field_tag(:crop_name) %>
<%= hidden_field_tag(:row_id, #row.id) %>
<%= submit_tag("submit") %>
Here is the controller update method:
def update
#row = Row.find(params[:id])
#garden = Garden.find_by_id(:garden_id)
#row.prisms.each do |p|
p.crop_name = params[:crop_name]
p.save!
end
redirect_to :controller => 'gardens', :action => 'show', id: #row.garden_id
end
Thanks for the help. I don't think I could have figured this out from the documentation alone.
If I'm understanding correctly, I think simple_form may be limiting you. A basic ruby form may do what you want. I'm not 100% sure what the best way is to do a simple_form on nested fields but this stackoverflow answer may be able to help more.
Using a basic ruby form
You want a form that has one field. When submitted, it will take the value from the submitted form and update that field for all prisms of that row. I would recommend digging more into the basics of ruby forms for this kind of scenario and then do something like this.
// html.erb
<%= form_tag({controller: "rows", action: "update_prism_crop_name"}, method: "post", class: "nifty_form") %>
<%= label_tag(:crop_name, "Crop name") %>
<%= text_field_tag(:crop_name) %>
<%= hidden_field_tag(:row_id, #row.id) %>
<%= submit_tag("Submit") %>
<% end %>
// rows_controller
def update_prism_crop_name
#row = Row.find(params[:row_id])
#row.prisms.each do |prism|
prism.crop_name = params[:crop_name]
prism.save!
end
# other redirect stuff
end
The form_tag explicitly calls out an action but I have to imagine that you'll need to build a route for this custom action as well.
I haven't tested any of this and I'm a bit rusty in rails but I believe something like this would work.

ActiveAdmin bug? Nested form in show resource page does not display form submit button

I am using ActiveAdmin to build an article show page where new comments can be added using a nested form but facing a problem. Article has_many :comments and also accepts_nested_attributes_for :comments. It all works fine in Rails console but I can't get the form submit button to show up. Here is my code for customizing activeadmin's show page for Article:
show do |article|
attributes_table do
row :id
row :title
end
div do
semantic_form_for [:admin, article], builder: ActiveAdmin::FormBuilder do |f|
f.has_many :comments, allow_destroy: false, new_record: true, heading: false do |g|
g.input :body
end
f.actions
end
end
end
The nested form is displayed and works correctly but the submit button is not displayed (meaning that f.actions has no effect).
Workaround: I moved the Nested form to a view and i'm able to see the "Update" button. like
show do
attributes_table do
row :id
row :description
end
panel "Link Projects" do
render partial: 'project_links', locals: { id: company }
end
end

Rails 3: Ajax nested resource delete

I have a nested resource model in my Rails 3 app. It is the standard blog app with posts and comments. I have just started using jQuery etc to make my app more dynamic, I am now struggling to remove comments in the nested model with the link_to helper.
Comments Model
class Comment < ActiveRecord::Base
belongs_to :post
end
Post Model
class Post < ActiveRecord::Base
has_many :comments, :dependent => :destroy
accepts_nested_attributes_for :comments
end
In my Posts/show.html.erb I have the following bloc that displays all the comments with a link_to helper to delete the comments. This works with HTML but when I added :remote => true, it deleted the parent post instead of the comment! How can I set it up so it deletes only the comment?
<% #post.comments.each do |comment| %>
<%= comment.body %>
<%= link_to "Approve", [#post,comment], :method =>:put, :remote=>true %>
<%= link_to "Delete", [#post,comment], :method =>:delete, :remote=>true %>
<%end%>
Thanks,
I think you want to have this in your delete action of your Comment class:
def delete
...
respond_to do |format|
format.html
format.js
end
end
Then, in your views/comments directory, you should have a file named delete.js.erb that does your jQuery DOM manipulation (finds the particular comment that you clicked the delete link of and remove it.
Then, your link_to for the delete method in your Posts/show.html.erb file, you can specify the controller and action, and also pass in any data you might need (the parent post so you can refer to it in your jQuery). You can refer to the first examples section of this site for the syntax on specifying a particular controller and action for a link_to helper here.
Just check the corresponding action in the controller.
If there is a render or redirect_to just delete it
it works for me (Rails 4)

Rails 3 save model and redirect using coffeescript

I have user class (using devise) and my User class has email subscriptions
class User < ActiveRecord::Base
...
has_one :email_sub, :class_name => "Subscriptions::EmailSub", :dependent => :destroy
end
I have a route
match 'profile', :controller => 'users', :action => 'view_profile'
and related controller that calls a specific file
class UsersController < ApplicationController
def profile
#subscriptions_email_sub = current_user.email_sub
end
end
And in the profile.html.erb file have a form (technically in a partial included in the template but I don't think that will make a difference) where the user can use radio buttons to set subscription options (subscribed or unsubscribed). The button part of the form is below:
<%= form_for(#subscriptions_email_sub) do |f| %>
...
<tr>
<td>Announcements</td>
<td><%= f.radio_button :announcements, 'announcements', :checked => #subscriptions_email_sub.announcements %></td>
<td><%= f.radio_button :announcements, 'announcements', :checked => !#subscriptions_email_sub.announcements %></td>
<td></td>
<td>Updates about the website and service</td>
</tr>
<%= f.submit "Update Subscriptions", :id => 'update_subs' %>
<% end %>
I'm trying to add coffeescript so when the user clicks the button it saves the model and notifies the user the settings have been updated (or an alert if there's an error).
(Alternatively I'm fine saving the model and reloading the whole page.)
So far I have in users.js.coffee
$ ->
$('#update_subs').click ->
$('form').submit();
I can't figure out how to get the page to reload. I think the form submit will cause it to use the controller for Subscriptions::EmailSub which will then try to load app/views/subscriptions/email_subs/show.html.erb I suspect I may have to use javascript to save the class and the reload the page.
Thanks for any help.
You don't need that code in users.js.coffee, you can make the form remote:
<%= form_for(#subscriptions_email_sub), :remote => true do |f| %>
This will submit the form asynchronously, expecting a JS response (unless you specify another content-type such as JSON).
You'll need to have a controller action to handle this update, presumably your SubscriptionsController.
It should respond to javascript requests:
class SubscriptionsController < ApplicationController
respond_to :js
...
def update
#subscription = Subscription.find(params[:id])
...
respond_with(#subscription)
end
end
Then you can simply add an update.js.coffee file to your views/subscriptions folder and add any changes you want to make to the DOM in there, just as you would for regular javascript.
# update.js.coffee
alert "Email subscription updated!"
$('form').ignite_fireworks()

Nested Forms - Ajax Delete

I have a nested form structure as follows:
class List < ActiveRecord::Base
has_many :restaurants, :dependent => :destroy
end
class Restaurant < ActiveRecord::Base
belongs_to :list
end
I can add restaurant items to a particular list in the same form where I create/edit a list. In order to nest the restaurant items within the list form I do the following:
<%= f.fields_for :restaurants do |builder| %>
<%= render 'restaurant_fields', f: builder %>
<% end %>
<%= link_to_add_fields "+ add to stack", f, :restaurants %>
The restaurants field partial has a link to remove an item:
<%= link_to "remove stack item", '#', class: "remove_fields" %>
The jquery (coffeescript) for these actions is as follows:
jQuery ->
$('form').on 'click', '.remove_fields', (event) ->
$(this).prev('input[type=hidden]').val('1')
$(this).closest('fieldset').hide()
event.preventDefault()
$('form').on 'click', '.add_fields', (event) ->
time = new Date().getTime()
regexp = new RegExp($(this).data('id'), 'g')
$(this).before($(this).data('fields').replace(regexp, time))
event.preventDefault()
When I click on remove stack item, I want to send an ajax request so that the stack item (restaurant) is not only hidden from the view (see above), but also the actual record is deleted at the same time. How would you advise I go about this?
You can pass in the _destroy param to do so:
Example attributes received from the client:
"restaurant" => { "stack_item" => { "id" => "987", "_destroy" => "1" } }
You will need to enable the :allow_destroy option on the association in the Restaurant model too.
See more here : Active Record Nested Attributes