NoMethodError in CommentsController#create - ruby-on-rails

Im a beginner in rails so i started to follow a tutorial on http://guides.rubyonrails.org/getting_started.html Now im stuck on the 6.4 part when you need to make a comment but i cant figure it out what the problem is. When i want to create a comment im getting this error and oh yeah im on windows
NoMethodError in CommentsController#create
undefined method `title' for # Comment:0x88e4038
this is my comment controller
class CommentsController < ApplicationController
http_basic_authenticate_with name: "dhh", password: "secret", only: :destroy
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.create(comment_params)
redirect_to article_path(#article)
end
def destroy
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
#comment.destroy
redirect_to article_path(#article)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
This is my show.html.erb
<p>
  <strong>Title:</strong>
  <%= #article.title %>
</p>
 
<p>
  <strong>Text:</strong>
  <%= #article.text %>
</p>
 
<h2>Comments</h2>
<%= render #article.comments %>
 
<h2>Add a comment:</h2>
<%= form_for([#article, #article.comments.build]) do |f| %>
  <p>
    <%= f.label :commenter %><br>
    <%= f.text_field :commenter %>
  </p>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
 
<%= link_to 'Edit Article', edit_article_path(#article) %> |
<%= link_to 'Back to Articles', articles_path %>
comment.html.erb
<p>
  <strong>Commenter:</strong>
  <%= comment.commenter %>
</p>
 
<p>
  <strong>Comment:</strong>
  <%= comment.body %>
</p>
 
<p>
  <%= link_to 'Destroy Comment', [comment.article, comment],
               method: :delete,
               data: { confirm: 'Are you sure?' } %>
</p>
and this is the route
Rails.application.routes.draw do
resources :articles do
resources :comments
end
root 'welcome#index'
end

I looked at the tutorial and the comment model has no attribute title. Rails is complaining because you're trying to validate the 'title' attribute in the Comment model:
validates :title, presence: true, length: { minimum: 5 }
Remove this validation.

Related

How to limit someone to deleting their own comment in Rails?

I am very new to Rails. I completed a tutorial here that walks you through the steps of creating a blog using it.
Part of the tutorial shows you how to create a controller that allows users to add comments to an article. I am trying to modify it so that users can only delete their own comments (and not others' comments).
Question:
Is there a way to modify the code so that way you can limit users to deleting their own comments? Any resources/tutorials are welcome too. I really just have no clue on how to start.
I feel like the right way to go is to mark the user some way when they submit the comment. Save that information in the database, and then check that information when someone goes to delete a comment. But I can't think of a way to do that without trying to build a full on log in system for users.
Code:
Here is the code from the tutorial:
Database Migration:
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :commenter
t.text :body
t.references :article, index: true, foreign_key: true
t.timestamps null: false
end
end
end
Controller:
class CommentsController < ApplicationController
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.create(comment_params)
redirect_to article_path(#article)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
Template:
<p>
<strong>Title:</strong>
<%= #article.title %>
</p>
<p>
<strong>Text:</strong>
<%= #article.text %>
</p>
<h2>Add a comment:</h2>
<%= form_for([#article, #article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Edit', edit_article_path(#article) %> |
<%= link_to 'Back', articles_path %>
Delete Comment:
class CommentsController < ApplicationController
  def create
    #article = Article.find(params[:article_id])
    #comment = #article.comments.create(comment_params)
    redirect_to article_path(#article)
  end
 
  def destroy
    #article = Article.find(params[:article_id])
    #comment = #article.comments.find(params[:id])
    #comment.destroy
    redirect_to article_path(#article)
  end
 
  private
    def comment_params
      params.require(:comment).permit(:commenter, :body)
    end
end
I found a similar question here, but there wasn't an answer that worked.
In CommentsController Edit your destroy method like below :
def destroy
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
if #comment.user.id == current_user.id
flash[:success] = "Comment Deleted Successfully!"
#comment.destroy
else
flash[:error] = "You can only delete your own comments!"
end
redirect_to article_path(#article)
end
Add a migration to add user_id to the comment table :
class AddUserIdToComments < ActiveRecord::Migration
def change
add_column :comments, :user_id, :integer
end
end
Comment & User Model should be like below to track the user from comment :
class User < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :user
end
View:
<p>
<strong>Title:</strong>
<%= #article.title %>
</p>
<p>
<strong>Text:</strong>
<%= #article.text %>
</p>
<h2>Add a comment:</h2>
<%= form_for([#article, #article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
<%= f.hidden_field :user_id, current_user.id %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Edit', edit_article_path(#article) %> |
<%= link_to 'Back', articles_path %>
In Comment Controller change comment_params
def comment_params
params.require(:comment).permit(:commenter, :body, :user_id)
end

Ruby Incorrect link generation redirect_to products_path(#product) generate /products.1 instead of /products/1

I'm trying to add a reviews on my single product page. But when I click Submit - It takes me to the /products.1 page, instead of /products/1
class CommentsController < ApplicationController
def create
#product = Product.find(params[:product_id])
#comment = #product.comments.new(comment_params)
#comment.user = current_user
#comment.save
redirect_to products_path(#product)
end
def destroy
end
private
def comment_params
params.require(:comment).permit(:user_id, :body, :rating)
end
end
and the comment.html.erb
<div class="row">
<div class="col-sm-6">
<% if signed_in? %>
<h4>Add a review:</h4>
<%= form_for([#product, #product.comments.build]) do |f| %>
<p>
<%= f.label :body, "Comment" %><br>
<%= f.text_area :body, class: "form-control" %>
</p>
<p>
<%= f.label :rating %><br>
<%= f.text_field :rating, class: "rating form-control" %>
</p>
<p>
<%= f.submit "Submit", class: "btn" %>
</p>
<% end %>
<% end %>
</div>
</div>
Try redirect_to #product instead of redirect_to products_path(#product).
Did you check your routes.rb under config? Try running rake routes in the terminal and you can debug from there.

Couldn't find Article without an ID [duplicate]

I am trying to submit some data to db and its ok but when i am trying to retrieve those data show that Couldn't find Article without an ID.ils 4.0.1.
I am using ruby 2.0.0 and ra
def show
#article=Article.find(params[:id])
end
the ** contain error.
class ArticlesController < ApplicationController
def new
end
def create
#article = Article.new(article_params)
redirect_to #article
#article.save
end
def show
#article=Article.find(params[:id])
end
private
def article_params
params.require(:article).permit(:title, :full_name, :email, :phone_number, :message)
end
end
articles/show.html.erb
<p>
<strong>Title:</strong>
<%= #article.title %>
</p>
<p>
<strong>Full Name:</strong>
<%= #article.full_name %>
</p>
<p>
<strong>Email:</strong>
<%= #article.email %>
</p>
<p>
<strong>Phone Number:</strong>
<%= #article.phone_number %>
</p>
<p>
<strong>Message:</strong>
<%= #article.message %>
</p>
articles/new.html.erb
<h1>New Articles</h1>
<%= form_for :article, url: articles_path do |f| %>
<p>
<%= f.label :title %>
<%= f.text_field :title %>
<p>
<%= f.label :full_name %>
<%= f.text_field :full_name %>
</p>
<%= f.label :email %>
<%= f.text_field :email %>
<p>
<%= f.label :phone_number %>
<%= f.text_field :phone_number %>
</p>
<%= f.label :message %>
<%= f.text_field :message %>
<p>
<%= f.submit :send_message %>
</p>
<% end %>
You are redirecting before actually saving your article.
This:
def create
#article = Article.new(article_params)
redirect_to #article
#article.save
end
should be:
def create
#article = Article.new(article_params)
#article.save
redirect_to #article
end
And if you want to add some error handling as well:
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render :new
end

create comments for nested routes

I'm trying to make a blog which has users, posts and comments. Each user can have many posts and many comments similarly each post can have many comments. I have successfully made the user and post sections but am having difficulty creating comments and then displaying them.
code:
routes.rb :
resources :users do
resources :posts do
resources :comments
end
end
user.rb :
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy
post.rb :
belongs_to :user
has_many :comments, dependent: :destroy
comment.rb :
belongs_to :post, :user
I'm creating and displaying comments in the post's view itself so..
posts_controller.rb :
def show
#user = current_user
#post = Post.find(params[:id])
end
view/posts/show.html.erb :
<p><strong>Title:</strong><%= #post.title %></p>
<p><strong>Text:</strong><%= #post.text %></p>
<% if #user.posts.comments.empty? %>
<h2>Comments</h2>
<%= render #posts.comments %>
<% end %>
<h2>Add a comment:</h2>
<%= render "comments/form" %>
<%= link_to 'Edit Post', edit_user_post_path(#user.id,#post) %> |
<%= link_to 'Back to Posts', user_posts_path(#user.id) %>
comments_controller.rb :
class CommentsController < ApplicationController
def create
#user = current_user
#post = #user.posts.find(params[:post_id])
#comment = #user.posts.comments.create(params[:comment])
redirect_to user_post_path(#user.id,#post)
end
def destroy
#user = current_user
#post = #user.posts.find(params[:post_id])
#comment = #user.posts.comments.find(params[:id])
#comment.destroy
redirect_to user_post_path(#user.id,#post)
end
end
And the partials are:
views/comments/_form.html.erb :
<%= form_for([#user,#post,#comment]) do |f| %>
<p>
<%= #user.email %>
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
I think my form_for is not right here but I'm new to rails and I've also tried form_for(#user,#post,#post.comments.build) but that didn't work either.. Anyways here's another partial:
views/comments/_comment.html.erb:
<p><strong>Commenter:</strong><%= #user.email %></p>
<p><strong>Comment:</strong><%= comment.body %></p>
<p><%= link_to 'Destroy Comment', [comment.post, comment],method: :delete,
data: { confirm: 'Are you sure?' } %>
</p>
Again here I'm having trouble with link to...any suggestions would be great.
You want to make a blog which has users , posts and comments, I see some differences between what you did and what I did it before when I was creating a blog also. I will tell you what I did (by editing the code of the files you posted in your question) then try it if it works with you :)
1- routes.rb make it like this
resources :users
resources :posts do
resources :comments
end
2- user.rb is fine no need to be modified
3- post.rb also is fine
4- comments.rb
belongs_to :post
belongs_to :user
5- posts_controller.rb
def show
#post = Post.find(params[:id])
#comment = Comment.new
end
6- view/posts/show.html.erb ( this view should make you able to see the post and the comments and a box for the new comments, and a link to edit post and a link to the posts index )
<p><strong>Title:</strong><%= #post.title %></p>
<p><strong>Text:</strong><%= #post.text %></p>
<h2>Comments</h2>
<%= render #posts.comments %>
<h2>Add a comment:</h2>
<%= render "comments/form" %>
<%= link_to 'Edit Post', edit_post_path(#post) %> |
<%= link_to 'Back to Posts', posts_path %>
7- comments_controller.rb ( don't forget to add the destroy method again )
class CommentsController < ApplicationController
before_filter :load_post
def create
#comment = #post.comments.build(params[:comment])
#comment.user_id = current_user.id
if #comment.save
redirect_to #post, notice: "Added comment."
else
render :new
end
end
private
def load_post
#post = Post.find(params[:article_id])
end
end
8- views/comments/_form.html.erb (just try to make it first in a simple way)
<%= form_for([#post,#comment]) do |f| %>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
9- views/comments/_comment.html.erb
<p><strong>Commenter:</strong><%= comment.user.email %></p>
<p><strong>Comment:</strong><%= comment.body %></p>
<p><%= link_to 'Destroy Comment', [comment.post, comment],method: :delete,
data: { confirm: 'Are you sure?' } %>
</p>
I hope this work with you as it works with me, try it and let me know how it goes with you, i got my blog work from the before code for revised episode 229.
I got the answer here it is:
posts_controller:
def show
#user = current_user
#post = #user.posts.find(params[:id])
#comment = #post.comments.new
end
show.html.erb:
<p><strong>Title:</strong><%= #post.title %></p>
<p><strong>Text:</strong><%= #post.text %></p>
<% if !#post.comments.empty? %>
<h2>Comments</h2>
<%= render #comment %>
<% end %>
<h2>Add a comment:</h2>
<%= render "comments/form" %>
<%= link_to 'Edit Post', edit_user_post_path(#user.id,#post) %> |
<%= link_to 'Back to Posts', user_posts_path(#user.id) %>
comments_controller.rb:
def create
#user = current_user
#post = #user.posts.find(params[:post_id])
#comment = #post.comments.create(params[:comment])
redirect_to user_post_path(#user.id,#post)
end
comment's partial
_form.html.erb:
<%= form_for([#user,#post,#comment]) do |f| %>
<p><%= #user.email %></p>
<p><%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p><%= f.submit %></p>
<% end %>

comments not displaying in ruby on rails blog application

I'm trying to display commenter and body of comments model in blog application. But it is not displaying.
Here is the code of comments controller.
class CommentsController < ApplicationController
http_basic_authenticate_with :name => "dhh", :password => "secret", :only => :destroy
def create
#post=Post.find(params[:post_id])
#comment=#post.comments.create(params[:comments])
redirect_to post_path(#post)
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
def check
#comment=Comment.all
end
end
//comment model
class Comment < ActiveRecord::Base
belongs_to :post
attr_accessible :body, :commenter
end
//post model
class Post < ActiveRecord::Base
attr_accessible :content, :name, :title, :tags_attributes
validates :name, :presence=>true
validates :title, :presence=>true,
:length=>{:minimum=>5}
has_many :comments, :dependent=>:destroy
has_many :tags
accepts_nested_attributes_for :tags, :allow_destroy => :true,
:reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
end
// comment view
<p>
<b>Commenter:</b>
<%= comment.commenter %>
</p>
<p>
<b>Comment:</b>
<%= comment.body %>
</p>
<p>
<%= link_to 'Destroy Comment', [comment.post, comment],
:confirm => 'Are you sure?',
:method => :delete %>
</p>
// Post view
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #post.name %>
</p>
<p>
<b>Title:</b>
<%= #post.title %>
</p>
<p>
<b>Content:</b>
<%= #post.content %>
</p>
<p>
<b>Tags:</b>
<%= join_tags(#post) %>
</p>
<h2>Comments</h2>
<%= render #post.comments %>
<h2>Add a comment:</h2>
<%= render "comments/form" %>
<br />
<%= link_to 'Edit Post', edit_post_path(#post) %> |
<%= link_to 'Back to Posts', posts_path %> |
Please fix this.
<%= render #post.comments %>
is incorrect. You must render partials, not objects.
I will think that your comment view in views/comments is named show.html.erb. Try something like that:
<%= #post.comments.map do |comment| %>
<%= render 'comments/show', comment: comment %>
<%= end %>
UPD: My mistake: it's correct, description in comments.
Which file is what you call 'comment view'? To be a able to render a collection like this
<%= render #post.comments %>
you need to place a comment template to views/comments/_comment.html.erb
Of course you can place it into another partial, e.g. 'posts/_comment.html.erb` but then you'll have to be more explicit:
<%= render :partial => 'posts/comment', :collection => #post.comments %>
(Mind there is an underscore in the file name, but not in the 'partial path' passed to render)

Resources