I am working on RailsGuides Tutorial (creating a blog app). When I run server and open: /posts/new
everything looks fine. But, when I try to create a post I get this error:
NoMethodError in Posts#show
Showing /home/darek/rails_projects/blog/app/views/posts/show.html.erb where line #3 raised:
undefined method `title' for nil:NilClass
Extracted source (around line #3):
1 <p> 2 <strong>Title:</strong> 3 <%= @post.title %> 4 </p> 5 <p>
In fact post is created, and I can see title and content at /posts But when I try to use show specific post I get this error. My first clue was to change line
<%= @post.title %>
to
<%= @post.try(:title) %>
Error is gone, but problem isn't solved.
When I try to show specific post I get Title, and Text forms empty. It is not what I want to see ;)
Ok, here is the code
Show.html.erb
<p> <strong>Title:</strong> <%= @post.title %> </p> <p> <strong>Text:</strong> <%= @post.text %> </p> <h2>Add a comment:</h2> <%= form_for([@post, @post.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 Post', edit_post_path(@post) %> | <%= link_to 'Back to Posts', posts_path %>
Posts_controller.rb
class PostsController < ApplicationController def new @post = Post.new end def index @posts = Post.all end def create @post = Post.new(params[:post].permit(:title, :text)) if @post.save redirect_to @post else render 'new' end end private def post_params params.require(:post).permit(:title, :text) 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, :text)) redirect_to @post else render 'edit' end end def destroy @post = Post.find(params[:id]) @post.destroy redirect_to posts_path end end
Rake Routes:
-VirtualBox:~/rails_projects/blog$ rake routes Prefix Verb URI Pattern Controller#Action post_comments GET /posts/:post_id/comments(.:format) comments#index POST /posts/:post_id/comments(.:format) comments#create new_post_comment GET /posts/:post_id/comments/new(.:format) comments#new edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit post_comment GET /posts/:post_id/comments/:id(.:format) comments#show PATCH /posts/:post_id/comments/:id(.:format) comments#update PUT /posts/:post_id/comments/:id(.:format) comments#update DELETE /posts/:post_id/comments/:id(.:format) comments#destroy posts GET /posts(.:format) posts#index POST /posts(.:format) posts#create new_post GET /posts/new(.:format) posts#new edit_post GET /posts/:id/edit(.:format) posts#edit post GET /posts/:id(.:format) posts#show PATCH /posts/:id(.:format) posts#update PUT /posts/:id(.:format) posts#update DELETE /posts/:id(.:format) posts#destroy root GET / welcome#index GET /posts/:id(.:format) posts#view DELETE /posts/:id(.:format) posts#destroy
Thanks for help and interest!
you have made your methods private. Remember where you put private keyword. all the methods below that, will become private, define your methods like this. private methods in end of the controller :
class PostsController < ApplicationController def new @post = Post.new end def index @posts = Post.all end def create @post = Post.new(params[:post].permit(:title, :text)) 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, :text)) redirect_to @post else render 'edit' end end def destroy @post = Post.find(params[:id]) @post.destroy redirect_to posts_path end private def post_params params.require(:post).permit(:title, :text) end end
Hope it will help. Thanks
I met the same problem as you when following the tutorial. And I checked my codes again then found the reason. In the posts_controller.rb file, you cannot put the private method in the middle of the codes, that means all the methods below (such as show, edit) will be private. Instead, put the private method at the bottom like this:
class PostsController < ApplicationController def new end def index @posts = Post.all end def create @post = Post.new(post_params) @post.save redirect_to @post end def show @post = Post.find(params[:id]) end private def post_params params.require(:post).permit(:title, :text) end end
Hope to solve your problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With