I am new to Ruby on Rails and I am making a view page showing a table from the database. I want to add a link_to to delete this record. I tried the code written below and nothing worked for me.
The browser keeps refreshing and does nothing.
ruby 3.1.2
Rails 7.0.4
<%= link_to 'Delete', #friend, data: {turbo_method: :delete, turbo_confirm: 'Sure?'}, class: "btn btn-danger" %>
also with this
<%= link_to 'Delete', #friend, method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger" %>
html.erb code
<p style="color: green"><%= notice %></p>
<%= render #friend %>
<div>
<%= link_to "Edit this friend", edit_friend_path(#friend) %> |
<%= link_to "Back to friends", friends_path %>
<%#= button_to "Destroy this friend", #friend, method: :delete,data: {turbo_confirm: 'Are you sure?'} %>
<%#= button_to "Destroy this friend", #friend, method: :delete,data: {turbo_confirm: 'Are you sure?'} %>
<%= link_to 'Delete', #friend, method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger" %>
</div>
Controller code
class FriendsController < ApplicationController
before_action :set_friend, only: %i[ show edit update destroy ]
# GET /friends or /friends.json
def index
#friends = Friend.all
end
# GET /friends/1 or /friends/1.json
def show
end
# GET /friends/new
def new
#friend = Friend.new
end
# GET /friends/1/edit
def edit
end
# POST /friends or /friends.json
def create
#friend = Friend.new(friend_params)
respond_to do |format|
if #friend.save
format.html { redirect_to friend_url(#friend), notice: "Friend was successfully created." }
format.json { render :show, status: :created, location: #friend }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #friend.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /friends/1 or /friends/1.json
def update
respond_to do |format|
if #friend.update(friend_params)
format.html { redirect_to friend_url(#friend), notice: "Friend was successfully updated." }
format.json { render :show, status: :ok, location: #friend }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #friend.errors, status: :unprocessable_entity }
end
end
end
# DELETE /friends/1 or /friends/1.json
def destroy
#friend.destroy
respond_to do |format|
format.html { redirect_to friends_url, notice: "Friend was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_friend
#friend = Friend.find(params[:id])
end
# Only allow a list of trusted parameters through.
def friend_params
params.require(:friend).permit(:first_name, :last_name, :email, :phone, :twitter)
end
end
Your code should work
<%= link_to 'Delete', #friend,
data: {turbo_method: :delete, turbo_confirm: 'Sure?'}, class: "btn btn-danger" %>
But more reliable to use button_to that generate form tag with button
<%= button_to 'Delete', #friend,
method: :delete, form: {data: {turbo_confirm: 'Sure?'}}, class: "btn btn-danger" %>
Related
I'm new on ruby on rails.
I'm currently working on a facebook clone application and having trouble when adding a post without refreshing the page. Tried to create a post but the post did not show upon submitting and encountered Internal Server Error. When the page is refreshed, the newly created post is finally displayed.
Error in rails server
Completed 500 Internal Server Error in 50ms (ActiveRecord: 15.9ms | Allocations: 10085)
ActionView::Template::Error (First argument in form cannot contain nil or be empty):
1: = form_for([post, #comment]) do |f|
2: .form-bottom-button-container
3: .d-flex.comment-text-button
4: .p-2.flex-grow-1
Here are my codes. Please help me out. Thank you very much!
app/controllers/posts_controller.rb
def create
#post = current_user.posts.build(post_params)
respond_to do |format|
if #post.save
format.js
format.html { redirect_to posts_path, notice: 'Successfully posted.'}
else
format.html { redirect_to posts_path, status: :unprocessable_entity }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
app/views/posts/create.js.haml
:plain
$("#post-display").append("#{escape_javascript(render 'post_display', post: #post)}");
app/views/posts/index.html.haml
-# All Posts
.col-8
.post-form
= render "post_form"
- if #posts.empty?
.post-card
.post-text
.no-post-text No posts to show
- else
#post-display
= render partial: "post_display", collection: #posts, as: :post
app/views/posts/_post_display.html.haml
.post-card
.post-text
.d-flex.justify-content-between
.d-flex
.post-user-image
- if post.user.profile_pic.present?
= image_tag post.user.profile_pic.url, class: "img img-fluid img-thumb"
- else
= image_tag "/default-user.jpg", class: "img img-fluid img-thumb"
.d-flex.flex-column
.username-bold= link_to post.user.username, profile_path(post.user.username)
.distance-date= distance_of_time_posted_in_words(post.created_at)
.post-edit-delete
- if post.user.username == current_user.username
= link_to edit_post_path(post), class: "text-space", remote: true, "data-bs-toggle" => "modal", "data-bs-target" => "#edit-post-#{post.id}-modal" do
%i.fa.fa-edit
.modal.fade(id="edit-post-#{post.id}-modal" tabindex="-1" aria-labelledby="edit-post-title" aria-hidden="true")
.modal-dialog.modal-dialog-centered.modal-dialog-scrollable
.modal-content
= link_to post, method: :delete, class: "text-space" do
%i.fa.fa-trash
.caption= post.caption
- if post.image.present?
= image_tag post.image.url, class: "img img-fluid img-fill"
-# Like Button
.row.container-margin-top
.col-6
- if liker(post)
= button_to post_like_path(post, liker(post)), method: :delete, class: "btn btn-maroon btn-wide btn-like-comment" do
%i.far.fa-thumbs-up
Unlike
- else
= button_to post_likes_path(post), method: :post, class: "btn btn-plain btn-wide btn-like-comment" do
%i.far.fa-thumbs-up
Like
.col-6
.btn.btn-plain.btn-wide.btn-like-comment.btn-comment
%i.far.fa-comment
%span Comment
-# Comment Section
.comment-box
.d-flex.justify-content-between
- unless post.likes.count == 0
.post-likes(type="button" data-bs-toggle="modal" data-bs-target="#likers-#{post.id}-modal")= "#{pluralize(post.likes.count, "like")}"
= render "layouts/likers_modal", post: post, index: post.id
.comment-toggle View Comments
.comment-display.hidden
= render "posts/comments", post: post
.comment-form
= render "comments/comment_form", post: post
app/views/comments/_comment_form.html.haml
= form_for([post, #comment]) do |f|
.form-bottom-button-container
.d-flex.comment-text-button
.p-2.flex-grow-1
= f.text_area :content, class: "comment-text-area comment", placeholder: "Write a comment..."
.p-2
= f.submit :Comment, class: "btn btn-maroon create-comment-button"
Check your application logs - it'll probably tell you the format.js method does not exist.
def create
#post = current_user.posts.build(post_params)
respond_to do |format|
if #post.save
format.js # <----
format.html { redirect_to posts_path, notice: 'Successfully posted.'}
else
format.html { redirect_to posts_path, status: :unprocessable_entity }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
Just remove that line or use the format.json method and you're good to go.
To make the page not refresh you must submit the form using ajax request... you simply add remote: true to the form.
form_for([post, #comment], remote: true) do |f|
Also the error you are getting is because #comment is not being set.
Hello can you pls explain me how should I delete my task from a todo app?
My show_html_erb form looks like this:
this is my third day learning ruby i am quite confused i saw the documentation did the same but it just not listening to my commands:(
<%= form_for([#todo_list, #todo_item]) do |f| %>
<div class="input-group mb-4">
<%= f.text_field :description , class:"form-control", placeholder:'Add todo items'%>
<div class="input-group-append">
<%= f.submit 'Add', class:"btn btn-primary input-group-btn"%>
</div>
</div>
<%end%>
<ul class='list-group'>
<% #todo_list.todo_items.each do |todo_item| %>
<% if todo_item.completed?%>
<li class='list-group-item bg-light'>
<div class="d-flex justify-content-between">
<span class="text-muted">
<em> <%= todo_item.description%></em>
</span>
**<%= link_to 'DELETE',todo_list_path(todo_item),method: :delete, class:'btn btn-dark'%>** ------>> **THISSSS**
<%= link_to '#', class:'btn btn-dark' ,data:{reflex: 'click->TodoItem#mark_incomplete',id:todo_item.id} do%>
<i class='fas fa-undo-alt'></i>
<%end%>
</div>
</li>
<%else%>
<li class='list-group-item'>
<div class="d-flex justify-content-between">
<span>
<%= todo_item.description%>
</span>
<%= link_to 'Destroy', todo_list_path(todo_item),
method: :delete,
data: { confirm: 'Are you sure?' } ,class:'btn btn-dark'%> ------>> THIIIISSSSS
<%= link_to '#', class:'btn btn-info',data:{reflex: 'click->TodoItem#mark_complete',id:todo_item.id} do %>
<i class='fas fa-check'></i>
<%end%>
</div>
</li>
<%end%>
<%end%>
</ul>
</div>
what do i give wrong ,( i suppose the path , when i delete )
My todolist controller looks like this:
class TodoListsController < ApplicationController
before_action :set_todo_list, only: [:show, :edit, :update, :destroy]
# GET /todo_lists
# GET /todo_lists.json
def index
#todo_lists = TodoList.all
end
# GET /todo_lists/1
# GET /todo_lists/1.json
def show
#todo_item = TodoItem.new
end
# GET /todo_lists/new
def new
#todo_list = TodoList.new
end
# GET /todo_lists/1/edit
def edit
end
# POST /todo_lists
# POST /todo_lists.json
def create
#todo_list = TodoList.new(todo_list_params)
respond_to do |format|
if #todo_list.save
format.html { redirect_to #todo_list, notice: 'Todo list was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /todo_lists/1
# PATCH/PUT /todo_lists/1.json
def update
respond_to do |format|
if #todo_list.update(todo_list_params)
format.html { redirect_to #todo_list, notice: 'Todo list was successfully updated.' }
format.json { render :show, status: :ok, location: #todo_list }
else
format.html { render :edit }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /todo_lists/1
# DELETE /todo_lists/1.json
def destroy
#todo_list = TodoList.find(params[:id])
#todo_list.destroy
respond_to do |format|
format.html { redirect_to todo_lists_url, notice: 'Todo list was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_todo_list
#todo_list = TodoList.find(params[:id])
end
# Only allow a list of trusted parameters through.
def todo_list_params
params.require(:todo_list).permit(:title)
end
end
The issue is that you are not passing the correct object/path to delete. Try the below code.
<%= link_to 'Destroy', todo_item,
method: :delete,
data: { confirm: 'Are you sure?' } ,class:'btn btn-dark'%>
And I believe the html which you shared above is index.html.erb not show.html.erb
So i found the answer , what i had to do is linking the delete method like that:
<%= link_to 'Destroy', todo_list_todo_item_path(#todo_list,todo_item),
method: :delete,
data: { confirm: 'Are you sure?' } ,class:'btn btn-dark'%>
that fixed my problem ( the reason why is because as you could see in my show.html.erb file that ive used a nested scaffold )
I'm getting the following error:
NoMethodError in Submissions#show
undefined method `comment_path'
I can login, enter a title and URL, and post a comment. When I hit the "Create Comment button"
this is where it errors out:
<%= link_to 'delete', comment, method: :delete, data: { confirm: 'are you sure?'} %>
Other than the error, I'm trying to ADD a Comment not DELETE one?
_comment.html.erb
<%= div_for(comment) do %>
<div class="comments-wrapper clearfix">
<div class="null-left">
<p><small> <%= comment.user.email %> <strong><%=
time_ago_in_words(comment.created_at) %></strong> ago </small></p>
<p class="lead"><%= comment.body %></p>
</div>
</div>
<% if comment.user == current_user %>
<%= link_to 'delete', comment, method: :delete, data: { confirm:
'are you sure?'} %>
<% end %>
<% end %>
comments_controller.rb
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
def create
#submission = Submission.find(params[:submission_id])
#comment = #submission.comments.new(comment_params)
#comment.user = current_user
respond_to do |format|
if #comment.save
format.html { redirect_to #submission, notice: 'Comment was successfully created.' }
else
format.html { render :new }
end
end
end
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url, notice: 'Comment was
successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_comment
#comment = Comment.find(params[:id])
end
def comment_params
params.require(:comment).permit(:submission_id, :body, :user_id)
end
end
submission_controller.rb
class SubmissionsController < ApplicationController
before_action :set_submission, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#submissions = Submission.all
end
def show
end
def new
#submission = current_user.submissions.build
end
def edit
end
def create
#submission = current_user.submissions.build(submission_params)
respond_to do |format|
if #submission.save
format.html { redirect_to #submission, notice: 'Submission was
successfully created.' }
format.json { render :show, status: :created, location: #submission
}
else
format.html { render :new }
format.json { render json: #submission.errors, status:
:unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #submission.update(submission_params)
format.html { redirect_to #submission, notice: 'Submission was
successfully updated.' }
format.json { render :show, status: :ok, location: #submission }
else
format.html { render :edit }
format.json { render json: #submission.errors, status:
:unprocessable_entity }
end
end
end
def destroy
#submission.destroy
respond_to do |format|
format.html { redirect_to submissions_url, notice: 'Submission was
successfully destroyed.' }
format.json { head :no_content }
end
end
def upvote
#submission = Submisson.find{params[:id]}
#submission.upvote_by current_user
redirect_to :back
end
def downvote
#submission = Submisson.find{params[:id]}
#submission.downvote_by current_user
redirect_to :back
end
private
def set_submission
#submission = Submission.find(params[:id])
end
def submission_params
params.require(:submission).permit(:title, :url)
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users
resources :submissions do
member do
put "Like", to: "submission#upvote"
put "Dislike", to: "submission#downvote"
end
resources :comments
end
root to: "submissions#index"
end
For delete, you need to pass submission id like
Your code
<%= link_to 'delete', comment, method: :delete, data: { confirm: 'are you sure?'} %>
After modified
<%= link_to 'Delete', [comment.submission, comment], method: :delete, data: { confirm: 'Are you sure?' } %>
On the comment form
<%= f.hidden_field :user_id, value: current_user.id %>
Create action on comment controller, remove this two lines
#comment = #submission.comments.new(comment_params)
#comment.user = current_user
After update delete link then test for comment create if not creating comment still then follow the below code.
Now your comment create action look like this
def create
#submission = Submission.find(params[:submission_id])
respond_to do |format|
if #submission.comments.create(comment_params)
format.html { redirect_to #submission, notice: 'Comment was successfully created.' }
else
format.html { render :new }
end
end
end
That code from my project which already working, if not working on your side then if have your public repository then post URL or post full error trace.
Update Based on GitHub Link
If you run the rake routes then you will see the comment delete routes format like
DELETE /submissions/:submission_id/comments/:id(.:format) comments#destroy
You need to pass submission_id plus id for comment delete
Update link_to delete looks like this
<%= link_to 'Delete', [comment.submission, comment], method: :delete, data: { confirm: 'Are you sure?' } %>
And your destroy action looks like this on the comments_controller
def destroy
#submission = Submission.find(params[:submission_id])
#comment = #submission.comments.find(params[:id])
#comment.destroy
redirect_to submission_path(#submission)
end
Hope it helps
the delete method is not working when trying to destroy a record. When clicking on the button, it will redirect me to shops#show action, looks like the method: :delete is not working...Any help please?
Routes
resources :shops
HTML
<% #shops.sort.each do |shop| %>
<tr>
<td><%= shop.name %></td>
<td><%= shop.email %></td>
<td><%= shop.direction %></td>
<td>
<%= link_to '<button>Borrar</button>', shop, method: :delete, data: { confirm: "Seguro?" } %>
</td>
</tr>
<% end %>
Controller
def destroy
#shop = Shop.find(params[:id])
#shop.destroy
respond_to do |format|
format.html { redirect_to "/sushiadmin", notice: 'Se ha editado la tienda.' }
format.json { head :no_content }
end
end
Do this:
<%= link_to 'Borrar', shop, method: :delete, data: { confirm: "Seguro?" }, class: 'btn btn-primary' %>
And delete Shop.find
def destroy
#shop.destroy
respond_to do |format|
format.html { redirect_to "/sushiadmin", notice: 'Se ha editado la tienda.' }
format.json { head :no_content }
end
end
Try with this (specifying the url)
link_to '<button>Borrar</button>' , shop_path( shop ), :method => 'delete', data: { confirm: "Seguro?" }
Acording with http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to
link_to(body, url, html_options = {})
I have a model called Images with an uploader attached to it (Carrierwave). Images belongs to a model called Listing. After creating a listings I'm redirected to the Images index page to upload files (localhost:3000/listings/1/images)
But for some reason every time I create a listing an image it's created at the same time. There's actually no image present but it displays the "delete" link I have for each image.
<span><%= link_to 'DELETE', listing_image_path(#listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
Any help? Thanks.
Listings Controller
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, :except => [:show, :index]
def index
#listings = Listing.order('created_at DESC')
respond_to do |format|
format.html
format.json { render json: #listings }
end
end
def show
end
def new
#listing = Listing.new
#listing.user = current_user
end
def edit
end
def create
#listing = Listing.new(listing_params)
#listing.user = current_user
respond_to do |format|
if #listing.save
format.html { redirect_to listing_images_path(#listing), notice: 'Post was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #listing.update(listing_params)
flash[:notice] = 'Deal was successfully updated.'
format.html { redirect_to #listing }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
def destroy
#listing.destroy
respond_to do |format|
format.html { redirect_to listings_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing
#listing = Listing.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_params
params.require(:listing).permit(:id, :condition, :description, :nickname, :price, :size, :title, :user_id)
end
end
Listings Form
<%= form_for(#listing, :html => { :class => 'form', :multipart => true }) do |f| %>
<% if #listing.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#listing.errors.count, "error") %> prohibited this listing from being saved:</h2>
<ul>
<% #listing.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= f.label :title %>
<%= f.text_field :title, :required => true %>
</div>
<div>
<%= f.label :price %>
<%= f.text_field :price %>
</div>
<div class="actions">
<%= f.submit 'Submit', :class => 'buyNow' %>
</div>
<% end %>
Images Controller
class ImagesController < ApplicationController
before_action :set_image, only: [:show, :edit, :update, :destroy]
before_filter :load_listing
def index
#images = #listing.images.load
#image = #listing.images.new
end
def new
end
def edit
end
def create
#image = #listing.images.new(image_params)
respond_to do |format|
if #image.save
format.html { redirect_to :back, notice: 'Image was successfully created.' }
format.json { head :no_content }
else
format.html { render action: 'new' }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #image.update(image_params)
format.html { redirect_to (#image.listing), notice: 'Image was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
def destroy
#image = #listing.images.find(params[:id])
#image.destroy
respond_to do |format|
format.html { redirect_to :back }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_image
#image = Image.find(params[:id])
end
def load_listing
#listing = Listing.find(params[:listing_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def image_params
params.require(:image).permit(:file, :listing_id)
end
end
Images Index
<div>
<%= form_for [#listing, #image], :html => { :class => 'uploadImages', :multipart => true } do |f| %>
<%= f.hidden_field :listing_id %>
<div>
<%= f.label :file, 'Upload Images' %>
<%= f.file_field :file, multiple: true, name: 'image[file]' %>
</div>
<% end %>
</div>
<div id="progress"></div>
<% if #images.present? %>
<ul class="editGallery">
<% #listing.images.each do |image| %>
<li>
<%= image_tag image.file_url(:list) if image.file? %>
<span><%= link_to 'DELETE', listing_image_path(#listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
</li>
<% end %>
</ul>
<% end %>
The problem is this line:
#image = #listing.images.new
That's building a new image for #listing, so when you call #listing.images.each that new image is included in the images array. Check that the image has actually been saved to the database before constructing a delete link for it.
<% #listing.images.each do |image| %>
<% unless image.new_record? %>
<li>
<%= image_tag image.file_url(:list) if image.file? %>
<span><%= link_to 'DELETE', listing_image_path(#listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
</li>
<% end %>
<% end %>
Take a look at this part of your code:
<% if #images.present? %>
<ul class="editGallery">
<% #listing.images.each do |image| %>
<li>
<%= image_tag image.file_url(:list) if image.file? %>
<span><%= link_to 'DELETE', listing_image_path(#listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
</li>
<% end %>
</ul>
I believe your problem is a combination of this and your images controller index action.
When you hit the index action you create a new record #image = #listing.images.new
Now your #listing.images.each call registers on the object that hasn't been saved.