Why does Rails delete method get routed to GET instead of DELETE? - ruby-on-rails

I am getting, the following routing error, i am not sure why it is not routing to DELETE and goes to GET
No route matches [GET] "/signout"
html.erb:
<%= link_to "Sign out", signout_path, method: "delete" %>
routes.rb:
match '/signout', to: 'sessions#destroy', via: :delete
What command am i missing?

You want to ensure you have the jquery_ujs file loaded as part of your application.js manifest. I believe in older versions of Rails it is known as rails_ujs.
application.js
// ...
//= require jquery_ujs
// ...

Check if you load jquery-ujs and allow javascript in your browser.
<%= link_to "link", some_path, method: "delete" %>
will generate
link
As soon as you click the link, jquery-ujs will cancel the action and make a delete request, taken from the data-method attribute:
from link_to:
: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 and :put. Note that if the user has JavaScript disabled, the request will fall back to using GET.

Related

Link_to generates a GET in Rails 4

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.

Is it possible to disable JS in RoR project?

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

No route matches POST confusion

I am very unfamiliar with routing and the entire back-end of Rails in general. I am attempting to have a click on "edit cart" lead to the edit page, I have the edit_cart_path and corresponding view- but when I click the edit cart button, I get
Routing Error
No route matches [POST] "/carts/21/edit"
I have resources :carts in routes.rb, I have get "/carts/:id/edit" => "carts#edit" as well. Have tried a couple other methods including "via: get". Why is it insisting on POST, and how to solve this?
I'm guessing you're doing something like this, in your view:
button_to(edit_cart_path(#cart))
When using a button_to helper, the default HTTP method will be POST.
You'll have to do explicitly define the HTTP method you want to execute:
button_to(edit_cart_path(#cart), method: :get)
I would encourage you to use the link_to helper instead, and add any button effect using CSS:
link_to(edit_cart_path(#cart), class: 'btn')
From the Rails 4 documentation:
button_to(name, options = {}, html_options = {})
The options hash accepts the same options as url_for.
There are a few special html_options:
:method - Symbol of HTTP verb. Supported verbs are :post, :get,
:delete and :put. By default it will be :post.

ruby on rails - link_to() problem

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.

sense of RESTful requests

I have a ruby-on-rails application and I'm now wondering why RoR uses Restful Requests:
eg. if you want delete an ressource it's a best practice to do it with such an HTTP Request:
DELETE /entry/13
you can also do it with with such an normal request:
GET /entry/delete/13 or GET /entry/13/delete
now my question:
when i make a link to such an restful delete operation with the link_to helper
link_to :controller =>:delete, :id => id, :method => :delete
it results in some cryptic javascript:
Delete
So whats the idea behind it?
In my opinion you just exclude non-javascript users.
All versions of Rails < 3 use very obtrusive javascript (and the result is pretty ugly, as you've demonstrated).
The doc suggests the method will fall-back to using GET if javascript is disabled:
: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 and :put.
Note that if the user has JavaScript
disabled, the request will fall back
to using GET. 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? or put?.
Either way, I would suggest you create the "destroy" links like so:
# when you have an "entry" object
link_to "Destroy", entry, :method => :delete
# when you only have an "entry" object's id
link_to "Destroy", entry_path(:id => id), :method => :delete

Resources