Rails 3.2.8 not firing ajax callbacks - ruby-on-rails

I'm having problems with rails 3.2.8 and ajax callbacks... it seems those are not firing at all... I've tried binding with Jquery code (I can see the js script on the chrome toolbox) and I've even tried putting the :success => 'alert("bla")' on the link_to line, but it still doesn't do anything... the controller works since my row is actually deleted... but can't bindd to the callbacks! please help!
Here is my view line:
<td><%= link_to 'Destroy', pet, :method => :delete, :remote=>true, :class => 'delete_pet' %></td>
Here is my controller action
def destroy
#pet = Pet.find(params[:id])
#pet.destroy
respond_to do |format|
format.html { redirect_to(pets_url) }
format.js { render :nothing => true }
end
end
and here is my js code:
jQuery(function($) {
$('.delete_pet').bind("ajax:before", function(){alert('bla2');})
.bind("ajax:success", function(){alert('bla2');})
.bind("ajax:failure", function(){alert('bla2');})
.bind("ajax:complete", function(){alert('bla2');});
});

replace
format.js { render :nothing => true }
with
format.json { render :nothing => true }
and also replace
<%= link_to 'Destroy', pet, :method => :delete, :remote=>true, :class => 'delete_pet' %>
with
<%= link_to 'Destroy', pet, :method => :delete, :remote=>true, 'data-type'=>'json', :class => 'delete_pet' %>

I've been having similar issues with the respond_to blocks. I've gotten around it temporarily by checking the request. For example, you're code would look like:
def destroy
#pet = Pet.find(params[:id])
#pet.destroy
if request.xhr?
# the request was received via an AJAX request
render :nothing => true
else
redirect_to(pets_url)
end
end
Not as elegant as the resond_to block, but it seems to reliably work as expected.
Good luck!

The problem was that on my application.js I was including manually a jquery file... like this..
//= require jquery-ui-1.8.23.custom
shame on me!

Related

Destroy method does not work, instead show method implements (Rails)

I need to make a button to destroy object.
Instead of destroy it shows fields
inex.html.erb
<%= link_to image_tag("/images/glossy_green_button.png"), device , { :html => { :method => :delete}, :controller => :devices, :action => 'destroy',:id => device.id, :onclick => 'return confirm(\'Are you sure?\');' }, :method => :turnon %>
devices_controller.rb
def destroy
#device = Device.find(params[:id])
#device.destroy
respond_to do |format|
format.html { render action: "destroy" }
format.json { head :no_content }
end
end
routes.rb
device GET /devices/:id(.:format) devices#show
PUT /devices/:id(.:format) devices#update
DELETE /devices/:id(.:format) devices#destroy
Appreciate any ideas what I got wrong.
Thank you
D
UPDATED:
<%= button_to "Delete", device , :method => :delete %>
this works fine
Which version of Rails are you using? Why your link_to method calling is so complex? It can be simply re-written. Try the following one:
<%= link_to image_tag("/images/glossy_green_button.png"), device , :method => :delete, :confirm => "Are you sure?"
Destructive actions should be performed as a form submission - http://www.w3.org/2001/tag/doc/whenToUseGet.html#checklist
use button_to (passing a :method of :delete) instead and style the button appropriately.
or Try this <%= button_to "delete", your_object, :method=>:delete, :class=>:destroy %>

Rails : User logged out after destroying an unrelated object with :remote => true

I'm following http://railscasts.com/episodes/250-authentication-from-scratch for simple authentication. It works as expected. I have a model in my app with the following partial :
<%= content_tag_for(:li, post) do %>
<%= link_to 'Delete', post, :confirm => 'Are you sure?', :method => :delete, :remote => true %>
<% end %>
It is called within index.html.erb as follows:
<%= render :partial => #posts.reverse %>
The destroy.js.erb is as follows, which is called if the object is successfully destroyed.
$('#<%= dom_id(#post) %>').css('background', 'red');
$('#<%= dom_id(#post) %>').hide();
On clicking the delete button, the post object gets deleted properly and the destroy.js.erb is rendered correctly too. But somehow, the user is logged out. Following is the code for my posts_controller.rb :
def destroy
logger.error 'in destroy'
#post = Job.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to(posts_url) }
format.xml { head :ok }
format.js
end
end
Any clues why this behavior?
And, if I remove the :remote => true from the delete link, then the user remains logged in. I have log statements in the destroy method for session that are never called in either case, but if ':remote=>true then the session is somehow screwed up. On checking the cookies, I found that the cookie is not destroyed but it does get modified when the destroy method on posts is called. Not sure why this has to happen.
Sounds like you are bumping into a rails security feature that is meant to protect against Cross Site Request Forgery. Adding :remote => true causes the request to be submitted via ajax without CSRF security tokens, so rails clobbers the session because it thinks it is a CSRF attack. To get around this you have a few options:
A quick and dirty (and insecure) solution is to turn off the security check for that request. To do this add this line to the top of your controller:
skip_before_filter :verify_authenticity_token, :only => [:destroy]
A more secure solution is to submit the CSRF token with the AJAX call. I think this will happen automatically if you change your remote link to a button_to. Read more here.
<%= button_to 'Delete', post, :confirm => 'Are you sure?', :method => :delete, :remote => true %>
You could also cookies to store the current_user rather than the session. The security implications of this will depend on the details of your app.

How do you recreate a remote link with the same .js update in Ruby on Rails?

Basically I want to make a link able to be refreshed dynamically from "Favorited" to "Removed", and at the same time give the user the option to go go back by reclicking the new button. The action does happen though, because when I refresh the page the updated button shows. Why does clicking the "Favorite this Classroom" link not work? The "Remove this Classroom" link seems to work. Thanks for your help
favorites_controller.rb:
def create
current_classroom.add_to_favorites(#classroom)
current_classroom.save
respond_to do |format|
format.js { }
format.html {redirect_to #classroom}
end
end
def destroy
current_classroom.remove_from_favorites(#classroom)
current_classroom.save
respond_to do |format|
format.js { }
format.html {redirect_to #classroom}
end
end
favorites/create.js.erb
$("#favorite_classroom").html("<%= escape_javascript(link_to 'Remove the Classroom', classroom_favorite_path(#classroom), :remote => true, :method => :delete) %>");
classrooms/_classroom_details.html.erb
<div id="favorite_classroom">
<% if loggedin_user.favorite_classroom?(#classroom) %>
<%= link_to 'Remove this Classroom', classroom_favorite_path(#classroom), :remote => true, :method => :delete %>
<% else %>
<%= link_to 'Favorite this Classroom', classroom_favorites_path(#classroom), :remote => true, :method => :post %>
<% end %>
routes:
classroom_favorites POST /classrooms/:classroom_id/favorites(.:format) {:action=>"create", :controller=>"favorites"}
classroom_favorite DELETE /classrooms/:classroom_id/favorites/:id(.:format) {:action=>"destroy", :controller=>"favorites"}
Error when I click on the "Favorite this Classroom" link:
ActionView::Template::Error (No route matches {:action=>"destroy", :controller=>"favorites"
Thanks!
You are using double-quotes twice in your js file. You can't do that. You need to rewrite it like this -
$("#favorite_classroom").html("<%= escape_javascript(link_to 'Remove the Classroom', classroom_favorite_path(#classroom), :remote => true, :method => :delete) %>");
Notice now that Remove the Classroom is enclosed in single quotes rather than double.
In addition, your route is incorrect because you have nested favorites within classrooms. When you write the link, you need to add the #favorite object that you are trying to delete:
= link_to 'Remove Favorite', classroom_favorite_path([#classroom, #favorite]), :remote => true, :method => :delete
Now the route you are trying to access is valid. That should get rid of the error.
I don't think you need the favorite controller, what you need is favorite/unfavorite action for classroom controller. Here's how it might look
classroom_controller.rb
respond_to :html, :js
def favorite
# ... find classroom by id
# do your stuff
#classroom.favorite = !#classroom.favorite
respond_with(#classroom)
end
views/classrooms/favorite.js.erb
<%# the message should be oposite to favorite %>
<% msg = #classroom.favorite ? "Remove this Classroom" : "Favorite this Classroom" %>
$("#favorite_classroom").html("<%= escape_javascript(link_to msg, [:favorite, #classroom], :remote => true) %>");
Here's the trick with path helper, [:favorite, #classroom] should be transleted to /classrooms/:id/favorite. If it won't work then try favorite_classrooms_path(#classroom)
And finally add to your routes.rb
resource :classrooms do
member { get :favorite }
end
Looks like you need to reference 'favorite_id' in your link to match your routes.
In your case, would probably be:
classroom_favorite_path([current_classroom, #classroom])

Deleting from a namespace

I have setup a admin namespace in order to access models in the admin area: /admin/pages
However i have the following problem
i cant get the delete function to work under Admin::PageController for example or any of my models.
Does anyone know how to do this.
I have the following:
Admin::PageController I have the following
def destroy
#page = Page.find(params[:id])
#page.destroy
respond_to do |format|
format.html { redirect_to admin_pages_url }
format.json { head :ok }
end
end
Then on my page index file where i want a link to delete the record i have the following: (/admin/pages)
<%=link_to admin_page_path(page), :class => 'ico del' do %>
<%='Delete'%>
<% end %>
Does not seem to work. Anyone know how to get this to work?
you have missed :method option in link_to call
link_to 'Delete', admin_page_path, :confirm => 'Are you sure?', :method => :delete
or
<%=link_to admin_page_path(page), :class => 'ico del',:method => :delete do %>
<%='Delete'%>
<% end %>
The link_to helper defaults to a GET request unless you specify additional attributes to tell it how you want it to be handled.
In this case, you need to set some extra arguments:
<%=link_to "Delete", admin_page_path(page), :class => "ico del", :remote => true, :method => :delete %>
What actually happens in the background is the Rails UJS (unobtrusive javascript adapter) captures the click event and sends the request via AJAX. So you should see it hit your server with a POST (but it passes in _method => delete as well) to delete the object.
I'm also assuming you have your routes set up correctly. Something like:
namespace :admin do
resources :pages
end

Adding routes for actions that operate on one record in rails

I want to create a method in my rails app that will increase a value tied to a record.
The method in the controller looks like this:
def upvote
#spot = Spot.find(params[:id])
#spot.rating += 1
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #spot }
end
end
Then when viewing the record at "spots/1" I include this code:
<%= link_to 'Upvote', #spot, :confirm => 'Are you sure?', :method => :upvote %>
Which, when clicked, throws the error:
"No route matches "/spots/1""
Even though I'm already at /spots/1. I know this is a routes issue, but I can't seem to give this method a route that works...
The parameter :method identifies the HTTP verb (GET, POST, UPDATE, ...), not the method to be called.
To add a new action, edit the routes.rb file
resources :sposts do
member do
put :upvote
end
end
Then use a named route
<%= link_to 'Upvote', upvote_spot_path(#spot), :confirm => 'Are you sure?', :method => :put %>

Resources