spacemonkey
spacemonkey

Reputation: 2550

Ruby on Rails error showing when posting

I am a beginner in RoR (8 hours old) and was faced with a problem I can't get past. The tutorial presented in the get started guide on their site goes through setting a post entry example. I get the following error:

NoMethodError in Posts#show
Showing /Users/khalidalghamdi/blog/app/views/posts/show.html.erb where line #3 raised:

undefined method `title' for nil:NilClass
Extracted source (around line #3):
1
2
3
4
5
6

  <p>
    <strong>Title:</strong>
    <%= @post.title %>
  </p>

  <p>

Rails.root: /Users/khalidalghamdi/blog

Application Trace | Framework Trace | Full Trace
app/views/posts/show.html.erb:3:in `_app_views_posts_show_html_erb__4427112910992919114_2164032300'
Request

Parameters:

{"id"=>"4"}

and this is the tutorial link http://guides.rubyonrails.org/getting_started.html and I am following section 5.6. It is not showing the posted details in the show.html.erb page. What am I doing wrong?

Update: Controller code:

class PostsController < ApplicationController
    def new

    end

    def create
        @post = Post.new(post_params)

        @post.save
        redirect_to @post
    end

    private
        def post_params
            params.require(:post).permit(:title, :text)
        end


    def show
        @post = Post.find(params[:id])
    end


end

Upvotes: 1

Views: 90

Answers (2)

Kirti Thorat
Kirti Thorat

Reputation: 53028

Set the instance variable @post in PostsController#show action. Currently, @post variable is set as nil so you are getting undefined method 'title' for nil:NilClass error.

Remove the show action from private. Its not getting called as you have made it private. Hence @post is not set.

For example: (As you haven't shared the code, I am giving an example)

class PostsController < ApplicationController
  ## ...
  def show
    @post = Post.find(params[:id])
  end
  ## ...

   private  
   def post_params
      params.require(:post).permit(:title, :text)
   end
end

Also, a better approach is to add a before_action in your controller where you can set the @post variable in order to avoid redundant code across multiple actions. This makes your code DRY too.

For example:

class PostsController < ApplicationController
  ## set_post would be called before show, edit, update and destroy action calls only
  before_action :set_post, only: [:show, :edit, :update, :destroy]
  ## ...

  def show
    ## No need to set @post here
  end

  ## ..
   private  

   def set_post
     @post = Post.find(params[:id])
   end

   def post_params
      params.require(:post).permit(:title, :text)
   end  
 end

Upvotes: 7

Pavan
Pavan

Reputation: 33542

Seeing your controller code,you have defined your show action after the private method.

Put it above the private method like this

class PostsController < ApplicationController
    def new

    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

Note:

Any method defined after the private method is also treated as private.

Upvotes: 1

Related Questions