Why is my RoR link pointing to the wrong controller action? - ruby-on-rails

I have the following in my projects_controller.rb:
def destroy
#project = Project.find_by_slug(params[:id])
#project.destroy
redirect_to projects_url
end
And I have the following in my routes.rb file:
delete "projects/:id", to: "projects#destroy", as: "destroy_project"
I have the following link (inside the show.html.erb file):
<%= link_to destroy_project_path(#project), method: :delete, class: "btn-gradient btn-red" do %>
<span>Delete Project</span>
<% end %>
Upon clicking the button, the page reloads. The show action is called upon clicking the button. I've added console logs in each method, and it is clear that the destroy action is never called.
Can anyone point me in the right direction?

the link_to helper receives 2 different sets of hashes for the options.
The first set is for things like the http method, and the second for the html attributes (class, id and so on)
The way you wrote it, you probably have method=delete in your query params, which is wrong. You have to explicitly enclose the method: :delete within its own options hash:
<%= link_to destroy_project_path(#project), { method: :delete }, class: "btn-gradient btn-red" do %>
<span>Delete Project</span>
<% end %>

If you use rails 7 with turbo framework you can try below for buttons.
<%= button_to "Delete this project", destroy_project_path(#project), method: :delete %>
Or you can try below for links.
<%= link_to destroy_project_path(#project.id) , data: { turbo_method: :delete } do %>
<span>Delete Project</span>
<% end %>

the problem that you are having is with the JS. there is a problem where something is not loading properly.
For testing try to remove your JS and use something like this
<%= javascript_include_tag "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js" %>
When you get the delete method working, then you can debug where in your JS there is a problem.
at this time there is not sufficient info on your question to be able to know what it is.

Related

Rails destroy does not work and forwards to a wrong link

I am totally new to rails and struggle with the easiest stuff. I have the following problem:
When I try to destroy a search (from my model search) it does not work and I get redirected to "/search.48 (the search with id 48). It gives me the notice "We're sorry, but something went wrong." and in the console it says something with POST. Neither the search is deleted nor the redirect_to search_path is working. What am I doing wrong?
This is my controller:
def show
#searches = current_user.searches
end
def destroy
#search = Search.find(params[:id])
#search.destroy
flash[:success] = "Search deleted"
redirect_to search_path
end
This is my view show:
<% #searches.each do |search| %>
<%= search.title %>
<%= search.description %>
<%= button_to "delete", search, method: :destroy %>
My routes.rb:
get 'search' => 'searches#show'
resources :searches
And I also included <%= javascript_include_tag 'application' %> in the application.html.erb as well as //= require jquery and //= require jquery_ujs in the application.js file.
So I really can't find my mistake. Can someone help me?
In your view file, the code for the button should look like:
<%= button_to "delete", search, method: :delete %>
Note the method is :delete, not :destroy. It's a little confusing, because 'delete' is the REST verb, but 'destroy' is the controller action name.
have you tried:
<%= button_to "Delete", { action: "delete", id: search.id },
method: :delete %>
in you view. Also it appears you are redirecting to search_path but I am guessing you want searches_path.
I got it! In my router I wrote get 'search' => 'searches#show' and somehow my controller was confused with the search_path. Since I renamed it to get 'mysearches' => 'searches#show' and mysearches_path it works perfectly

undefined method error with delete statement

For my projects I have the following relevant code
routes:
resources :lists do
resources :items
end
I now included a loop on list/show page in which I want to show the item and provide the users with the possibility to delete the item.
So i got code like this:
<% #items.each do |item|%>
<p>
Item: <%= item.name %>
<%= time_ago_in_words(item.created_at) %> ago.
</p>
<%= link_to "Delete", [#list.item, item], method: :delete %>
<% end %>
But when I try to run it I get the error:
undefined method 'item' for #<List:0x007fba7be6fe28>
While I did define the variables in my controller:
Items-controller:
def destroy
#list = current_user.list
#item = #list.items
end
Could anyone explain whats causing this error?
you have a typo in your controller - it should be #items = #list.items that's why the iteration doesn't work properly.
edit: after formatting your original question, I see that the error was raised on #list object, so you have to fix path to delete action:
<%= link_to "Delete", [#list, item], method: :delete %>
you build the path by providing the parent object (#list) and then the object itself (item) - Rails will translate it to list_item_path.
change your link_to
= link_to("Delete", lists_items_url(#list, #item), method: :delete)
You have defined resources :lists and resources :items.
Basically what you want to do is send a DELETE request to the collection with the IDs to fetch and delete the items.
Run a rake routes to check the exact naming, but I think it's written like that to be sure. Although you don't seem to be needing the IDs based on your controller's action, you still need to supply them for the helper.
You're using #items.each and in your controller have only #item.

rails link_to with block, controller options and html post

I am trying to use link_to in rails 4 with controller and html options and a do..end block. I have seen similar posts but have not been able to use any of the answers successfully.
Working code without a do..end block:
<%= link_to 'recommend', { controller: 'recommendations', id: offer.id }, method: :post %>
When I try to use some embedded ruby to add extra information to the link, I cannot get it to work:
<%= link_to( { controller: 'recommendations', id: offer.id }, method: :post) do %>
<p>Some Html</p><%= offer.recommendations %>
<% end %>
The code compiles but in the rendered, the link that is generated is the following:
<a controller="recommendations" id="38">
<p>Some Html</p>0
</a>
Any help would be appreciated. I think that it is a small problem with the syntax but I have tried all manner of brackets, spaces etc that I could think of without luck.
UPDATE: I have tried the following code without success:
<%= link_to( { controller: 'recommendations', action: 'create', id: offer.id }, method: :post) do %>
<p>Some Html</p><%= offer.recommendations %>
<% end %>
The HTML output is:
<a action="create" controller="recommendations" id="39">
<p>Some Html</p>0
</a>
This might not be important but as a side note, the create action doesn't have a helper function for links. When I run the
rake routes
command I get the following
...
recommendations GET /recommendations(.:format) recommendations#index
POST /recommendations(.:format) recommendations#create
new_recommendation GET /recommendations/new(.:format) recommendations#new
...
In my opinion this isn't a problem but it is a reason why code such as:
link_to create_recommendation_path
won't work. Finally, the intention of the link is to act as a 'like' button. It creates a recommendation and then displays the current page again. Once again, thanks for the help in advance.
The reason link_to create_recommendation_path doesn't work is because there is no named route for create_recommendation_path, only for recommendations_path. You can see the named routes in your routes list (which you have in your post above). The left most column that comes out of routes shows the named routes. Notice that recommendations#create doesn't have an entry in the list.
You could probably get the path you want with
<%= link_to recommendations_path(:offer_id => offer.id), :method => :post do %>
html stuff
<% end %>
This should post to a path that looks like
/recommendations?offer_id=<the offer id>
(except the post data will be in the headers not on the URL)
This will work if the create method going to do something like
Recommendation.create(params)
and the only parameter you need to create a new Recommendation is an offer_id
What I don't understand is why you're trying to POST with a link? Does creating a recommendation only require an offer id?
In your link_to you're only specifying a controller, you need to also specify the action otherwise it doesn't know where to route it to. Either use:
<%= link_to({ controller: 'recommendations', action: 'show', id: offer.id }) do %>
<p>Some Html</p><%= offer.recommendations %>
<% end %>
Or
<%= link_to({ show_recommendations_path(id: offer.id) }) do %>
<p>Some Html</p><%= offer.recommendations %>
<% end %>

Deleting records using forms in rails 3.2

I have two models, users and materials. Users can favourite materials. I have set up the relationships and the code for favouriting works fine but I can't seem to get the code for unfavouriting right. I have the following code for unfavouriting:
Materials Controller (in show action where unfavourite form is)
#favourite = Favmat.where(:user_id => current_user.id, :material_id => #material.id)
Note: I use this code to decide which button to show in the view. Assuming a record exists we get this:
View
<%= form_for #favourite, :method => :delete do |f| %>
<%= f.submit "Unfavourite" %>
<% end %>
The problem seems to be here. Nothing I do seems to get me a working route to the destroy action in the favmats controller. I have tried using a form_tag instead but then I get very odd routes that don't work.
Favmats Controller
def destroy
Favmat.find(params[:id]).destroy
respond_to do |format|
format.html { redirect_to #material }
format.js
end
end
Update
I have also tried using link_to instead of a form. The code is as follows:
<%= link_to "Unfavourite", favmat_path, method: "delete" %>
The weird thing is that the html for this takes the favmat id from the material, not the favmat object. I don't know how to get the favmat object id in there. Nothing seems to work.
Try passing #favourite object instead of favmat_path to link_to:
<%= link_to "Unfavourite", #favourite, method: :delete %>

Delete the last record in a database

I'm trying to delete the last database record but when I press the link, the page just refreshes and I dont get anything :/
Here's my controller:
def delete
#todo_items = Todo.last
#todo_items.delete
end
& here's my view
<h1>Shared Todo App</h1>
<p>All your todos here</p>
<% #todo_items.each do |t| %>
<li><%= t.todo_item %>
<% end %>
<%= link_to 'Delete', todo_item, confirm: 'Are you sure?', method: :delete %>
Any ideas?
First, your action name should be destroy, not delete. A link with method: :delete will by default map to an action named destroy. See this guide for details.
Second, you probably want to redirect somewhere at the end of your destroy action. For example, redirect_to root_path, or whatever is appropriate.
I came across the same error when following the same tutorial
I changed my controller to:
def destroy
#todo_items = Todo.last
#todo_items.destroy
end
and changed the name of my view to destroy.html.erb.
This seems to work for me.
As said before, your action should be called destroy, but that's not hte problem here.
If the page is only refreshing, it means it's not calling the DELETE method, or else you should see an "action not found" error or Rails should run the default destroy method.
Your problem is probably with javascript. Make sure you have it enabled and that on the application.html.erb page you have the following import:
<%= javascript_include_tag :all %>
Or at least, the rails.js file, which is the one that makes the link_to method work when you change the default method:
<%= javascript_include_tag "rails" %>
Controller action should be :destroy
def destroy
#todo_items = Todo.last
#todo_items.delete
end
as Rails has 7 actions, which includes: new, show, edit, index, destroy and update.
Hence request will be for destroy action. So try this, this will work.

Resources