I've successfully added ujs in one rails (3.2.6) app. Adding the :remote => true to my form tag allows me to make ajax calls to my js.erb files for dynamic loading of divs, ect..
But in another application on the same machine (Ubuntu 12.0.4), is seems the ujs engine is not working. I'm always getting a Template not Found because the form is sending format => html rather than js. If I force the form to use js format (format => 'js'), it then just renders the js.erb file, rather than calling it via ajax.
In the application.js, I've included the proper headers with the following:
//= require jquery
//= require jquery_ujs
//= require_tree .
The javascript files are included when I actually browse to the primary home page which is using the application layout, which includes the above mentioned javascirpt references. The form in the page is as follows:
<%= form_tag list_path, :remote => true, :id => 'frmBookResults', :method => :post do %>
But although it contains :remote => true, and there's a route established for list_path (the route works, because if I change the list.js.erb to list.html.erb, the view renders), and a method in the controller to handle the request (def list....end), the subsequent list.js.erb is ignored and I get a template not found error, because rails is processing the form request as html, which I can confirm in the log.
I've searched everywhere I could for a solution, but can't figure out why my ujs isn't working for this particular app, when it is nearly identical to my working app, gemset, versions, and configuration.
I've found a couple of other articles on stack overflow where people had the same problem, but no final, working answer was given.
Any help or direction would be greatly appreciated.
It was indeed an issue with the ajax being broken. The onkeyup trigger I was using to submit the form was as follows:
<%= form_tag list_path, :id => 'frmBookResults', :remote => true do %>
<input id='keyword' type='text' onkeyup='document.forms["frmBookResults"].submit();'/>
<% end %>
Note the following:
document.forms["frmBookResults"].submit();
Apparently, submitting the form via javascript was the issue, because when I updated the onkeyup to use a jquery submit as described below, rails ujs kicked in and the ajax calls to my list.js.erb worked:
onkeyup="jQuery('#frmBookResults').submit()"
Thanks for all the feedback mccanff! Your contribution along with other developers from the rails group at linkedIn helped me finally solve my issue.
Related
A rails 4 app. A simple question: why does this genereate a GET request?
<%= link_to("fdsfds", some_delete_path, method: :delete, data: { confirm: "Are you sure fdsfds?" }) %>
routes:
delete '/some-path/some-path123' => 'controller123#method123', as :some_delete
All query libraries are included properly.
html:
<a data-confirm="Are you sure?" rel="nofollow" data-method="delete" href="/fdsfdsfds">dsfdsfds</a>
error:
No route matches [GET] "/fdsfdsfdss"
Your code is good, but your javascript include is probably not. Check that your application.js is including the correct libraries. What you may be missing is 'jquery_ujs' which is what handles confirmation dialogs and non-Get requests.
Here's mine with query.
//= require jquery
//= require jquery_ujs
//= require_tree .
Without the javascript library, your link will be a GET request.
I realize this isn't an answer, but instead a "how do I go about debugging this?"
What does your inspector show? Does it show the request as a DELETE? If no, continue.
Add this to the very bottom of your routes path, update the link_to, and check your inspector if it sends a DELETE request?
controller:
def d
abort
end
routes:
match '/d' => 'posts#d', :via => [:delete]
view:
<%= link_to 'delete', '/d', :method => :delete %>
There may be some conflicting route, which while highly unlikely, there are a lot of moving parts which sometimes cause finicky errors.
If that doesn't answer your question, can you post your routes and view, and perhaps a screenshot of your inspector?
If anyone comes here that uses the bootstrap (v4) gem and always ignored the tether warning in development: You actually need to add the tether gem as advised.
That error stops executing the current js file. If all js files are seperate (as they are in development) this doesn't stop the data-method js part getting executed. In production all js is concat into a single file and thus it won't execute the rest of the file which likely contains the data-method code.
New to rails. Was working on chapter 2 of railsTutorial.
I was pair programming with someone who only uses text based browser w3m. So once we created user resource, we created a new user and tried deleting it but couldn't. I could do it on my Chrome browser though, so thought this may be issue with JS or so.
How do we resolve this?
Rails relies on javascript for links to http DELETE actions.
link_to "Delete Thing", thing_path(#thing), method: :delete
Generates a link with a data-method attribute. The Rails UJS driver then catches the click and turns it into into an AJAX HTTP DELETE request.
method: symbol of HTTP verb - This modifier will dynamically create an
HTML form and immediately submit the form for processing using the
HTTP verb specified. Useful for having links perform a POST operation
in dangerous actions like deleting a record (which search bots can
follow while spidering your site). Supported verbs are :post, :delete,
:patch, and :put. Note that if the user has JavaScript disabled, the
request will fall back to using GET. If href: '#' is used and the user
has JavaScript disabled clicking the link will have no effect. If you
are relying on the POST behavior, you should check for it in your
controller's action by using the request object's methods for post?,
delete?, patch?, or put?.
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to
Added:
The whole reason we do this is that Rails is built around restful interfaces using the full range of HTTP methods; GET, POST, DELETE, PUT, PATCH. But some browsers can only send GET & POST requests and HTML does not define links which perform other actions than GET.
If no javascript is a requirement you can create a form to send requests other than GET:
<%= form_for #thing, method: :delete do |f| %>
<%= f.submit 'Delete thing' %>
<% end %>
Note that this form uses method="post" for compatability. Rails adds a special hidden input to the resulting form:
<input name="_method" type="hidden" value="delete" />
Which Rails uses to fake the extended set of HTTP methods (DELETE, PUT, PATCH, etc).
If you don't want to use Turbolinks with your Rails(4) application, it's easy! Just do this:
Remove the gem 'turbolinks' line from your Gemfile
Remove the //=require turbolinks from your app/assets/javascripts/application.js
Remove the two "data-turbolinks-track" => true hash key/value pairs
from your app/views/layouts/application.html.erb
I'm attempting to create a button for a form that allows the user to save the entered data without redirecting/reloading or anything.
I've added a button_to to my form partial as follows:
<%= button_to "Update", incorporation_path(#incorporation), method: :post, remote: true %>
This does indeed save the data but submits the form with redirect and all.
Upon adding a render :nothing => true to the update controller method, I was simply confronted by a blank page when I clicked the button. This is particularly surprising because I'd figured that the remote: true line would prevent this.
What might be up?
Any thoughts are appreciated
Update
You are talking about a form! Have you set the remote: true on form_for? Because that's how you submit a form asynchronously.
Original answer
remote: true is a part of Unobtrusive scripting adapter for jQuery. As the name implies this approach is unobtrusice and will not work if JS is deactivated or the library is not loaded. So make sure that you have the following lines in your script file:
//= require jquery
//= require jquery_ujs
I have a search page in my app, where there is an ajax search form. The search form works properly, passing parameters to the model to filter the search, and the model returning a collection of results. Upon search submit, #results are rendered on the page. Each #result then has a link to an action on it, like:
<%=link_to "Message", message_user_path(:id => user.id), :remote => true%>
Where this action in the controller is:
respond_to :js, :html
def message
#user_id = params[:id]
#user = User.find_by_id(#user_id)
respond_to do |format|
format.html
format.js
end
end
and this responds with message.js.erb, which triggers a messaging panel to pop up with a message to the user. All of this is working correctly, checking the log I see the correct get request sent, and the correct format being processed:
Started GET "/users/3/message"
Processing by UsersController#message as JS
However, if I refresh the page and try to click the same link that was working before, I get the error Template is Missing. Checking the log, I see that now there are two requests sent, first an html then the same js request.
Started GET "/users/4/message"
Processing by StudentsController#message as HTML
...
Completed 406 Not Acceptable in 3ms (ActiveRecord: 1.0ms)
Started GET "/users/4/message"
Processing by StudentsController#message as JS
The html request throws the missing template error. Does anyone know why refreshing the page causes rails to attempt to respond with an html request to a remote link?
EDIT: routes.rb
resources :students do
member do
get 'message'
end
end
Does your app/assets/javascripts/application.js contain
//= require jquery
//= require jquery_ujs
?
And your erb contains <%= javascript_include_tag "application" %>?
I was just struggling with a problem like this for HOURS and the last of those two points fixed it; I saw the first point mentioned in some other questions so I'll repeat it here.
Hope that helps.
(Credit where credit's due)
What solver it for me was adding :format => "js"
So in your case:
<%=link_to "Message", message_user_path(:id => user.id, :format => "js"), :remote => true %>
In general, when you use link_to on a particular button or so, when you press the button, as js request is send to the controller, but also searches for the respective .js.erb file and so on.
My solution was to replace
format.json do
with
format.js do
you can troubleshoot the request by setting a breakpoint (i use pry) in the controller and then look at the variable
request.format
For newer versions of Rails, this should be fixed where using remote: true within the link_to code, as the original poster was doing, will only look for a .js format to respond with. As others have said, if you never need an html response, then you can remove that from your code all together; you won't even need a respond_to, respond_with, etc as Rails will auto respond with JS looking for the template you already have made. So your controller code would look like this:
def message
#user_id = params[:id]
#user = User.find_by_id(#user_id)
end
And the link would still be this:
<%=link_to "Message", message_user_path(:id => user.id), :remote => true %>
Or this would work as well (my preferred way of syntax):
<%=link_to "Message", message_user_path(id: user.id), remote: true %>
This code will call the controller action which will look for the template message.js.erb.
I know this question is old now, but for anyone looking for answers and using current Rails 6+ (I'm using 7.0.0alpha), and if you are getting this same type of issue where both HTML and JS templates are being requested; check that turbolinks is not what is causing the issue. Sometimes turbolinks can cause a request to be sent twice and it may be sending the first request as an HTML request.
My form with remote: true was inside another form and I didn't know it.
So make sure it isn't inside another form.
I made this link in order to destroy a comment :
<%= link_to 'Destroy Comment', [comment.post, comment],
:confirm => 'Are you sure?', :method => :delete %>
this suppose to send to the destroy action in the comments_controller.
the problem is that it searches for the 'show' action, Instead of the 'destroy' action :
Unknown action
The action 'show' could not be found for CommentsController
Do you think you know why it does that?
Thanks,
Oded
edit: problem solved I used 'button_to'
Rails 3:
When you use JQuery, make sure you have the right rails.js file (https://github.com/rails/jquery-ujs). When you use Prototype, the correct rails.js file is already installed. Also, make sure the following is added in your layout head:
<%= csrf_meta_tag %>
And also make sure that both the JS framework and the rails.js file is being loaded.
<%= javascript_include_tag "jquery", "rails" %>
# or
<%= javascript_include_tag "prototype", "rails" %>
Just a side-note - You can also point to the Googleapis link: http://scriptsrc.net/.
When you use :method => :delete inside a link, the following HTML will be created:
Click me!
As you see, the HTML5 data- attribute is being used. The rails.js file automaitcally puts click events on links with these attributes. When data-method="delete" is set, the request will be done with the DELETE HTTP method. So clicking it will destroy the comment. Also, setting :confirm will create a data-confirm attribute which does what you would expect.
Rails 2:
When you use Prototype, the :method => :delete thing will work automatically. Just make sure you include the right Javascript files:
<%= javascript_include_tag :defaults %>
When using JQuery you should install the 'jrails' plugin (https://github.com/aaronchi/jrails). It allows you to use the same Prototype helpers for JQuery. The plugin uses an old version of JQuery, so make sure you update that one.
I don't know for sure if the :method attribute uses Prototype in Rails 2 or just regular Javascript. So it could be that you don't even need Prototype or JQuery for the :method attribute in Rails 2.
As I said in the comment: I never use button_to for DELETE links. You can just as easily get it working with link_to. And as far as I know it's the helper most people use when creating these kind of links. Hope it helps. :)
ERROR: ActionController::RoutingError (No route matches [GET] "/javascripts/jquery.js")
Solution, download: http://code.jquery.com/jquery-1.6.3.js
ERROR: AbstractController::ActionNotFound (The action 'show' could not be found for CommentsController)
Solution, download: https://github.com/rails/jquery-ujs/raw/master/src/rails.js
In rails 3.1.0 save the above js files to app/public/javascripts/
Rename or remove your existing js files.
I've just solved this problem in my own App (rails 3). I followed the steps for rails 3 and, the most important issue, installed the correct rails.js file in my public/javascripts folder. It didn't work until I've installed rails.js.
The one i chose is this:
https://raw.github.com/rails/jquery-ujs/master/src/rails.js
I just came across this same issue with Rails 3. I'm using jQuery with the updated rails.js file. What fixed it for me was something simple - use :method => :delete, not :method => :destroy.
=link_to( 'delete account', user_admin_path(current_user.id), :confirm => "Deleting your account is irreversible!! Are you sure you wish to continue?", :method => :delete )
And in the header I have:
= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js", "jquery.colorbox-min", "jquery.validate.min", "rails"
Works like a charm :)
Make sure you reference //= require jquery and //= require jquery_ujs (in that order) in your application.js file, in \app\assets\javascripts.