Using Rails Destroy Method without sending an http DELETE request? - ruby-on-rails

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 %>

Related

Pass data safely from view to controller in rails

I want to pass data from a view (link) to a controller so it can look up the related information. Services for a company, in this case.
I see examples where people have added to params like this:
<div>
<%= link_to 'Services', :controller => 'company', :action => 'services', :company_id => #company.id %>
</div>
...but that results in a transparent (unsafe) URL like this:
http://localhost:5000/company/services?company_id=17
Is there a way to get around this without stuffing data into the Session? What's the best practice on links inside an app that requires authentication?
THere is no such major harm in passing data like this in View.
Still if you insist on having, then check prettyurls:
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
Prior to we must have valid checks in controller & model files.
1. Valid Checks and redirection in Controller is helpful.
2. Depending on need adding validations in model can be a good support.
<%= link_to "Sign in", new_session_path(:id => Base64.encode64("1")) %>
and in your controller
def new
id=Base64.decode64(params[:id].to_s)
end
this is another form for create a link with data
check your routes with command un console rake routes
for more information read this documention
http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to

Invalid route name for GET and POST

I'm working through an older tutorial that was done for Rails 3. I'm using Rails 4.1.4.
One of the instructions is to change the routes file to include the following:
get '/boards/:board_id/conversations/:id/reply' => "conversations#reply", :as => :reply_board_conversation
post '/boards/:board_id/conversations/:id/reply' => "conversations#save_reply", :as => :reply_board_conversation
Obviously that gives me an error:
Invalid route name, already in use: 'reply_board_conversation'
It seems to me that the route is somehow trying to replicate the behaviour of a new and create action. Get for new and Post for create with a single route.
The problem is I can't figure out how to rewrite the route so it works. I've googled for solutions but can't seem to find anything. If anyone could point me in the right direction it would be hugely appreciated.
It looks like the only issue is with the duplicated "named route" name reply_board_conversation. So you could simply change one. I'd probably rename the save version to save_reply_board_conversation. Then it should work. Just remember to refer to the route this way in the future. This would primarily be used in a form tag. So, for exmaple:
<= form_tag :url => save_reply_board_conversation_path do %>
Note the use of save_reply_board_conversation_path instead of reply_board_conversation_path given that the form would be submitting a POST request instead of a GET request.
The names for these routes should be different although since the composition of the URL is the same so you really only need a name for the first one.
The trick with named routes is they generate the URL only, they do not set the HTTP request method. That has to be done independently.
That means you can call the same named route two different ways:
<%= link_to('View', board_path(#board)) %>
<%= link_to('Delete', board_path(#board), method: :delete) %>
These actually render as the same URL but one will hit the GET route, the other the DELETE one.

Passing id in form_for action

I have a form to update an attribute of a model - I don't want it to go to the standard update action I want it to go to a different action.
<% for car in #cars %>
<%= form_for car, :url => { :action => "custom_action/#{car.id}" } do |f| -%>
This is giving the following error -
No route matches {:action=>"custom_action/1", :controller=>"cars"}
However if I visit the url - custom_action/1 - I don't get the routing error.
Any idea why I can't do this?
In addition to what Frederick Cheung said about GET vs POST vs PUT, I think your code might be wrong in general.
To do exactly what you want, try:
form_for car, :url => {:action => "custom_action", :id => car, :controller => "cars"} do |f|
I don't think this is a good idea, and will probably cause you pain. I suggest taking a look at the Ruby on Rails Routing Guide, to understand how to do this properly. (Routing is a topic where I always have to consult the manual.)
With correct routes your code should look something like this:
form_for car, custom_action_car_path(car) do |f|
Which will be easier to change in the future if/when you refactor your app.
If you go to the url by typing it into the url bar, you're making a GET request, whereas forms emit POST requests by default, and in this case would probably emit a PUT request (since you're acting on an existing record).
It sounds like your route is only routing GET requests. Given that you say your custom action does update the record, it sounds like you should update your routes to accept PUT requests instead.

renaming routes (map, link_to, to_param) in rails

I'm having a little issue...I setup a rails application that is to serve a german website. To make use of Rails' internal pluralization features, I kept all my models in english (e.g. the model "JobDescription").
Now, if I call "http://mysite.com/job_descriptions/", I get all my job_descriptions....so far, so good. Because I didn't want the english term "job_descriptions" in my url, I put the following into my routes.rb
map.german_term '/german_term', :controller => 'job_descriptions', :action => 'index'
map.german_term '/german_term/:id', :controller => 'job_descriptions', :action => 'show'
If I call "http://mysite.com/german_term/" or "http://mysite.com/german_term/283" I get all my job_descriptions, which is fine.
However, to make the URL more SEO friendly, I'd like to exchange the id for a more userfriendly slug in the URL. Thus, I put the following in my job_description.rb:
def to_param
"#{id}-#{name.gsub(/[^a-z0-9]+/i, '-')}"
end
which, whenever I use "job_description_path" in any link_to method, renders my URLs out to something like "http://mysite/job_descriptions/13-my-job-description-title".
However, and this is where I'm stuck, I'd like to get "http://mysite/german_term/13-my-job-description-title". I already tried to exchange the "job_description_path" with "german_term_path" in the link_to code, but that only generates "http://mysite/german_term/13". Obviously, to_param isn't called.
One workaround I found is to build the link with:
<%= link_to job_description.name, german_term_path(job_description.to_param) %>
But that's rather tedious to change all the link_to calls in my code. What I want is to replace "job_description" by "german_term" whenever it occurs in a URL.
Any thoughts?!?
Regards,
Sebastian
I think you're going to need to use the restful route helpers to get what you want.
In that case, it wouldn't take much re-factoring (assuming you've mapped JobDescriptions as a resource). Leave your to_param as is and change your JobDescriptions route to something like the following:
map.resources :job_descriptions, :as => 'german_term'
Hope this helps!
Rails only utilizes the
def to_params
end
URL builder when you are using a restful route/link helper. The only way I am aware of is to do it similar to how you did, unless you are willing to just scrap your english language links and do it all in German. In that case, just get rid of the named route lines and change the to_params to use the correct name field from the database. At that point, the REST routes should behave correctly.

Performing AJAX delete operations restfully in rails

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

Resources