I have books, with chapters nested underneath, with questions for each chapter nested within the chapters, and comments nested in the questions.
When I click on new chapter on the books page how do I get it to save to the book its associated with, and how do I get the books#show page to loop through all the chapter titles (with links to each chapters show page).
This is the error: undefined method `title' for nil:NilClass. Referring to this file: Users/bardiap/saasapp/app/views/books/show.html.erb
<div class="homepage">
<h1><%= #book.title %></h1>
<%= link_to 'New chapter', new_book_chapter_path(#book, #chapter) %>
<% #chapters.each do |chapter| %>
<h3><%= link_to chapter.title, chapter %></h3>
<% end %>
<p>
<%= link_to 'Edit', edit_book_path(#book) %> |
<%= link_to 'Destroy', book_path(#book),
method: :delete,
data: { confirm: 'Are you sure?' } %> |
<%= link_to 'Back', books_path %> |
</p>
</div>
Here is my books and chapters controllers:
class BooksController < ApplicationController
def show
#book = Book.find(params[:id])
#chapters = Chapter.where(book_id: #book.id).order("created_at ASC")
end
def index
#books = Book.all
end
def new
#book = Book.new
end
def edit
#book = Book.find(params[:id])
end
def create
#book = Book.new(book_params)
if #book.save
redirect_to #book
else
render 'new'
end
end
def update
#book = Book.find(params[:id])
if #book.update(book_params)
redirect_to #book
else
render 'edit'
end
end
def destroy
#book = Book.find(params[:id])
#book.destroy
redirect_to books_path
end
private
def book_params
params.require(:book).permit(:title,:text,:author)
end
end
Chapter
def show
#chapter = Chapter.find(params[:id])
#questions = question.where(chapter_id: #chapter.id).order("created_at ASC")
end
def index
#chapters = Chapter.all
end
def new
#chapter = Chapter.new
end
def edit
#chapter = Chapter.find(params[:id])
end
def create
#chapter = Chapter.new(chapter_params)
if #chapter.save
render 'books/show'
else
render 'books/show'
end
end
def update
#chapter = Chapter.find(params[:id])
if #chapter.update(chapter_params)
redirect_to #chapter
else
render 'edit'
end
end
def destroy
#chapter = Chapter.find(params[:id])
#chapter.destroy
redirect_to chapters_path
end
private
def chapter_params
params.require(:chapter).permit(:title, :text)
end
end
Here are the models and routes
class Book < ApplicationRecord
has_many :chapters
validates :title, presence: true,
length:{minimum: 5}
end
class Chapter < ApplicationRecord
has_many :questions
belongs_to :book
validates :title, presence: true,
length:{minimum: 5}
end
Routes
Rails.application.routes.draw do
devise_for :users
root to: 'pages#home'
get 'about', to: 'pages#about'
get 'terms', to: 'pages#terms'
get 'privacy', to: 'pages#privacy'
resources :contacts, only: :create
resources :podcasts
resources :books do
resources :chapters, shallow: true
end
resources :chapters do
resources :questions, shallow: true
end
resources :questions do
resources :comments, module: :questions, shallow: true
end
resources :users do
resource :profile
resources :comments
end
get 'contact-us', to: 'contacts#new', as: 'new_contact'
get 'podcast', to: 'pages#podcast'
resources :essays do
resources :comments, module: :essays, shallow: true
end
end
And views:
chapters/_form.html.erb
<%= form_for [#book, #chapter] do |form| %>
<p>
<%= form.label :title %><br>
<%= form.text_field :title %>
</p>
<p>
<%= form.label :text %><br>
<%= form.text_area :text %>
</p>
<p>
<%= form.submit "Submit" %>
</p>
<% end %>
chapters/index.html.erb
<div class="homepage">
<button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab">
<i class="material-icons"><%= link_to "add", new_chapter_path%></i>
</button>
<div class="mdl-grid">
<% #chapters.each do |chapter| %>
<div class="mdl-cell mdl-cell--4-col">
<div class="demo-card-event mdl-card mdl-shadow--2dp">
<div class="mdl-card__title mdl-card--expand">
<h4>
<%=chapter.title%>
</h4>
</div>
<div class="mdl-card__actions mdl-card--border">
<%=link_to 'VIEW BOOK',chapter_path(chapter), class: "mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect"%>
<div class="mdl-layout-spacer"></div>
<i class="material-icons">chapter</i>
</div>
</div>
</div>
<% end %>
</div>
<% #chapters.each do |chapter| %>
<%= link_to 'Edit', edit_chapter_path(chapter) %> |
<%= link_to 'Destroy', chapter_path(chapter),
method: :delete,
data: { confirm: 'Are you sure?' } %>
<% end %>
<br><br><br><br><br>
</div>
chapters/show.html.erb
<div class="homepage">
<h3><%= #chapter.title %></h3>
<h5><%= #chapter.text %></h5>
<p>
<%= link_to 'Edit', edit_book_path(#book) %> |
<%= link_to 'Destroy', book_path(#book),
method: :delete,
data: { confirm: 'Are you sure?' } %> |
<%= link_to 'Back', books_path %> |
</p>
</div>
Where am I going wrong, and is there other things I can do to make my code work better.
To create a new Chapter in a Book, in books/show:
<%= link_to 'New chapter', new_book_chapter_path(#book) %>
(No need to pass the chapter, as it will be created). Then, in ChaptersController#new:
def new
#book = Book.find_by(id: params[:book_id]
if #book
#chapter = #book.chapters.build
end
end
You can also change BooksController#show
def show
#book = Book.find_by(id: params[:id])
if #book
#chapters = #book.chapters.order("created_at ASC")
end
end
Related
screenshot
Currently I'm using acts_as_votable gem along with bootstrp-sass gem,I want to upvote the post when glyphicon icon is clicked, instead it throws me above errors.
This is my posts_controller.rb file
class PostsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
def search
if params[:search].present?
#posts = Post.search(params[:search])
else
#posts = Post.all
end
end
def index
#posts = Post.all.order('created_at DESC')
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def show
#post = Post.find(params[:id])
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :date, :time, :location))
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to root_path
end
def upvote
#post.upvote_by current_user
redirect_to :back
end
private
def post_params
params.require(:post).permit(:title, :date, :time, :location)
end
end
This is my show.html.erb file
<div id="post_content">
<h1 class="title">
<%= #post.title %>
</h1>
<p class="date">
Submitted <%= time_ago_in_words(#post.created_at) %> Ago
<% if user_signed_in? %>
| <%= link_to 'Edit', edit_post_path(#post) %>
| <%= link_to 'Delete', post_path(#post), method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
</p>
<p class="date">
<%= #post.date %>
</p>
<p class="time">
<%= #post.time %>
</p>
<p class="location">
<%= #post.location %>
</p>
<div id="comments">
<div class="btn-group pull-left">
<%= link_to like_post_path(#post), method: :put, class: "btn btn-default" do %>
<span class="glyphicon glyphicon-heart"></span>
<%= #post.get_upvotes.size %>
<% end %>
</div>
<h2><%= #post.comments.count %> Comments</h2>
<%= render #post.comments %>
<h3>Add a comment:</h3>
<%= render "comments/form" %>
</div>
This is my routes.rb file
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
resources :posts do
resources :comments
collection do
get 'search'
end
member do
put "like", to: "posts#upvote"
end
end
root "posts#index"
get '/about', to: 'pages#about'
end
And this is my post model
class Post < ActiveRecord::Base
acts_as_votable
searchkick
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :date, :time, :location, presence: true
belongs_to :user
end
NoMethodError in PostsController#upvote undefined method `upvote_by'
for nil:NilClass
The error is because you didn't initialized #post in upvote method so #post is nil
def upvote
#post = Post.find(params[:id])
#post.upvote_by current_user
redirect_to :back
end
Hi there I want to add a destroy action in post#show view I think I have creates the environment but when I place this code with a condition I have a message error.
<% if #user.comment == current_user %>
<% link_to #post_comment_path(post_id: #post.id, id: comment.id), method: :delete, data: { confirm: "Are you sure?" } do %>
<i class="fa fa-trash"></i>
<% end %>
<% end %>
I created a partial in post show#view which names _comments.html.erb
here it is
<p class="text-center">Poster un commentaire</p>
<%= simple_form_for [post, post.comments.new] do |f| %>
<%= f.error_notification %>
<%= f.input :content, label: "Commentaire"%>
<%= f.submit "Envoyer", class: "btn btn-primary" %>
<% end %>
and it render like that <%= render 'comments' %>
and above the partial (in post show#view) I do an iteration like that
<ul class="list-unstyled">
<% #post.comments.each do |comment| %>
<li>
<p><% comment.content %></p>
<% end %>
</li>
</ul>
But nothing appears when I create a new message, I don't userstand why.
I give your more code details
post.rb
has_many :comments, dependent: :destroy
comment.rb
belongs_to :user
belongs_to :post
The route is:
resources :posts do
resources :categories
resources :comments
end
Comments controller is
class CommentsController < ApplicationController
before_action :set_post
def create
#comment = #post.comments.build(comment_params)
#comment.user_id = current_user.id
if #comment.save
flash[:success] = "You commented the hell out of that post!"
redirect_to :back
else
flash[:alert] = "There is a problem with your comment"
render root_path
end
end
def destroy
#comment = #post.comments.find(params[:id])
#comment.destroy
flash[:success] = "Comment deleted :("
redirect_to root_path
end
private
def set_post
#post = Post.find(params[:post_id])
end
def comment_params
params.require(:comment).permit(:content, :post_id, :user_id)
end
end
Thank you so much for your help.
Your link_to erb code needs an equals sign for it to actually display
<%= link_to post_comment_path(post_id: #post.id, id: comment.id), method: :delete, data: { confirm: "Are you sure?" } do
I am building a blog application in which I am trying to have two links in that two links I am sending the post_id to my update controller but it is giving me error .And I want to collect that post_id in my update controller and want to check the "status"(Status is basically the column name in my posts table and by default my status column has a status of pending ) .So when admin click on approve the status of column should change to approve and when admin click on decline the status of column should change to decline also user post should be deleted .Admin can access all the users posts whereas user can access his only post
posts_controller
class PostsController < ApplicationController
before_action :authenticate_user!
def index
#posts = Post.user_post(current_user).order('created_at DESC').paginate(:page => params[:page], :per_page => 5)
end
def new
#post = Post.new
end
def show
#post=find_params
end
def create
#post = Post.new(post_params)
#post.user = current_user
if #post.save
Post.upload(params[:post][:files],#post.id)
redirect_to #post
else
render 'new'
end
end
def edit
#post = find_params
puts "cccccccccc#{params[:commit]}"
Post.up(#post.id,params[:commit])
end
def update
#post = find_params
if #post.update(post_params)
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = find_params
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body)
end
def find_params
Post.find(params[:id])
end
end
posts/_form.html.erb
<%= form_for #post,html: { multipart: true } do |f| %>
<% if #post.errors.any? %>
<div id="errors">
<h2><%= pluralize(#post.errors.count, "error") %> prevented this post from saving:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label :title %><br>
<%= f.text_field :title %><br>
<br>
<%= f.label :body %><br>
<%= f.text_field :body %><br>
<br>
<!-- if you want to upload multiple files at a time -->
<%= f.label :files %><br>
<%= f.file_field :files,:multiple => true %><br>
<br>
<%= f.submit %>
<br>
<% end %>
posts/edit.html.erb
<div id="page_wrapper">
<h1>Edit Post</h1>
<%= render 'form' %>
<br>
</div>
migration
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :body
t.integer :user_id
t.string :status
t.timestamps
end
end
end
posts/show.html.erb
<div id="post_content">
<h1 class="title"><%= #post.title %></h1>
<p class="date">
Submitted <%= time_ago_in_words(#post.created_at) %> Ago
<% if user_signed_in? %>
<%= link_to 'Edit', edit_post_path(#post) %> |
<%= link_to 'Delete', post_path(#post), method: :delete, data: { confirm: 'Are you sure?' } %>
<%= link_to "approve",[:edit,#post] %>
<%= link_to "decline",[:edit,#post] %>
<% end %>
</p>
<p class="body"><%= #post.body %></p>
<div id="comments">
<h2><%= #post.comments.count %> Comments</h2>
<%= render #post.comments %>
<h3>Add a comment:</h3>
<%= render "comments/form" %>
</div>
</div>
post.rb
class Post < ActiveRecord::Base
has_many :documents
has_many :comments, dependent: :destroy
belongs_to :user
validates :title, presence: true, length: {in: 5..15}
validates :body, presence: true,length: {in: 5..200}
def self.up(id,params)
puts "aaaaaaaa#{id}"
puts "bbbbbbbbbbbbb#{params}"
end
def self.user_post(id)
role = User.find_role(id)
if role == 'admin'
Post.all
elsif role == 'user'
Post.where(user_id: id)
elsif role == 'developer'
Post.where(user_id: id)
end
end
def self.icon(extension)
case extension
when 'pdf'
EXTENSION[1]['pdf']
when 'png' || 'jpg' || 'jpeg'
EXTENSION[0]['png']
when 'doc' || 'odt'
EXTENSION[2]['doc']
end
end
####limit to upload files not more than ######
def self.upload(files,post_id)
files.each do |file|
#file_extension=file.content_type.split('/')[1]
doc = Document.new(document: file,post_id: post_id )
#save is a method which will save the content in the database
doc.save!
end
end
end
routes.rb
Rails.application.routes.draw do
root "posts#index"
devise_for :users
resources :posts do
resources :comments
end
resources :uploads
end
There are a bunch of problems with your code.. I'll not try to address them all but the specific problem you are facing..
first you need to generate path for both approve and decline action..
resources :posts do
patch '/approve' => 'posts#approve', as: :approve #posts_approve_path(post) is the route helper for this
patch '/decline' => 'posts#decline', as: :decline #posts_decline_path(post) is the route helper for this
resources :comments
end
this will generate the required routes.
now inside your view wherever you want to approve and decline.
<%= link_to "approve",posts_approve_path(#post.id), method: :patch %>
<%= link_to "decline",posts_decline_path(#post.id), method: :patch %>
In your controller you need to modify find_params as the generated routes will pass :posts_id as the :id param.
def find_params
id = params[:id] || params[:posts_id]
Post.find(id)
end
Now in your controller add 2 new methods to implement the functionality.
def approve
#post = find_params
#post.update_attribute(:status, 'approved') if #post.present?
redirect_to post_path(#post), notice: 'Post approved'
end
def decline
#post = find_params
#post.destroy if #post.present?
redirect_to post_path(#post), notice: 'Post deleted'
end
I have a Post model, and a Comment model that belongs to Post. I was able to display the Post in the home view corresponding to the home controller and home action and the User/show view. Thus, in the home and user views, the posts are listed in order of creation time. I was also able to have a post form in both the user and home views and a comment form in the home and user views.
The problem arises when I try to display the comment underneath each displayed Post in the home and user views. How can I list the comments associate with each post under the post in the home and user views ?
How do I make sure the comments in the databased are listed under the corresponding post ?
Here is my comments controller:
class CommentsController < ApplicationController
def index
#comments =Comment.all.paginate(page: params[:page])
end
def show
#comment = Comment.find(params[:id])
#post = #Comment.post
end
def new
end
def create
#comment = Comment.new(comment_params)
if #comment.save
flash[:success] = "Comment created"
redirect_to :back
else
render 'new'
end
end
def edit
#comment = Comment.find(params[:id])
end
def update
#comment = comment.find(params[:id])
if #comment.update_attributes(comment_params)
flash[:success] = "Comment updated"
redirect_to #comment.post
else
render 'edit'
end
end
def destroy
Comment.find(params[:id]).destroy
flash[:success] = "Comment deleted"
redirect_to users_url
end
private
def comment_params
params.require(:comment).permit(:author_name, :body)
end
end
Here is my home view: app/views/home/home.html.erb:
<% if logged_in? %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= render 'shared/user_info' %>
</section>
<hr/>
<br/>
<section class="stats">
<%= render 'shared/stats' %>
</section>
<section class="post_form">
<%= render 'shared/post_form' %>
</section>
</aside>
<div class="col-md-8">
<h3>Post Feed</h3>
<%= render 'shared/feed' %>
</div>
</div>
<% else %>
<div class="center jumbotron">
<h1>Welcome to the Unstarv website</h1>
<h2>
Please sign up now to use this site
<%= link_to "Sign Up", signup_path =%>
now.
</h2>
<%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
</div>
<%= link_to image_tag("rails.png", alt: "unstarv logo"), '#' %>
<% end %>
And here is my home controller:
class HomeController < ApplicationController
def home
if logged_in?
#post = current_user.posts.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
def about
end
def privacy
end
def terms
end
end
And here is my Post model, the relevant part:
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments
default_scope -> { order(created_at: :desc) }
mount_uploader :picture, PictureUploader
end
The relevant part of my User model:
class User < ActiveRecord::Base
attr_accessor :remember_token
before_save { self.email = email.downcase }
has_many :posts, dependent: :destroy
has_many :comments
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
validates :username, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }, allow_blank: true
def feed
following_ids = "SELECT followed_id FROM relationships WHERE follower_id = :user_id"
Post.where("user_id IN (#{following_ids}) OR user_id = :user_id", user_id: id)
end
end
And here is my Comment model:
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
default_scope -> { order(created_at: :desc) }
end
And here is the post controller:
class PostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
#comment = Comment.new
#comment.post_id = #post.id
#comments = #post.comments.all
end
def new
#post = Post.new
end
def create
#post = current_user.posts.build(post_params)
if #post.save
flash[:success] = "Post created!"
redirect_to root_url
else
#feed_items = []
render 'home/home'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
#post.update(post_params)
flash.notice = "Post '#{#post.title}' Updated!"
render 'home/home '
end
def update
#post = Post.find(params[:id])
#post.update(post_params)
flash.notice = "Post '#{#post.title}' Updated!"
redirect_to root_url
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.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, :body, :picture)
end
end
Here is my app/views/post/_post.html.erb file,
<li id="post-<%= post.id %>">
<span class="user"><%= link_to post.user.username, post.user %></span>
<span class="content">
<%= post.title %>
<%= post.body %>
<%= image_tag post.picture.url if post.picture? %>
</span>
<span class="timestamp">
Posted <%= time_ago_in_words(post.created_at) %> ago.
<% if current_user?(post.user) %>
<%= link_to "delete", post, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</span>
<section>
<h2>Your Comments here</h2>
<h3>Post a Comment</h3>
<h3>Post a Comment</h3>
<%= render 'shared/comment_form' %>
<% post.comments.all.each do |comment| %>
<h4><small>Comment by</small> <%= comment.post.user.username %></h4>
<p class="comment"><%= comment.body %></p>
<p><small>Posted <%= distance_of_time_in_words(Time.now, comment.created_at) %> ago</small></p>
<br/>
<%end%>
</li>
And here is my app/views/shared/comment_form_html.erb , which works fine:
<%= form_for [ post, post.comments.build] do |f| %>
<p>
<%= f.label :body, "Your Comment" %><br/>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit 'Submit' . method="post", class: 'btn btn-primary' %>
</p>
<% end %>
Here is my app/views/posts/_post.html.erb
<li id="post-<%= post.id %>">
<span class="user"><%= link_to post.user.username, post.user %></span>
<span class="content">
<%= post.title %>
<%= post.body %>
<%= image_tag post.picture.url if post.picture? %>
</span>
<span class="timestamp">
Posted <%= time_ago_in_words(post.created_at) %> ago.
<% if current_user?(post.user) %>
<%= link_to "delete", post, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</span>
<h2>Comments</h2>
<h3>Post a Comment</h3>
<%= render 'shared/comment_form', post: post %>
<h3>Comments (<%= post.comments.size %>)</h3>
<% post.comments.each do |comment| %>
<h4><small>Comment by</small> <%= comment.post.user.username %></h4>
<p class="comment"><%= comment.body %></p>
<p>Posted <%= distance_of_time_in_words(Time.now, comment.created_at) %> ago</p>
</li>
<br/>
<%end%>
Thanks a lot for your help !!!!
The issue is related in how you are creating the comments.
With the actual code, the comment does not belong to any post so in your comments_controller change create action to something like:
def create
post = Post.find(params[:post_id])
#comment = post.comments.build(comment_params)
if #comment.save
flash[:success] = "Comment created"
redirect_to :back
else
render 'new'
end
end
I was following this tutorial http://www.sitepoint.com/nested-comments-rails/ to implement nested comments for an image board. It worked fine until I made "comments" belong to "boards" and then had to nest my routes.
Here are my routes:
Rails.application.routes.draw do
root "boards#index"
devise_for :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end
resources :boards do
resources :comments
get '/comments/new/(:parent_id)', to: 'comments#new', as: :new_comment
get '/comments/(:parent_id)', to: 'comments#destroy', as: :delete_comment
get '/comments/edit/(:parent_id)', to: 'comments#edit', as: :edit_comment
end
end
Here is my form:
<%= form_for [#board, #comment] do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :parent_id %>
<div class="form-group">
<% if #comment.parent_id == nil %>
<%= f.label :title %>
<%= f.text_field :title, class: 'form-control' %>
<% else %>
<% nil %>
<% end %>
</div>
<div class="form-group">
<%= f.radio_button(:user_id, current_user.id) %>
<%= f.label(:user_id, "I want to post as myself") %>
<%= f.radio_button(:user_id, nil) %>
<%= f.label(:user_id, "I want to post anonymously") %>
</div>
<div class="form-group">
<%= f.label :content %>
<%= f.text_area :content, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= f.label :image %>
<%= f.file_field :image %>
</div>
<%= f.submit class: 'btn btn-primary' %>
<% end %>
And here is my controller:
class CommentsController < ApplicationController
def index
#comments = Comment.hash_tree
end
def new
#comment = Comment.new(parent_id: params[:parent_id])
end
def edit
#comment = Comment.find(params[:parent_id])
end
def create
if params[:comment][:parent_id].to_i > 0
parent = Comment.find_by_id(params[:comment].delete(:parent_id))
#comment = parent.children.build(comment_params)
else
#comment = Comment.new(comment_params)
end
if #comment.save
redirect_to root_url
else
render 'new'
end
end
def update
#comment = Comment.find(params[:id])
if #comment.update(comment_params)
redirect_to #comment
else
render 'edit'
end
end
def make_parent
#comment.parent_id = nil
#comment.save
end
def destroy
#comment = Comment.find(params[:parent_id])
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url }
end
authorize! :destroy, #comment
end
private
def comment_params
params.require(:comment).permit(:title, :content, :user_id, :image)
end
end
I've tried setting a custom route in the form, this gets the form to at least appear, however when you hit the submit button it returns 'No route matches [POST] "/boards/1/comments/new"'. If I got to the controller and then change the corresponding "get" to a "post" then it causes the form to just reappear after pressing submit and nothing is added to the database. I've also experimented with shallow nesting my routes as per my instructors advice but this didn't work.
Your association between boards and comments must be:
board.rb
has_many :comments
comment.rb
belongs_to :user
routes.rb
resources :boards do
resources :comments, only: [:new, :edit, :destroy]
end
this will create a route
new_board_comment GET /boards/:board_id/comments/new(.:format) comments#new
edit_board_comment GET /boards/:board_id/comments/:id/edit(.:format) comments#edit
board_comment DELETE /boards/:board_id/comments/:id(.:format) comments#destroy