Rails 3 - AJAX REST new form double submits on single user click - ajax

I have a standard form for the new action of a controller being submitted by AJAX. Every time the user clicks the submit button or presses enter once, the form is submitted twice immediately, creating two identical objects.
There are no validations on the model and there are instances where that is appropriate.
The form view looks like this:
<%= simple_form_for #contact, remote: true do |f| %>
<table>
<tr><td class="cell-right-align">First Name</td><td><%= f.text_field :first_name %></td></tr>
<tr><td class="cell-right-align">Last Name</td><td><%= f.text_field :last_name %></td></tr>
<tr><td></td><td><%= f.submit "Create Contact" %></td></tr>
</table>
<% end %>
The controller action for it:
def create
respond_to do |format|
if #contact.save
format.js { render 'search_result' }
else
format.js { render 'new' }
end
end
end
The logs for the create action show that on the same second there are two POST actions, both identical.
How can I stop the double POST? I've tried adding :disable_with => 'Saving...' to the submit button and it had no effect.

It might be asset pipeline issue. Can you run the app in production mode and verify that the assets are precompiled. I suspect that the javascript used to handle the submit is duplicated. Thus binding two identical events to the form submit.

Related

RAILS 4: Trying to get the current page to pass to render in an AJAX request

I have a fairly straight forward question.
On my site, within the header is a "invite a colleague" link to a modal that contains a form:
<%= simple_form_for(current_user, :url => send_invite_user_path(current_user), remote: true) do |f| %>
<%= f.label :email %><br>
<%= f.text_field :email, class: 'form-control' %>
<%= f.submit "Send", class: "btn btn-primary ShareSend" %>
<% end %>
Here is the send invite controller
def send_invite
#current_page = URI(request.referer).path
#email = params[:user][:email]
InviteWorker.perform_async(current_user.id, #email)
respond_to do |format|
flash.now[:success] = "Invite sent"
format.html { redirect_to #current_page, :current_page => #current_page}
format.js { render #current_page}
end
end
It works fine when not using AJAX, but I want to try to get it to work via AJAX. The issue is that the "current_page" when I open the modal and try to send via AJAX refers to the "send_invite" action and is looking for a "send_invite" template. I want it to render WHATEVER page the user is on. To add to my difficulty I am using friendly_id.....I tried using
#page_hash = Rails.application.routes.recognize_path(URI(request.referer).path)
To try to extract the user action from the current page path, but obviously this doesn't work with friendly id.
Is there a "Rails way" of capturing the current page (ignoring the modal) and passing this to render....
I hope this is clear...
An AJAX call does not trigger a complete reload of the current page (unless explicitly told to). The request is handled in the background by javascript.
In your case you should add a view called send_invite.js.erb (i guess in your app/views/users folder - assuming that send_invite belongs to UsersController) that has some javascript that notifies the user of a successful invite and closes the modal. This view could be as simple as:
alert("Invite sent!");window.closeMyInviteModal();
This script will be executed if (and each time) the AJAX call succeed.
Clean the js responder in send_invite. This will by default render the send_invite.js view.
format.js { }
See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#a-simple-example

Rendering partial template after redirect to another url

My goal is to display a welcome message for the user after they create a new account and are redirected to their profile page; i.e., have the message be displayed on their profile page.
With the following code, I'm able to display the message but only for a split second - before the redirect occurs, which is nevertheless successful.
In my controller, I create the message and use an Ajax call to render my JavaScript template:
def create_user
# ...
#welcome_msg = "WELCOME"
format.js { render template: "layouts/message.js.erb" }
# ...
end
message.js.erb
$(window.location.replace("<%= profile_url %>"));
$("#welcome_message_placeholder").html("<%= j render partial: 'layouts/welcome_message', locals: { :user => #user, :welcome_msg => #welcome_msg } %>");
_welcome_message.html.erb
<%= #welcome_msg %>
application.html.erb
<div id="welcome_message_placeholder"></div>
What do I need to add/change to ensure that the user sees the message only after being redirected?
Turns out that one way to do this involves a slightly different approach from what I had above.
What I did (and what worked, thankfully) was I created a new flash type in my users controller that I then defined in all of my controllers (to avoid it being undefined in my application template) like so:
add_flash_types :custom_notice # included in all controllers
def create_user
# ...
format.js {render js: "window.location.href='#{profile_url}'"} # to replace message.js.erb
flash[:custom_notice]="WELCOME"
# ...
end
Now the message can essentially be treated as a traditional notice in the base template, and the partial can be rendered directly (without a JS template middleman):
application.html.erb
<% if custom_notice %>
<%= render partial: "layouts/welcome_message" %>
<% end %>
_welcome_message.html.erb
<%= custom_notice %>
Note that add_flash_types (registering custom flash types) isn't supported in Rails 3.

Rails 3 each method and Ajax

I'm trying to implement some Ajax in my app. A strange behaviour occurs!
It's a daycare application. When you show a specific daycare of a specific date you can add some children.
Originally a list of the children of the database is generated and when you click on one of them the page reload and a new child appears in the attendance list of the daycare. It's working fine, i just wanna add some ajax to be more userfriendly !
When you click on child to add him to the daycare, a daycare_item is created ( join table, an id of the child and the id of the daycare ).
I make the changes to make it ajax ready:
partial for the list
format.js in the daycare_item controller
remote true on the link.
It works, no more reload! But the list is updated only when you click a second time on the children list ( the last child added doesn't appears yet ). The js transaction works and if you refresh manually the page, the missing child appears.
I tried few things and here are my results:
In my partial there are
<% #daycare.daycare_items.each do |c| %>
<li><%= c.child.firstname ></li>
<% end %>
This produce the "lag" effect with one children who is not showing ( until a full refresh )
But if i put a
<%= #daycare.daycare_items.count %>
the code is update in time !
I see nothing strange in the logs.
I'm asking why the .each method make a difference?
A var was stoping a part of the code to be executed, the var wasn't wrong and doesn't generate an error.
The elements involved:
daycare_items controller
def create
#daycare = Daycare.find(params[:daycare_id]) # for Ajax
#daycare_item = DaycareItem.new(params[:daycare_item])
....
end
the create.js.erb
$('#children-list').html(" <%=j render partial: 'daycares/daycare', locals: { daycare: #daycare } %> ");
the view daycares#show
<div id="children-list">
<%= render #daycare %>
</div>
the partial ( a part of ) _daycare.html.erb
<p>counting test:<%= daycare.daycare_items.count %></p>
# here was something like this <%= #waiting.count %> #waiting is define in the daycare controller but not in the daycare_items controller
<p>
<% daycare.daycare_items.each do |dci| %>
<%= dci.enfant.prenom %>
<% end %>
</p>

update page with with new data selected from dropdownlist in rails 3.2

I have dropdown list using select_tag and I have button near it.
I have following requirements:
1) on click of submit button it should go to books#show action
2) Then in show action I retrieve the selected book from dropdown list
3) The show method should show details of book that I would retrieve from database
i.e,the same page should update with this book details.
However,I am unable to perform none of this.
In my view:
<%= form_tag books_path do |f|%>
<%= label_tag "select book" %>
<%= select_tag "selectbook", options_from_collection_for_select(#bid,"book_id","book_id"), :prompt => "Select book",:class => 'cmbbook' %>
<%= submit_tag "view ...", :disable_with => "Please wait." ,:action => "show"%>
<%end%>
In my controller
if(params[:selectbook])
#books = Book.where("book_id = ?",params[:selectbook])
else
#books = Book.all
end
#bid= Books.select("book_id").uniq;
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #books }
format.json { render json: #books }
end
The submit method calling action create instead of show and I also wish the page autoupdate with new book data.
First of all, you should specify controller and action for the form, like this
form_tag( {:controller => 'your_controller', :action => "show"} )
For autoupdating page you should read rails doc
I have found what to do:
I have to write a method in javascript that calls getJson() method to appropriate controller and action and again update view using javascript.Thus,using ajax javascript problem is solved.However,I wish I can do same with pure ruby code.

2 instance variables of the same name in different controllers

I finished Michael Hartl's Ruby on Rails Tutorial. Now I'm working on the suggested exercises. The application he builds is basically a Twitter clone where one can post Microposts and they appear in your feed http://ruby.railstutorial.org/chapters/user-microposts#fig-micropost_created
The main page is in home.html.erb from the StaticPagesController and features a Micropost textbox where one can post Microposts. The code for the textbox looks like so:
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
The #micropost variable is initialized in the StaticPagesController like so:
class StaticPagesController < ApplicationController
def home
if signed_in?
#micropost = current_user.microposts.build
end
end
Now inside the MicropostsController there's a create action like so:
def create
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
My question is what is the purpose of the first #micropost variable as opposed to the second?
thanks,
mike
The first #micropost becomes available to the view rendered by the first controller method; the second #micropost becomes available to the view rendered by the second controller method. And it just so happens that the two methods are rendering the same view.
The only wrinkle is that since the second controller is conditional. If the create succeeds (passes validation and saves) then there's a redirect, so there's no proper view (although there will be in a moment, after the client-side redirect). But if it fails, then the view gets an object that contains the user-entered values as well as the validation errors which the view can then show to the user.

Resources