Rails Project not Handling Request through AJAX - ruby-on-rails

I have an otherwise functioning rails project where I'm trying to update some form controls to work over AJAX instead of HTML. But my controller continues to handle it as HTML instead of JS and I'm not sure why.
The link I'm trying to make remote in my users/index.html.erb:
<%= link_to 'Disable', disable_user_path(user), :confirm => 'Are you sure?',
:method => :put, :remote => true %>
Rendered as:
<a href="/users/1/disable" data-confirm="Are you sure?" data-method="put"
data-remote="true" rel="nofollow">Disable</a>
My Users Controller:
def disable
#user = User.find(params[:id])
if #user.update_attribute(:enabled, false)
respond_to do |format|
format.html { redirect_to root_path, :flash => { :success => "Disabled." }}
format.js {}
end
else
redirect_to root_path, :flash => { :error => #user.errors.full_messages }
end
end
My includes in application.html.erb:
<%= javascript_include_tag "//ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", "//ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js", "jquery.rails.js", "application" %>
I think I pulled down the third and fourth files from a standard place, but if those are possibly the culprit I can look inside them or track down more information about them.
When I test it, it doesn't prompt me with "Are you sure?" and it responds with the redirection and "Disabled" flash message, and the server logs confirm it's being handled as html.
Started GET "/users/1/disable" for 127.0.0.1 at 2012-02-11 17:17:31
-0200 Processing by UsersController#disable as HTML

You may still need to include the unobtrusive javascript adapter if you have not done so already.

It looks like jQuery is not being loaded.
Check your include tag, specifically the resource path...
<%= javascript_include_tag "//ajax.googleapis.com/ajax/libs/....." %>
Most browsers will interpret //... as a local resource, as in local to the browser.
Paste the URL into a browser and see if it will load. I bet it will fallback to the file:// scheme, then complain about not being found (on your local machine).
Either add a http:// scheme on there, or get rid of the double slashes.
<%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/....." %>
# or...
<%= javascript_include_tag "ajax.googleapis.com/ajax/libs/....." %>

The problem ended up being that my includes weren't grabbing all the files that were apparently needed. I blasted my javascripts directory, installed the gem from scratch per the instructions in the readme, and changed my include to this:
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js", :defaults %>

Related

Getting "Template is missing" error when attempting to render js.erb file

I'm new to Rails, and I'm having an issue where I can't render a .js.erb file. I think the root of the issue is that Rails' internal routing mechanism expects me to name and configure my files just so, but I'm missing one or two pieces, and I'm not sure how to look for what needs to be fixed.
I have an HTML view with a link to a controller action:
<%# snip %>
<div id="holding_issues_list">
<%= link_to "Show issues on hold", {
:action => "show_user_issues",
:controller => "support",
:issue_type => "holding",
:user_id => #user.id },
:remote => true %>
</div>
<%# snip %>
I think (but I'm not sure) that :remote => true causes the link to make an AJAX call.
This is the corresponding controller action in the controller app/controllers/support_controller.rb:
def show_user_issues
#target_div = params[:target_div] || "holding_issues_list"
user = User.find(params[:user_id])
issue_type = params[:issue_type]
#snip - set the value of #issues
end
I want this file, named show_user_issues.js.erb and placed in app/views/support, to be rendered when the controller exits:
$("#<%= #target_div %>").show();
alert('test');
$("#<%= #target_div %>").html(
"<%= escape_javascript render :partial => '_show_user_issues', :locals => {:target_div => #target_div, :issues => #issues} %>");
This is app/views/support/_show_user_issues.html.erb, the partial I want show_user_issues.js.erb to render:
<% for issue in #active_issues %>
<div id="issue_<%= issue.id %>_display">
<%= render :partial => 'show_issue_mini', :locals => {:issue => issue} %>
</div>
<% end %>
When I try clicking the link in my original HTML view, nothing happens. When I open it up in a new tab, I get this error message:
Template is missing
Missing template support/show_user_issues,
application/show_user_issues with {:locale=>[:en],
:handlers=>[:builder, :erb], :formats=>[:html]}. Searched in: *
"/home/<>/app/views" *
"/home/<>/gems/kaminari-0.14.1/app/views"
The alert('test') that I put into show_user_issues.js.erb doesn't show up, so I think that Rails is getting hung up on rendering that file - that is, the routing mechanism can't find it. How can I correct this issue?
P.S. I double-checked that I put in all the file names exactly as they are in the code base.
Change your controller action to handle the type of request.
def show_user_issues
#target_div = params[:target_div] || "holding_issues_list"
user = User.find(params[:user_id])
issue_type = params[:issue_type]
#snip - set the value of #issues
respond_to do |format|
format.js
end
end
This will check the format of the request which is .js in case of :remote => true. So it will handle it by rendering the show_user_issues.js.erb file.
A couple other problems that I ran into after applying Manoj Monga's answer that I suspect other new Rails devs might run into:
In show_user_issues.js.erb, I had
[...].html("<%= escape_javascript render :partial => '_show_user_issues',[...]
The underscore before '_show_user_issues' caused the ERB builder to fail. It should have just been 'show_user_issues'.
In _show_user_issues.html.erb, I had
<% for issue in #active_issues %>
If you look closely at show_user_issues.js.erb, though, I named the variable #issues, not #active_issues:
[...]:locals => {:target_div => #target_div, :issues => #issues}[...]
So I changed the line in the HTML partial to
<% for issue in #issues %>
After these last couple changes, the new functionality I was adding worked as expected.

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.

Ajax post/gets (forms/links) submits multiple times in jQuery UI tabs

I've implemented jQuery UI tabs in an Rails app, and I get an error:
When i submit a ajax form or link, it gets submitted multiple times.
As seen in this Doom console output:
DELETE http://localhost:3000/innmeldings/101 404 (Not Found)
DELETE http://localhost:3000/innmeldings/101 404 (Not Found)
The more times i switch betweens the tabs, the more times the ajax
link submits. I have googled it, but not found anything, which makes
me believe this is not a common error in the JQuery UI tabs.
Any idea what I do wrong?
I uses rails 3.05. I've tried different versions of jQuery og jQuery Ui:
class InnmeldingsController < ApplicationController
respond_to :js, :html
def destroy
#innmelding = Innmelding.find(params[:id])
#innmelding.destroy
#innmeldings = Innmelding.all
respond_with( #innmeldings, :layout => !request.xhr? )
end
def list
#innmeldings = Innmelding.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #innmeldings }
format.js
end
end
list.html.erb:
<td><%= link_to 'Destroy', innmelding, :remote => true, :id => "reload", :method => :delete %></td>
application.js:
$(document).ready(function(){
$( "#nav" ).tabs();
});
You should check you're not binding events (e.g. clicks) multiple times. This would occur when you load the same JavaScript files multiple times as you load the tab content via AJAX without caching the content (i.e. with the option cache: false, which is default).
Found solution (thanks to William who got me on the track). By default Rails loads the js files by ajax calls. Solution: Hiding the js files in application.html.erb from other then needed controllers.
In my controller simply:
def index
#vis_js = 1
end
and application.html.erb:
<% if defined?(#vis_js)%>
<%= javascript_include_tag 'event_calendar', :cache => true %>
<%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js", "jquery.validate.js", "jquery.ui.datepicker-no", :cache => true %>
<%= javascript_include_tag 'rails', :cache => true %>
<%= javascript_include_tag 'application', :cache => true %>
<% end %>

link_to delete url is not working

I have the following link_to delete url in my app
<%=link_to "Delete",blog_path(#blog.id), :method => :delete, :class => "delete", :confirm => "Are you sure ?"%>
It does not seem to be working.When I click this url, it just takes me to the show path.Can someone please tell me how to fix this. Thanks.
Are you using jQuery? If so, I think the problem could be that you are using jQuery without the updated rails.js file.
Download rails.js here:
https://github.com/rails/jquery-ujs/raw/master/src/rails.js
Drop it in your javascripts directory, overwriting the rails.js that comes default with rails.
Add a javascript include line to include it.
<%= javascript_include_tag "rails" %>
Put this after your Jquery include tag. You probably also want to disinclude the javascript defaults if you don't plan on using prototype.
I included jQuery UI in my application, I found that delete is now working as show, but after doing above Resolved Issue.
Make sure these lines appear in application.js :
//= require jquery
//= require jquery_ujs
Ensure that you have java script turned on. Otherwise :method => :delete acts just as show in Rails.
If you're using restful routing for blogs, then the following should work:
<%= link_to "Delete", #blog, :method => :delete, :confirm => "Are you sure ?"%>
You can try with 'data-method' instead of :method.
<%=link_to "Delete",blog_path(#blog.id), 'data-method' => :delete, :class => "delete", :confirm => "Are you sure ?"%>
You can check on jquery_ujs.js the following piece of code:
// Handles "data-method" on links such as:
// Delete
In order for link_to to work with the delete method, Rails needs the unobtrusive scripting adapter for jQuery.
Make sure that your Gemfile has
gem 'jquery-rails'
Make sure that app/assets/javascripts/application.js has
//= require jquery
//= require jquery_ujs
Make sure that your app/views/layouts/application.html.erb has
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
inside the head tag. Remove the 'data-turbolinks-track' => true section if you don't plan to use Turbolinks.
you should use
<%=button_to "Delete",blog_path(#blog.id), :method => :delete, :class => "delete", :confirm => "Are you sure ?"%>
It's possible to have a working link_to without jQuery
I've found the best process to make a working delete link for ruby on rails without jQuery! Here I already make an answer: https://stackoverflow.com/a/67710994/14387700
But for making this easy, I'm writing this here again.
We need to work with 3 things:
Adding destroy method in articles_controller.rb
routes.rb setup
LINK_TO tag
Let's Start...
Adding destroy method in articles_controller.rb
At first, we will add def destroy ... end in articles_controller.rb,
lets open:
# app/controllers/articles_controller.rb
def destroy
#article = Article.find(params[:id])
#article.destroy
params[:id] = nil
flash[:notice] = "Art has been deleted"
redirect_to :action => :index
end
Here
in the 1st line, we're calling a variable '#article' which will find and select the ID parameters of the article on rails console from our database. Then,
in 2nd line, the #article variable will make the destroy command in the console. then,
in 3rd line: the id params will be deleted and
in 4th line, a notice will flash in application page "Art has been deleted" and also will show in console that, found nothing in the database.
In 5th line, after the destroying process completed, we will be redirected to the article index page.
This is the main factor which will give the destroying command. and make the link_to working.
Setup routes.rb
BUT WAIT
We need 2 routes for the destroy page which are:
A GET protocol setup
A DELETE protocol setup
In routes just add:
resources :articles, except: [:destroy] # this will add all get request links automatically except destroy link
post '/articles/new' => 'articles#create'
post '/articles/:id' => 'articles#update'
post '/articles/:id/edit' => 'articles#update' # this 3 lines are needed for other forms purpose
# we need this 2 lines for our delete link_to setup
delete 'articles/:id/delete' => 'articles#destroy', as: 'articles_delete'
get '/articles/:id/delete' => 'articles#destroy'
Here
The 2nd last line is declaring the DELETE method,
'articles/:id/delete' will be the link structure in post link tag (known as: anchor tag in HTML) for every single post,
'=>' is pointing the link structure to the controller tag which is 'articles#destroy',
then we defined the path text by setting ** as: 'articles_delete'** which we will use as:
'articles_delete_path' or 'articles_delete_url' in link_to tag.
Then
in last line, we defined the get request for the delete link which will give us a working link like "https://2haas.com/articles/1/delete" except "/articles/1/destroy" that means we can customize our delete link from this 2 methods setup with more additional information..
Last sweetest delete output
The desired link_to tag
we can use this to get proper delete link_to tag which will work.
<%= link_to 'Delete Article', articles_delete_path, method: :delete %>
<%= link_to 'Delete Article', articles_delete_url, method: :delete %>
<% obj.each do |post| %>
<%= link_to 'Delete Article', articles_delete_path(post), method: :delete %>
<% end %>
AND that's done except jQuery
Thanks for reading this answer properly.!
HAPPY PROGRAMMINGS

Ruby On Rails 3 submit form AJAX update results in div

I am stuck; I did a search and I can't find a pointer on how to get this project to work. I have a form on my index.html.erb as:
<html> <head>
<title>Ajax List Demo</title> <h1>Listing posts</h1>
<%= javascript_include_tag "prototype" %> </head> <body>
<h3>Add to list using Ajax</h3>
<% form_tag ( :remote=>true, :update => 'my_list', :action => :list , :method=>:post, :format =>:xml ) do %>
Enter the url:
<%= text_field_tag 'url' ,'', :size => 80 %>
<%= submit_tag "Find" %>
<% end %>
<div id="my_list"><%= render :partial => 'profiles/list' %></div> </body> </html>
Now I have a div with this called my_list. When I submit the form I want my partial _list.html.erb (inside profiles dir, tried home dir too) to update with the results of list.
My home controller has this method:
def list
puts "here!!!!"
reader = Reader.new
#profiles = reader.processURL(params[:url])
render :partial=>'profiles/list', :locals => { :profiles => #profiles}
end
I end up getting this error:
ActionView::MissingTemplate (Missing partial profiles/list with {:locale=>[:en, :en], :handlers=>[:rjs, :builder, :rhtml, :rxml, :
erb], :formats=>[:xml]} in view paths "C:/Users/....tree/app/views"):
app/controllers/home_controller.rb:22:in `list'
Rendered C:/Ruby187/lib/ruby/gems/1.8/gems/actionpack-3.0.0/lib/action_dispatch/middleware/templates/rescues/missing_template.erb
within rescues/layout (1.0ms)
Could anyone help me or send me in the right direction to understand how to update a div rendering via Rails on form submit? Thanks again.
First of all I am getting ajax to render(#homepages) in index.html.erb via index.js.erb OK, but my search to update #homepages is not working.
In your javascript_include_tag you missed out rails.js which I think handles the ajax request. javascript_include_tag :defaults would have done all that for you plus some others that you do not need. Providing you are not using jquery you need prototype and rails.js as a minimum.
I do not think the format of this form_tag is correct:
<% form_tag (:remote=>true, :update => 'my_list', :action => :list , :method=>:post, :format =>:xml) do %>
The first value after the "(" should be the item_path, then the conditions :action => :list.
:method => post should take you to the create or new action.
:update => 'my_list' would be done in the list.js.erb using javascript (prototype)
The code for jquery and prototype is similar, but slightly different (see Railscast 205)
Why format xml in the form_tag, put it in the controller "list" mine is:
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #homepages }
format.js
end
Don't sure if you can get away with 'url' should not it be :url you might be able to use either.
When I was getting the missing template it was because it was looking for a search.html.erb file. In your case it is looking for a list.html.erb.

Resources