Nested Forms - Ajax Delete - ruby-on-rails-3

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

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.

rails3 jquery autocomplete how to get the id and full name while typing

1 - how can i get the id based on the first or last name selected?
2 - I was able to have it work for first name or last name, but i want to be able to have a full name (based on first or last name) when i start typing. For example when i type ev be able to see Evelin mars, Steve bach, Matt Evans, ....
I have a full name function in my person.rb model.
Is it possible?
view
<%= autocomplete_field_tag 'person_ids[]', '', autocomplete_person_last_name_segments_path, 'data-delimiter' => ',', :multiple => true, :id_element => '#some_element', :placeholder => "type a name" %>
controller
class SegmentsController < ApplicationController
autocomplete :person, :last_name
...
route.rb
resources :segments do
get :autocomplete_person_last_name, :on => :collection
end
person.rb
def full_name
"#{first_name} #{last_name}"
end
UPDATE
I were able to show the full name by adding :extra_data => [:first_name], :display_value => :full_name to the controller and it becomes
controller
class SegmentsController < ApplicationController
autocomplete :person, :last_name, :extra_data => [:first_name], :display_value => :full_name
...
But how do i get the id?
If you look at your AJAX response, you should see that by default, the id is also returned.
I believe that you actually want to use this id. This is what you can do in your view, using :ide_element => #Your_model_id" :
<%= autocomplete_field_tag 'some_label', '', your_autocomplete_path, :id_element => '#yourmodel_id', class: "form-control" %>
<%= f.hidden_field :yourmodel_id, :value => nil %>
You can have a look at the github page of the gem, there is a paragraph dealing with this.

condition in partial from other controller

I have a model group -> has_many :questions and a question -> has_many :votes
In my my view show, for the controller groups, I have a partial that can display the list of the questions :
<%= render :partial => 'question', :collection => #group.questions.byvote %>
Then I have a link to vote with a style like this :
<%= link_to(question_votes_path(question), :controller => :vote, :action => :create, :method => :post, :id => 'vote') do %>
<%= image_tag("voteUp.png")%>
<%= question.votes_count%>
<%end%>
What I would like to do is make a condition, like :
<% if canvote?%>
… and change the style of the div.
BUT. Making a condition in the group controller can't be made because I need to make my request about the question and not about the group :
Vote.where(:user_id => current_user.id, :question_id => #question.id).first
How can I make it form the other controller group or tell an helper_method in the question controller ?
I think you should use a model method - you can then call it right in the view and do so unobtrusively. The following method will return true if the user has voted on a given question:
User.rb
def voted?(question)
#returns true if vote exists
Vote.exists?(:user_id => current_user.id, :question_id => question.id)
end
You can use it like this:
_question.html.erb
<% if current_user.voted?(#question) %>
#code to use if the user has voted on this question
<% else %>
#code to use if the user has NOT voted on this question
<% end %>

Rails Jquery How to submit multiple forms via ajax

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');
});
});
});

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()