Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"undefined method `title' for nil:NilClass" Rails Guides Tutorial

Tags:

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!

like image 663
szatan Avatar asked Jul 23 '13 12:07

szatan


2 Answers

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

like image 52
Rails Guy Avatar answered Nov 12 '22 08:11

Rails Guy


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.

like image 25
Fred Wu Avatar answered Nov 12 '22 08:11

Fred Wu