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
Related
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.
I need make system call from method of Ruby of Rails , but I want it to stay on the same page.
Right now for some reason it does not execute , but shows :
Routing Error
No route matches [POST] "/devices/22918"
Try running rake routes for more information on available routes.
This is the button:
<%= link_to image_tag("/images/glossy_green_button.png"), device , :method => :turnon, :confirm => "Are you sure?" %>
This is method:
def turnon
#device = Device.find(params[:id])
result = `/perl/toggle.pl #device.infodot on`
end
please let me know what I am doing wrong,
thank you
D
You're simply not using the method correctly. You're using it to target the action of the controller you want to execute (note that I explicitly said action and not method for clarity).
Available actions in a controller are defined by your routes.rb file.You should eventually read or re read that
In your case, let's say you have a resource device (I guess this is what you have), you'll first create a new action in your routes.rb file
resources :devices do
put :turnon, on: :member
end
You can read doc about this syntax here but basically I'm making the action turnon available via the HTTP PUT method on each devices, meaning that it will be accessible through the URL /devices/1/turnon or via the url_helper : turnon_device_path (or turnon_device_url)
I assume that your turnon action will modify existing things, not creating new things, that's why I'm using the PUT verb
Then the link will look something like :
<%= link_to image_tag("/images/glossy_green_button.png"), turnon_device_path(device) , :method => :put, :confirm => "Are you sure?" %>
see that the method is the HTTP method corresponding to the new route I created.
I also assume that you put the turnon method in the DevicesController.
Finally as you want to do that in ajax, you can have a look a the remote: true option
For my Website model, my current method of letting users destroy an instance of that model is putting this on an html page:
<%= link_to "delete", website, :method => :delete %>
However, this would have to send a DELETE request to /websites/:id(.:format) in order to use the destroy method. I can't do that because the id's of my Websites are strings such as http://example.com, meaning localhost:3000/websites/http://example.com just doesn't make sense.
So what I'm wondering is, is there another way to delete instances of my Websites model, other than sending an http DELETE request? I wish I could access the destroy method directly.
Any help is greatly appreciated.
Why don't you have the primary key id's of the websites as integers, and then have a "url" string attribute that can be the http://example.com name.
This will make many things easier, notably associations. Also, you can still search for things based on the url, and you aren't really limited by making the url a column and an id # as the primary key.
I'm not really sure to understand your problem but have you take a look to friendly_id ?
Thanks to this gem, you will be able to create url with string instead of basic sql primary ids.
you can access public methods by adding new route to your routes.rb.
for example:
routes.rb
post '/websites/:id' => 'websites#destroy', :as => :destroy_website
view
<%= link_to "destroy", destroy_website_path(:id => "http://example.com"), :method => :post %>
I am using rails3 and I have a user model. This model has a status column. I am showing admin following table
Mary approve reject
John approve reject
Both approve and reject are links. Since clicking on approve will approve user's record it should not be a get request. It should be a post request. I was thinking to achieve a post request I should make clicking on approve or reject an ajax call.
In the ajax call I would make post call instead of get.
Is this a good strategy? Anyone has any better suggestion.
Thanks
Just pass :method => 'post' to your link_to call:
<%= link_to 'approve', approve_user_path(user), :method => 'post' %>
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to
You're right, it shouldn't be a get request. Actually, I think it's neither a post request, because you already have the record and want to change it.
You could just pass :method => :put to link_to. Rails will make a JS handler and when the link is clicked, it will create an invisible form with action=PUT and submit it.
BUT, AJAX is a nice thing too and it's just as hard as setting the method: :remote => true
HTTP POST is used for create, and HTTP PUT is used for update. As such, you should be using doing a PUT (add :method => 'put' to your link_to) since you are updating the user record. Here's more details: http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
How do you perform delete and put operations restfully in rails? I have read the documentation and thought I was doing everything properly, but I can't seem to get it to work.
For example, if I wanted to delete an employee I would create a controller called "EmployeesController" and create a destroy method to perform the delete.
Then I went into the routes.rb file and entered map.resources :employees, which gives you access to the URL helper functions.
In whatever I want to call the Ajax operation from, I should just have a line like:
<%= link_to_remote "Delete", employee_path(#employee), :method => :delete %>
When I click on the link, it is still is sending a POST operation, so it does nothing.
What am I missing or doing wrong?
Try
:url => employee_url(#employee)
IIRC, *_path is a named route generated by the :resource directive which includes the method, thus overwriting your :method => :delete
From my code:
<%= link_to_remote "Delete", :url => post_url(post), :method => :delete %>
Just to add a few extra details: Using :url => employee_url(#employee) helped (from the accepted answer). The other part that was messing me up was the fact that I was expecting an HTTP delete request, but I kept getting POST requests with a parameter "_method" (automatically added by rails) which was set to delete.
So it was calling the proper destroy action, which I proved by adding a couple of debug statements to the controller. Yes, my delete code was wrong in the controller, so it wasn't really deleting when I thought it was.
If your problem is not having AJAX request you have to add proper javascript tags