I'm currently trying to delete a post through the link
<%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' }
The problem is that when i click on it, instead of destroying the post, it's redirect me to the show view of the post.
Here is my index.html.erb
<table>
<tr>
<th>titre</th>
<th>description</th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.description %></td>
<td><%= link_to 'Show', post_path(post)%> </td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<br>
And here is my controller posts.controller
class PostsController < ApplicationController
before_action :set_post, except: [:create, :index, :new]
def index
#posts = Post.all
end
def show
end
def new
#post = Post.new
end
def edit
end
def create
#post = Post.new(post_params)
#post.save
redirect_to :action => "index"
end
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Lime was successfully updated.' }
else
format.html { render :edit }
end
end
end
def destroy
#post.destroy
redirect_to root_path, :notice => "Vous n'ĂȘtes plus un batard"
end
private #private has nos end
#Must be set to update later
def set_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :description)
end
end
Thx for helping
Make sure you have //= require jquery and //= require jquery_ujs included in your application.js And include application.js included into view/layout/application.html.erb
Related
So my goal with this method is to have it link to customers/1/showcar similar to how it will link to customers/1/edit, which is how I'm attempting to model my code.
My controller is
class CustomersController < ApplicationController
before_action :set_customer, only: [:show, :edit, :update, :destroy, :showcar]
# GET /customers
# GET /customers.json
def index
#customers = Customer.all
end
# GET /customers/1
# GET /customers/1.json
def show
end
# GET /customers/1/showcar
def showcar
end
# GET /customers/new
def new
#customer = Customer.new
end
# GET /customers/1/edit
def edit
end
# POST /customers
# POST /customers.json
def create
#customer = Customer.new(customer_params)
respond_to do |format|
if #customer.save
format.html { redirect_to #customer, notice: 'Customer was successfully created.' }
format.json { render :show, status: :created, location: #customer }
else
format.html { render :new }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /customers/1
# PATCH/PUT /customers/1.json
def update
respond_to do |format|
if #customer.update(customer_params)
format.html { redirect_to #customer, notice: 'Customer was successfully updated.' }
format.json { render :show, status: :ok, location: #customer }
else
format.html { render :edit }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
# DELETE /customers/1
# DELETE /customers/1.json
def destroy
#customer.destroy
respond_to do |format|
format.html { redirect_to customers_url, notice: 'Customer was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_customer
#customer = Customer.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def customer_params
params.require(:customer).permit(:cust_id, :cust_fname, :cust_lname, :cust_phone, :cust_addr, :cust_date)
end
end
and my html.erb file where I'm attempting to call the method is
<style>
th, td{
padding-left: 20px;
}
</style>
<p id="notice"><%= notice %></p>
<h1>Customers</h1>
<table>
<thead>
<tr>
<th>Cust ID</th>
<th>Cust fname</th>
<th>Cust lname</th>
<th>Cust phone</th>
<th>Cust addr</th>
<th>Cust date</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #customers.each do |customer| %>
<% belongstocust = Car.where(cust_id: customer.cust_id) %>
<tr>
<td><%= customer.cust_id %></td>
<td><%= customer.cust_fname %></td>
<td><%= customer.cust_lname %></td>
<td><%= customer.cust_phone %></td>
<td><%= customer.cust_addr %></td>
<td><%= customer.cust_date %></td>
<td><%= link_to 'Show', customer %></td>
<td><%= link_to 'Edit', edit_customer_path(customer) %></td>
<td><%= link_to 'Destroy', customer, method: :delete, data: { confirm: 'Are you sure?' } %></td>
#placeholder, not permanent code
<% i = '' %>
<% belongstocust.each do |car| %>
<% i = car.car_model %>
<td><%= link_to 'Show ' + i, car_path(car) %></td>
<% end %>
<td><%= link_to 'Show Car', showcar_customer_path(customer) %> </td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Customer', new_customer_path %>
<br>
<%= link_to 'Home', home_index_path %>
The issue is, whenever I have the code <td><%= link_to 'Show Car', showcar_customer_path(customer) %> </td>, I get the noMethodError even though the method is defined inside the controller, and it looks the exact same as def show and def edit. I've tried making a controller called customer, and adding the showcar method to that controller, and it worked, but it wouldn't pass over the customer. I also tried adding showcar to customer.rb, but it also gave me a noMethodError. I'm a complete noob when it comes to ruby, and was just told to make a project using the framework, so I've been having to learn along the way. This could be a really simple issue that I don't know how to solve due to my ignorance, so if that's the case I'm sorry.
I get the noMethodError even though the method is defined inside the controller
No. You have showcar defined, not showcar_customer_path. You are missing a route, the thing that defines xxx_path methods.
In your config/routes.rb you probably have
resources :customers
To register this new action, you can do
resources :customers do
member do
get :showcar
end
end
Now showcar_customer_path should be available to use in the views.
I am receiving this error and I don't understand as I have defined the method in the comments controller, haven't I?
I am getting slightly confused to why it is not working.
Comments controller:
class CommentsController < ApplicationController
def create
#story = Story.find(params[:story_id])
#comment = #story.comments.create(params[:comment].permit(:name, :body))
redirect_to root_path
end
end
Stories Controller:
class StoriesController < ApplicationController
before_action only: [:destroy, :show, :edit, :update]
def index
#stories = Story.order('created_at DESC')
end
def new
#story = current_user.stories.build
end
def create
#story = current_user.stories.build(story_params)
if #story.save
flash[:success] = "Your beautiful story has been added!"
redirect_to root_path
else
render 'new'
end
end
def edit
#story = Story.find(params[:id])
end
def update
#story = Story.find(params[:id])
if #story.update_attributes(params.require(:story).permit(:name, :description))
flash[:success] = "More knowledge, more wisdom"
redirect_to root_path
else
render 'edit'
end
end
def destroy
#story = Story.find(params[:id])
if #story.destroy
flash[:success] = "I think you should have more confidence in your storytelling"
redirect_to root_path
else
flash[:error] = "Can't delete this story, sorry"
end
end
def show
#stories = Story.all
end
private
def story_params
params.require(:story).permit(:name, :description)
end
end
Index.html.erb:
<p id="notice"><%= notice %></p>
<h1>This is a list of posts</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>User</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #stories.each do |story| %>
<tr>
<td><%= story.name %></td>
<td><%= story.description %></td>
<td><%= story.user.username %></td>
<td><%= link_to 'Show', story %></td>
<% if user_signed_in? %>
<td><%= link_to 'Edit', edit_story_path(story)%></td>
<td><%= link_to 'Destroy', story_path(story),method: :delete,data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
</tbody>
</table>
<h2><%= #story.comments.count %>Comments</h2>
<%= render #story.comments %>
<h3>Add a comment</h3>
<%= render 'comments/form' %>
<%= link_to 'New Story', new_story_path %>
Story Controller:
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
# GET /comments
# GET /comments.json
def index
#comments = Comment.all
end
# GET /comments/1
# GET /comments/1.json
def show
#comments = #story.comments.all
#comment = #stroy.comments.build
end
# GET /comments/new
def new
#comment = Comment.new
end
# GET /comments/1/edit
def edit
end
# POST /comments
# POST /comments.json
def create
#story = Story.find(params[:story_id])
#story.comments.create(comment_params)
end
# PATCH/PUT /comments/1
# PATCH/PUT /comments/1.json
def update
respond_to do |format|
if #comment.update(comment_params)
format.html { redirect_to #comment, notice: 'Comment was successfully updated.' }
format.json { render :show, status: :ok, location: #comment }
else
format.html { render :edit }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
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
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:user_name, :body, :story_id)
end
end
Make sure you have run the right migrations
rails g scaffold comment user_name:string body:text story:references
now
rake db:migrate
In your story model write
has_many :comments
And in your comment model make sure you have
belongs_to :story
or in your story controller in the show method have this
#comments = #story.comments.all
#comment = #stroy.comments.build
And now in your story form show views, something like this
<h3>Comments</h3>
<% #comments.each do |comment| %>
<div>
<p><%= comment.body %></p>
</div>
<% end %>
<%= render 'comments/form' %>
In your comment/_form.html.erb add
<%= f.hidden_field :story_id %>
If you want to display on your index edit you like so
<tbody>
<% #stories.each do |story| %>
<tr>
<td><%= story.name %></td>
<td><%= story.description %></td>
<td><%= story.user.username %></td>
<td><%= link_to 'Show', story %></td>
<% if user_signed_in? %>
<td><%= link_to 'Edit', edit_story_path(story)%></td>
<td><%= link_to 'Destroy', story_path(story),method: :delete,data: { confirm: 'Are you sure?' } %></td>
<% story.comments.each do |c| %>
<%= c.body %>
<% end %>
<% end %>
</tr>
</tbody>
You have to start by understanding how associations works:
One Story will have many comments.
You have to define the association in the model:
class Story < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :story
end
Then the methods in the controller will be available:
class CommentsController < ApplicationController
def create
#story = Story.find(params[:story_id])
#story.comments.create(comment_params)
end
end
And in your app/stories/show.html.erb view:
<% #story.comments.each do |comment| %>
<%= comment.body #or the comment content method %>
<% end %>
i got a little annoying problem.
i use this line of code on my homepage and it works, but on my posts/index page it doesn't work.
<%= link_to post.title, user_post_path(post.user.user_name, post), class:"post-listing-home-title" %>
Ultimately i want to render all posts from users on the post index page, linking to their post assosicated like this
localhost:3000/users/user_name/posts/"name of the post"
here is my error
Showing /Users/****/rorapps/*****/app/views/posts/index.html.erb where line #10 raised:
No route matches {:action=>"show", :controller=>"posts", :id=>"eli-the-great", :user_id=>nil} missing required keys: [:user_id]
here is my code
Posts controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /posts
# GET /posts.json
def index
#posts = Post.all.order("created_at desc")
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = current_user.posts.build
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = current_user.posts.build(post_params)
respond_to do |format|
if #post.save
flash[:notice] = "Post successfully created"
format.html { redirect_to #post }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
flash[:notice] = "Post successfully created"
format.html { redirect_to #post }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, :content,:slug, :metadescription, :focuskeyword)
end
end
posts/index.html.erb
<p id="notice"><%= notice %></p>
<h1 class="post-listing">Listing Posts</h1>
<% #posts.each do |post| %>
<p class="date"><%= post.created_at.strftime('%A, %B %d') %></p>
<%= link_to post.title, user_post_path(post.user.user_name, post), class:"post-listing-title" %>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
welcome.html.erb again this is where the line of code works
<div class="container">
<% #posts.each do |post| %>
<div class="featured-post fadeInBlock animated">
<p class="date"><%= post.created_at.strftime('%A, %B %d') %></p>
<span class="show-right"><%= link_to '', user_post_path(:user_id, post), class:"myright fa fa-chevron-right" %></span>
<%= link_to post.title, user_post_path(post.user.user_name, post), class:"post-listing-home-title" %>
<% if user_signed_in? %>
<td><%= link_to 'Edit', edit_user_post_path(:user_id,post) %></td>
<td><%= link_to 'Destroy', user_post_path(:user_id, post), method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
</div>
<% end %>
<div id="about-home">
<div id="about-box">
<h1 id="abouttext">Try Harder !</h1>
</div>
</div>
Thank you everyone for your help
The problem is with this line
<%= link_to post.title, user_post_path(post.user.user_name, post), class:"post-listing-title" %>
You are render these links inside a loop
<% #posts.each do |post| %>
So its seems like one of your post author doesn't has user_name.
In my Ruby on Rails application users are able to leave reviews for products, and then the administrator can view all reviews. What I want to be able to do is make it so that an administrator can still see all reviews left by everyone but a normal user can only view their own reviews and not everyone elses. Is there a simple way I can do this without using java?
Below is my index.html.erb that displays all reviews by everyone.
<div class="centre-content">
<div class="main-title">All reviews:</div>
<table>
<tr>
<th>Product</th>
<th>Name</th>
<th>Review text</th>
<th>No of stars</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #reviews.each do |review| %>
<tr>
<td><%= review.product.title %></td>
<td><%= review.user.name %></td>
<td><%= review.review_text.truncate(35) %></td>
<td><%= review.no_of_stars %></td>
<td><%= link_to 'Show', review %></td>
<td><%= link_to 'Edit', edit_review_path(review) %></td>
<td><%= link_to 'Destroy', review, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'Back', :back %>
</div>
application.html.erb where the administrator can click to view all reviews:
<% if admin? %>
<li> <%= link_to "Users", "" , :class => active_menu("users") %>
<ul>
<li> <%= link_to "Users" , users_path %> </li>
<li> <%= link_to "Edit profile" , edit_user_path(session[:user_id]) %> </li>
</ul>
<li> <%= link_to "Categories", categories_path , :class => active_menu("categories") %>
<li> <%= link_to "Reviews", reviews_path , :class => active_menu("reviews") %>
<% end %>
reviews_controller.rb:
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
# GET /reviews
# GET /reviews.json
def index
#reviews = Review.all
end
# GET /reviews/1
# GET /reviews/1.json
def show
end
def new
if logged_in?
existing_review = Review.find_by_user_id_and_product_id(session[:user_id], params[:id])
if existing_review == nil
#review = Review.new(product_id: params[:id],
user_id: User.find(session[:user_id]).id)
session[:return_to] = nil
else
redirect_to edit_review_path(existing_review.id)
end
else
session[:return_to] = request.url
redirect_to login_path, alert: "You need to login to write a review"
end
end
# GET /reviews/1/edit
def edit
end
def create
#review = Review.new(review_params)
if #review.save
product = Product.find(#review.product.id)
redirect_to product, notice: 'Your review was successfully added.'
else
render action: 'new'
end
end
# PATCH/PUT /reviews/1
# PATCH/PUT /reviews/1.json
def update
respond_to do |format|
if #review.update(review_params)
format.html { redirect_to #review, notice: 'Review was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #review.errors, status: :unprocessable_entity }
end
end
end
# DELETE /reviews/1
# DELETE /reviews/1.json
def destroy
#review.destroy
respond_to do |format|
format.html { redirect_to reviews_url }
format.json { head :no_content }
end
end
def displays
product = Product.find(params[:id])
#reviews = product.reviews
if #reviews.empty?
redirect_to product, notice: "No reviews - as yet ..."
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_review
#review = Review.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def review_params
params.require(:review).permit(:product_id, :user_id, :review_text, :no_of_stars)
end
end
reviews.rb model:
class Review < ActiveRecord::Base
belongs_to :product
belongs_to :user
validates :review_text, :presence => { :message => "Review text: cannot be blank ..."}
validates :review_text, :length => {:maximum => 2000, :message => "Review text: maximum length 2000 characters"}
validates :no_of_stars, :presence => { :message => "Stars: please rate this book ..."}
end
Is there anyway I can make it so that a user only views their own reviews?
In your controller display method, you can do stg like this i think :
def display
product = Product.find(params[:id])
#reviews = product.reviews.select! { |s| s.user_id == current_user.id } unless admin?
....
end
That way, only admin will have all reviews, and others users will only see their own reviews (with theirs ids)
you dont have current_user method but it es explained well in this tutorial :
https://www.railstutorial.org/book/log_in_log_out#sec-current_user
it is the same as session[:id] but in a well ordered manner.
Ps: i'm not sur about the s.user_id ... don't remember the exact syntax but should be it.
Another way :
you could take the reviews for this specific product id and then filter out by the user id.
`#reviews = Reviews.find_by_product_id(params[:product_id]).select { |r| r.user_id == current_user.id }`
My girl model has comments with using gem 'acts_as_commentable'
When I access example.com/girls/show/1
It shows ID#1 girl's profile.
All the posted comments are shown in the bottom of this page.
For each comment row, I want to add delete button to delete a comment.
If it should pass the parameter to girls_controller.rb's comment_destroy action.
How action part and view should be??
It keeps undefined local variable or method `girls' error with codes below.
"girls/show.html.erb" view should be something like this. Just a part.
<table>
<tr>
<th>ID</th>
<th>Title</th>
<th>Body</th>
<th>Subject</th>
<th>Delete</th>
</tr>
<% #all_comments.each do |comment| %>
<tr>
<td><%= comment.id %></td>
<td><%= comment.title %></td>
<td><%= comment.body %></td>
<td><%= comment.subject %></td>
<td><%= button_to 'comment_destroy', girls, confirm: 'Are you sure?', :disable_with => 'deleting...', method: :delete %></td>
</tr>
<% end %>
</table>
girls_controller.rb's comment_destroy action should be something like this
def comment_destroy
#comment = comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to girls_url }
format.json { head :ok }
end
redirect_to :controller => 'girls', :action => 'show', :id => params[:girls][:id]
flash[:notice] = "comment deleted!"
end
It looks like you have comments nested under a girl, and you want to delete the comment.
Routes
resources :girls do
resources :comments, only: [:create, :destroy]
end
Then, you have a comments controller that handles your creation and destroy.
<%= button_to 'comment_destroy', [#girl, comment], confirm: 'Are you sure?', :disable_with => 'deleting...', method: :delete %>
The destroy method in your comments controller:
def destroy
#girl = Girl.find(params[:girl_id])
#comment = #girl.comments.find(params[:id])
if #comment.destroy
redirect_to #girl, notice: "Comment Removed"
else
redirect_to #girl, error: "We could not remove the comment"
end
end
end
UPDATE -- based on user's request to use a non-restful solution
Routes:
resources :girls do
member do
delete :delete_comment, to: "girls#delete_comment", as: "delete_comment"
end
end
controller
def delete_comment
#girl = Girl.find(params[:id])
#comment = #girl.comments.find(params[:comment_id])
if #comment.destroy
redirect_to #girl, notice: "Comment Removed"
else
redirect_to #girl, error: "We could not remove the comment"
end
end
View link
<%= button_to 'comment_destroy', delete_comment_path(#girl, comment_id: comment.id), confirm: 'Are you sure?', :disable_with => 'deleting...', method: :delete %>
Final note: I really don't like this solution. You should have a Comments controller and go with my first solution.