Having trouble with Rails Routing after form submission - ruby-on-rails

So I'm trying to make a form that would allow users to comment on specific posts. Im currently having trouble after the submit button is clicked. The entry does get put into the database, however it looks like im experiencing some routing problems.
Here is the URL I get redirected to:
"localhost:3000/groups/13/posts/62/comments"
I get the following error after submission:
No route matches {:action=>"show", :controller=>"groups"}
I ran rake routes to find this:
group GET /groups/:id(.:format) groups#show
Here is my comments controller:
class CommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment].merge({:user_id => current_user.id}))
redirect_to :action => :show, :controller => :groups
end
end
Here is my form for the comment:
<%= form_for([post.group, post, post.comments.build]) do |f| %>
  <p>
    <%= f.label :comment %><br />
    <%= f.text_area :body, :rows => 3, :cols => 55 %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
Does anyone have any ideas what might be wrong? Why is it redirecting to the url "localhost:3000/groups/13/posts/62/comments"
Thanks

I would do:
class CommentsController < ApplicationController
respond_to :html
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment]) do |comment|
comment.user = current_user # user_id shouldn't be an attr_accessible
end
respond_with #comment, location: group_path(#post.group)
end

Related

Ruby on Rails blog and adding comments to posts and editing and deleting comments

I'm working on a ROR blog and have encountered some issues along the way. I'm currently learning Rails and just feel completely lost with connecting all the pieces. I've been working on my comments section for days and was finally able to create comments on posts, but I can't edit or delete them. I also referenced the SO questions below but am still running into problems.
Add Comment to User and Post models (Ruby on Rails)
Here's my layout:
Comment model params:
body \ user_id \ post_id
Model associations:
user.rb
has_many :posts
has_many :comments
post.rb
belongs_to :user
has_many :comments
comment.rb
belongs_to :user
belongs_to :post
routes.rb:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
get '/' => 'users#index'
get '/posts' => 'posts#index'
post '/posts/create' => 'posts#new'
post '/posts/edit' => 'posts#edit'
get '/signin' => 'sessions#new', as: :new_session
post '/create-session' => 'sessions#create', as: :create_session
get 'signout' => 'sessions#destroy', as: :destroy_session
resources :users
resources :posts
resources :comments
end
comments controller:
class CommentsController < ApplicationController
def index
#comment = Comment.all
end
def new
user = session[:user_id]
#comment = Comment.new(post_id: params[:post_id])
#post = Post.find(params[:post_id])
end
def create
#comment = Comment.new(comment_params)
#comment.user_id = session[:user_id]
#postid = params[:id]
if #comment.save
flash[:notice] = "comment created."
redirect_to '/posts'
else
flash[:error] = "Error creating comment."
redirect_to '/posts'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#comment = Comment.find_by_id(params[:id])
#comment.update(comment_params)
flash[:notice] = "Comment updated."
redirect_to '/posts'
end
def destroy
#comment = Comment.find(params[:comment_id])
#comment.destroy
redirect_to '/posts'
end
private
def comment_params
params.require(:comment).permit(:body, :user_id, :post_id)
end
end
Posts show.html.erb page in views/posts folder:
<%# show all posts %>
<div id="single-post">
<h1>User - <%= #post.user.username %></h1>
<h2>Post - <%= #post.body %> </h2>
<%= link_to("Edit Post", edit_post_path(#post)) %>
</br>
<%= link_to("Delete Post", #post, method: 'delete') %>
</br>
<%= link_to("Add Comment", new_comment_path(post_id: #post.id)) %>
<%#<%= link_to("Edit Comment", edit_comment_path(post_id: #post.id, comment_id: #comment.id))%>
</div>
<h3><% #post.comments.reverse.each do |c| %> </h3>
<div id="single-comment">
<h4>Comment</h4>
<h5>From - <%= c.user.username %></h5>
<h6><%= c.body %> </h6>
</br>
<%= link_to("Edit Comment", edit_comment_path(#post.id)) %>
</br>
<%= link_to("Delete Comment", comment_path(#post.id), method: :delete) %>
</div>
<% end %>
</div>
new.html.erb form in views/comments folder
<div id="comment-form">
<%= form_for #comment do |f| %>
<%= f.label :body %>
<%= f.text_area :body, class: "text-area" %>
<%= f.hidden_field :post_id %>
<%= f.submit %>
<% end %>
</div>
Again I can add comments to posts. When I hover over the edit tag on the comment I'm seeing this: localhost:3000/comments/72/edit
I see this error when I click on edit
When I hover over the delete button I see this: localhost:3000/comments/72
I see this error when I click on delete
I'm at the point where I'm completely lost and feel I have tried everything possible but nothing seems to work. Please help! Here's the GitHub repo as well: https://github.com/angelr1076/rails-blog
The First argument in form cannot contain nil or be empty is telling you that #comment in <%= form_for #comment do |f| %> is nil. This is because in the edit action of your CommentsController you are setting #post instead of #comment.
Change this to be:
def edit
#comment = Comment.find(params[:id])
end
For deleting a comment, the Couldn't find Comment without an ID is telling you that the value you're passing to find is nil. This is because you're trying to use params[:comment_id] instead of params[:id]. Change the destroy action to:
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to '/posts'
end
Update:
Also as per your code, you should change edit and delete links to below
<%= link_to("Edit Comment", edit_comment_path(c)) %>
<%= link_to("Delete Comment", comment_path(c), method: :delete)
You are passing #post.id which is an id of post. Instead you should pass id of the comment using the block variable from your comments.each, noticing that the .id isn't needed here because it can be inferred by Rails.

no method error in posts#edit (take 2)

I posted a question before but my pictures weren't posting so now I am just gonna copy and paste the code. I am trying to make a blogging web app is Rails and I am in the "edit" phase and basically I am getting a no method error.
here is my controller code:
class PostsController < ApplicationController
def index
#post = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to show_path(#post)
end
def edit
#post = Post.find(params[:id])
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
and here is my edit.html.erb view page
This is the edit page for
<%= form_for #post do |f| %>
<%= f.label :title %>
<%= f.text_field :title %><br />
<%= f.label :body %>:
<%= f.text_field :body %><br />
I am guessing the problem is somewhere in there
here is my routes.rb:
Rails.application.routes.draw do
get "pages/about" => "pages#about"
get "pages/contact" => "pages#contact"
get "/posts" => "posts#index"
post "/posts" => "posts#create"
get "post/:id" => "posts#show", as: :show
get "/posts/new" => "posts#new"
get "post/:id/edit" => "posts#edit", as: :edit_post
end
Please help this is really frustrating :/
You need to add a line in your route file such as:
resources :posts
Also add a update method in your posts_controller:
def update
#post = Post.find(params[:id])
#post.update(post_params)
redirect_to #post
end
I hope this helps you !
When you use form_for like
<%= form_for #post do |f| %>
It's a shorthand for something that looks like this
<%= form_for #post, as: :post, url: post_path(#post), method: :patch, html: { class: "edit_post", id: "edit_post_45" } do |f| %>
So form_for expects that you have defined post_path helper, which you get when you use resources to define your routes, like this
resources :photos
Since you haven't defined your routes like that you don't have path helper that form_for expects and you get an error.
here is the error message:
NoMethodError in Posts#edit
Showing /Users/Hisham/Desktop/Rails_projects/myblog/app/views/posts/edit.html.erb where line #6 raised:
undefined method `post_path' for #<#:0x007fcdc84fd7b8>
Did you mean? posts_path
posts_new_path
font_path
Extracted source (around line #6):
4
5
6
7
8
9
<%= form_for #post do |f| %>
<%= f.label :title %>
<%= f.text_field :title %><br />
Rails.root: /Users/Hisham/Desktop/Rails_projects/myblog
Application Trace | Framework Trace | Full Trace
app/views/posts/edit.html.erb:6:in `_app_views_posts_edit_html_erb___871381459853082993_70260921890920'

action create couldn't be found for PostsController

I'm following a rails tutorial and need some help to proceed further. Problem is, once I fill out the form which has a title,body fields and hit submit, it has to redirect to the show.html.erb page instead it throws an error.
Error: The action 'create' could not be found for PostsController
routes.rb
Rails.application.routes.draw do
get "/pages/about" => "pages#about"
get "/pages/contact" => "pages#contact"
get "/posts" => "posts#index"
post "/posts" => "posts#create"
get "/posts/show" => "posts#show", as: :show
get "/posts/new" => "posts#new"
end
posts_controller_tests.rb
require 'test_helper'
class PostsControllerTest < ActionController::TestCase
def index
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to show_path
end
def show
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
new.html.erb
<h1>Create a new blog post</h1>
<div class="form">
<%= form_for Post.new do |f| %>
<%= f.label :title %>: <br>
<%= f.text_field :title %> <br> <br>
<%= f.label :body %>: <br>
<%= f.text_area :body %> <br> <br>
<%= f.submit %>
<% end %>
</div>
Any help on this would be appreciated.
Note: You are using posts_controller_tests.rb not posts_controller.rb. You are putting your controller code in test controller.
Try to move the code in app/controllers/posts_controller.rb:
class PostsController < ApplicationController
def index
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to show_path
end
def show
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
Your create action always redirects you to the show action. It doesn't matter if your model was saved or not.
You have to check if the model was saved or not:
def create
#post = Post.new(post_params)
if #post.save
flash[:success] = 'Successfully saved'
redirect_to #post
else
render 'new'
end
end
If it wasn't saved, it renders the new action again.
Change your routes.rb to this:
Rails.application.routes.draw do
get "/pages/about" => "pages#about"
get "/pages/contact" => "pages#contact"
resources :posts
end
Moreover you should inherit your controller from ActionController::Base
so change first line of your controller to
class PostsController < ActionController::Base
and move the controller to app/controllers/posts_controller.rb

Rails 4 RoutingError: No Route Matches [POST]

I'm working through a small exercise while learning Rails 4, but running into a routing error while trying to update an object. I keep getting an error message: No route matches [POST] "/movies/1/edit" but can't see where my code is not correct:
my movies_controller.rb
class MoviesController < ApplicationController
def index
#movies = Movie.all
end
def show
#movie = Movie.find(params[:id])
end
def new
#movie = Movie.new
end
def create
#movie = Movie.create(movie_params)
if #movie.save
redirect_to "/movies/#{#movie.id}", :notice => "Your movie was saved!"
else
render "new"
end
end
def edit
#movie = Movie.find(params[:id])
end
def update
#movie = Movie.find(params[:id])
if #movie.update_attributes(params[:movie])
redirect_to "/movies"
else
render "edit"
end
end
def destroy
end
private
def movie_params
params.require(:movie).permit(:name, :genre, :year)
end
end
Here's my edit.html.erb
<h1>Now Editing:</h1>
<h3><%= #movie.name %></h3>
<%= form_for #movie.name do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<br>
<%= f.label :genre %>
<%= f.text_field :genre %>
<br>
<%= f.label :year %>
<%= f.number_field :year %>
<br>
<%= f.submit "Update" %>
and the routes.rb file:
MovieApp::Application.routes.draw do
get "movies" => "movies#index"
post "movies" => "movies#create"
get "movies/new" => "movies#new"
get "movies/:id" => "movies#show"
get "movies/:id/edit" => "movies#edit"
put "movies/:id" => "movies#update"
end
last, here's the output from running rake routes:
Prefix Verb URI Pattern Controller#Action
movies GET /movies(.:format) movies#index
POST /movies(.:format) movies#create
movies_new GET /movies/new(.:format) movies#new
GET /movies/:id(.:format) movies#show
GET /movies/:id/edit(.:format) movies#edit
PUT /movies/:id(.:format) movies#update
form_for #movie.name should be form_for #movie. I can't tell what's going on, but I suspect this is somehow giving you a <form action="">.
Your error message shows that you are sending a post request to the edit url.
No route matches [POST] "/movies/1/edit"
Whereas in the route you have specified a get request.
get "movies/:id/edit" => "movies#edit"
I believe that is somehow causing the problem and so you could change the request to post.
post "movies/:id/edit" => "movies#edit"
in index file if you are using
button_to 'Edit', edit_movie_path(movie)
change it to
link_to 'Edit', edit_movie_path(movie)
because button send it as POST but the link will send it as GET.

Creating an object from the show action of another object in Rails

So I have a fairly typical blog application with posts and comments.
Each comment belongs to one post
A post can have many comments.
Basically I want to add a form for comments to the show action for posts, without having post_id under attr_accessible in the comment model.
In my posts controller I have:
def show
#post = Post.find(params[:id])
#poster = "#{current_user.name} #{current_user.surname} (#{current_user.email})"
#comment = #post.comments.build( poster: #poster )
end
I'm not entirely sure what I should be doing in the comments controller (I'm not confident that the code above is right either if I'm honest). At the moment I have:
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:post])
if #comment.save
redirect_to #post, notice: "Comment posted"
else
redirect_to #post, error: "Error!"
end
end
My routes:
resources :comments
resources :posts do
resources :comments
end
and finally the form:
<%= form_for #post.comments.build do |f| %>
<%= f.label :content, "WRITE COMMENT" %>
<%= f.text_area :content, rows: 3 %>
<%= f.hidden_field :post_id, value: #post.id %>
<%= f.submit "Post" %>
<% end %>
The problem here is that I have no way of passing my post_id from the show action of the posts controller to the create action of the comments controller. Any help is much appreciated. Thank you in advance!
Your posts controller looks fine... but assuming your routes looks like
resources :posts do
resources :comments
end
then your CommentsController#create should/could look like:
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment])
if #comment.save
redirect_to #post, notice: "Comment posted"
else
redirect_to #post, error: "Error!"
end
end
And your form:
<%= form_for [#post, #comment] do |f| %>
<%= f.hidden_field :poster, value: #poster %>
<%= f.label :content, "WRITE COMMENT" %>
<%= f.text_area :content, rows: 3 %>
<%= f.submit "Post" %>
<% end %>
I will assume that your post model has_many comments and comment belongs_to post
than you in your routes file you can do something like this
resources :posts do
resources :comments
end
this will give you a url schem such as
/posts/:post_id/comments , allowing you to always have post_id of the comment parrent
The URL for your show post should be like post/show/(:id).
Now, in the comment form, you can place a hidden field, with value of params[:id].
hidden_field(:post_id, :value => params[:id])
When you submit your form, you can get the value of post_id using the hidden field.
def create
#comment = Comment.new(params[:comment])
#comment.post_id = params[:post_id]
if #comment.save
flash[:notice] = 'Comment posted.'
redirect_to post_path(#comment.post_id)
else
flash[:notice] = "Error!"
redirect_to post_path(#comment.post_id)
end
end

Resources