Reputation: 2550
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
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
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