Typically when I am using a delete link it will look something like this
<% #variable_name.each do |block| %>
<%= link_to 'Destroy', block, method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
For the current project, I am unable to use the "block" path for delete. I now need to call a path that is related to block, but not defined in it. I was thinking something like this
<% #variable_name.each do |block| %>
<%= link_to 'Destroy', someother_path, method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
Is it possible to link to a url instead of using a helper method? If so how would I find that url.
Yes, you can use any other urls as long as you defined the routes in routes.rb
in your routes.rb file
resources :variables do
delete :someother, on: :member
end
then you can check the routes.
To check the urls, please run following command line in terminal.
rake routes
or
rake routes | grep variable
and you can do
<% #variable_name.each do |block| %>
<%= link_to 'Destroy', someother_variable_path(Variable.find_by_name(block)), method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
You can pass arguments to the path helper:
someother_path(first_argument: 'whatever')
Also, if you want the full path of the link (including domain host + port), use this:
someother_url(first_argument: 'whatever')
The last option is to write the path as a string, for example:
link_to 'Destroy', "/posts/#{post.id}/destroy" # etc.
But this last option should not be used as it is complicated to maintain.
Related
I'm learning ruby and rails too. I understood how the link_to and deleting items worked with a single resource.
<%= link_to 'Destroy', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %>
And this works since it uses the article_path and uses rails magic where it takes takes article.id although article was passed in and there was a route article with DELETE and it needed the :id
Prefix Verb URI Pattern Controller#Action
article GET /articles/:id(.:format) articles#show
DELETE /articles/:id(.:format) articles#destroy
However after nesting a resource inside it say, comments
To delete a comment it becomes
<%= link_to 'Destroy Comment', [comment.article, comment],
method: :delete, data: { confirm: 'Are you sure?' } %>
Here are the (relevant) routes for the nested resource (note :format is ommitted)
Prefix Verb URI Pattern Controller#Action
article_comment GET /articles/:article_id/comments/:id comments#show
DELETE /articles/:article_id/comments/:id comments#destroy
Controller code
def destroy
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
#comment.destroy
redirect_to article_path(#article)
end
View code
<h3>Comments</h3>
<% #article.comments.each do |comment| %>
<p>
<strong> <%= comment.username %> </strong>: <%= comment.body %>
<!-- link_to goes here -->
</p>
<% end %>
Q1)
Firstly, is there another syntax for deleting a comment i.e another way of doing [comment.article, comment] in the structure of article_comment_path(comment) (like with non-nested resources in the first code block).
Q2)
What does [comment.article, comment] mean/do and how does it translate to the correct route with
DELETE /articles/:article_id/comments/:id comments#destroy
(Rails has a lot of syntactic sugar (I come from a Java background) so as I code I'm trying not to use syntactic sugar until I fully understand it.)
This code is all from section 5.13 (non nested resources) and section 8 (nested resources) of guides.rubyonrails.org.
For Q1) I found an answer which was
The wanted alternative syntax is
article_comment_path(#article.id, comment.id)
So overall
<%= link_to 'Destroy comment', article_comment_path(#article.id, comment.id), method: :delete, data: {confirm: 'Are you sure?'} %>
This answer was helpful
And the reason why you need the id for the article and the comment is that they are required due to the way the DELETE route is structured. #article.id is needed for articles/:article_id/ andcomment.id is needed for comments/:id
I would also like to add article_comment_path(#article.id, comment.id) in the link_to can be replaced with [#article, comment]. However if using this array input approach you cannot specify specifically the id, the whole object must be passed. So you cannot do [#article.id, comment.id] (Although I somewhat understand this array syntax with link_to im yet to get how q2 works).
I am trying to delete a particular "work" from an array of "works" which is embedded in user.
In my work.html.erb file in views:-
<% #works.each do |f| %>
<%= link_to 'Destroy', profiles_destroy_path(f), data: {:confirm => 'Are you sure?'}, :method => :delete %>
<% end %>
And in my controller:-
def destroy
#work = current_user.works.find(params[:id])
#work.destroy
respond_to do |format|
format.html { redirect_to root_url }
end
end
I am getting following error:-
Mongoid::Errors::InvalidFind at /profiles/destroy.56fa4d2f498b5908a002e2e8
P.S. - I am new to rails.
Please check params[:id] is not nil. There's no :id at session start and you get the Mongoid::Errors::InvalidFind exception above.
delete action doesn't have path by default..
<%= link_to 'Destroy', profiles_path(f), data: {confirm: 'Are you sure?'}, method: :delete %>
That will call the destroy action from your controller.
And make sure params[:id] is not nil.
PS: use rails 4 annotation (avoid using rockets (=>))
There may be an error in Juan's answer.
I believe you want:
<%= link_to 'Destroy', profile_path(f), method: :delete, data: {confirm: 'Are you sure?'} %>
Note: the singular "profile_path" instead of "profiles_path"
This is because the destroy action uses the same path as the show action, but uses a DELETE method instead of a GET. (Which you can observe by running "rake routes" in your terminal and comparing the two routes.)
I am writing a rails app for planning school assignments.
I have been experiencing a problem upon clicking the delete button on the web page it just refreshes the page but doesn't delete anything from the page.
Here is my destroy action from assignment_controller along with assignment_params.
def destroy
#assignment = Assignment.find(params[:id])
#assignment.destroy
redirect_to assignments_path
end
private
def assignment_params
params.require(:assignment).permit(:name)
end
And this is my index.html.erb
<h1>Listing of Assignments</h1>
<% #assignment.each do |x| %>
<h2><%= x.name %></h2>
<%= link_to "Delete", assignments_path(#assignment),
method: :delete,
data: { confirm: "Are you sure?" } %>
<% end %>
I'm not sure if the problem is with the route but here is my routes.rb just in case.
Rails.application.routes.draw do
devise_for :users
resources :assignments
root 'home#index'
end
Thank you!
Instead of:
<%= link_to "Delete", assignments_path(#assignment),
method: :delete,
data: { confirm: "Are you sure?" } %>
Try this:
<%= link_to "Delete", assignment_path(x),
method: :delete,
data: { confirm: "Are you sure?" } %>
You must pass the x not #assignment because you have been passed it in a loop. Also, change: assignments_path to assignment_path.
You have to change your link for delete to below
<%= link_to "Delete", x, method: :delete, data: { confirm: "Are you sure?" } %>
Here's the line from my routes config file:
DELETE /posts/:post_id/comments/:id(.:format) posts/comments#destroy
I want to delete a single comment but I can't get the syntax right. Here's what I tried:
<% if current_user == comment.user %>
<span class="edit-delete-line"><p><small><%= link_to "Delete", post_comments_path([#commentable, comment]), method: :delete, data: { confirm: "Are you sure?" } %> </span>
</small></p>
<% end %>
That gives me a routing error. I also tried:
<% if current_user == comment.user %>
<span class="edit-delete-line"><p><small><%= link_to "Delete", post_comments_path(params([:post_id], [:comment_id])), method: :delete, data: { confirm: "Are you sure?" } %> </span>
</small></p>
<% end %>
I got "wrong number of argument" error this time. I know this should be simple, right???
You're trying to delete a single comment, so you need to use post_comment_path(#commentable, comment), not plural post_comments_path, which points at the index. If you have your controller set up to also accept the unnested resource (just /comments/:id), you can just use comment_path directly.
Check out the Rails routing guide for more details.
<%= content_tag :span, link_to("Delete", [#commentable, comment], method: :delete, data: { confirm: "Are you sure?" }), class: "edit-delete-line" if current_user == comment.user %>
This should get it working for you.
To give you a simple synopsis, you have to realize that the Rails routes are basically helper methods which are generated when you define your respective routes.
The route helpers themselves don't do anything except give you a dynamic way to call specific routes. For example, instead of "/posts/<%= #post.id %>", you can call posts_path(#post).
--
The Rails routes work very simply -- they take arguments like any other helper method.
Thus, if you call a route which requires specific values to be passed (for example post_comments_path(post_id, comment_id), you have to pass the respective values to the helper.
Therefore, you can call the following:
post_comments_path(#commentable, comment), method: :delete
... or if you're using link_to, you should be able to pass the respective data objects that you require:
link_to "Destroy", [#commentable, comment], method: :delete
So let's say I have Posts and Comments and the url for show is /posts/1/comments/1. I want to create a link to delete that comment in the comments controller destroy method. How do I do that?
<%= link_to 'Destroy', post_comment_path(#post, comment),
data: {:confirm => 'Are you sure?'}, :method => :delete %>
in comments controller:
def destroy
#post = Post.find(params[:post_id])
#comment = Comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to post_comments_path(#post) }
format.xml { head :ok }
end
end
Since some time ago, the confirm option has to be included in a data hash, otherwise it will be silently ignored:
<%= link_to 'Destroy', post_comment_path(#post, comment),
data: { confirm: 'Are you sure?' }, method: :delete %>
Sometimes when you have <span>, <i> or nested elements inside of a <a> tag this way link_to use is difficult. You can inseted use raw HTML which is easy to handle, like so:
<a class="btn btn-sm" href="/blogs/<%=#blog.id%>" data-method="delete">
<i class="pg-trash"></i><span class="bold">Delete</span>
</a>
Given you have #post variable with your post object
Before Rails 7
<%= link_to 'Delete comment', post_comment_path(#post, comment),
method: :delete, data: {confirm: 'Are you sure?'} %>
Rails 7 (with Turbo, out of the box)
<%= link_to 'Delete comment', post_comment_path(#post, comment),
data: {turbo_method: :delete, turbo_confirm: 'Are you sure?'} %>
In rails 7.0.4.2
You can use destroy method this way 'turbo gem'
<%= link_to 'Delete', user, data: {turbo_method: :delete, turbo_confirm: 'Are you sure?'} %>
Turbo gives you the speed of a single-page web application without having to write any JavaScript. Turbo accelerates links and form submissions without requiring you to change your server-side generated HTML. It lets you carve up a page into independent frames, which can be lazy-loaded and operate as independent components. And finally, helps you make partial page updates using just HTML and a set of CRUD-like container tags. These three techniques reduce the amount of custom JavaScript that many web applications need to write by an order of magnitude. You can install 'turbo' in terminal by:
gem install turbo-rails -v 1.0.1
Or in Gemfile and bundled it.
gem 'turbo-rails', '~> 1.0', '>= 1.0.1'
Then
bundle install