I'm new to rails and recently noticed an error on one of my show views while working on a project for school. The error has to do with the name method not being defined yet I'm unsure how to remedy this. Help would be much appreciated! The error I receive is:
NoMethodError in Topics#show
Showing /Users/Jason/code/bloccit/app/views/topics/show.html.erb where line #17 raised:
undefined method `name' for nil:NilClass
<%= link_to post.title, [@topic, post] %>
</h4>
<small>
submitted <%= time_ago_in_words(post.created_at) %> ago by <%= post.user.name %><br>
<%= post.comments.count %> Comments
</small>
</div>
Relevant files include..
topics/show.html.erb
<h1><%= @topic.name %></h1>
<% if policy(@topic).update? %>
<%= link_to "Edit Topic", edit_topic_path, class: 'btn btn-success' %>
<% end %>
<div class="row">
<div class="col-md-8">
<p class="lead"><%= @topic.description %></p>
<% @posts.each do |post| %>
<div class="media">
<div class="media-body">
<h4 class="media-heading">
<%= link_to post.title, [@topic, post] %>
</h4>
<small>
submitted <%= time_ago_in_words(post.created_at) %> ago by <%= post.user.name %><br>
<%= post.comments.count %> Comments
</small>
</div>
</div>
<% end %>
</div>
<div class="col-md-4">
<% if policy(Post.new).create? %>
<%= link_to "New Post", new_topic_post_path(@topic), class: 'btn btn-success' %>
<% end %>
</div>
</div>
post.rb
class Post < ActiveRecord::Base
has_many :comments
belongs_to :user
belongs_to :topic
default_scope { order('created_at DESC') }
end
topic.rb
class Topic < ActiveRecord::Base
has_many :posts
end
posts_controller.rb
class PostsController < ApplicationController
def show
@post = Post.find(params[:id])
@topic = Topic.find(params[:topic_id])
authorize @post
end
def new
@topic = Topic.find(params[:topic_id])
@post = Post.new
authorize @post
end
def create
@topic = Topic.find(params[:topic_id])
@post = Post.new(post_params)
@post.topic = @topic
authorize @post
if @post.save
flash[:notice] = "Post was saved."
redirect_to [@topic, @post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
def edit
@topic = Topic.find(params[:topic_id])
@post = Post.find(params[:id])
authorize @post
end
def update
@topic = Topic.find(params[:topic_id])
@post = Post.find(params[:id])
authorize @post
if @post.update_attributes(post_params)
flash[:notice] = "Post was updated."
redirect_to [@topic, @post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
topics_controller.rb
class TopicsController < ApplicationController
def index
@topics = Topic.all
authorize @topics
end
def new
@topic = Topic.new
authorize @topic
end
def show
@topic = Topic.find(params[:id])
@posts = @topic.posts
authorize @topic
end
def create
@topic = Topic.new(topic_params)
authorize @topic
if @topic.save
redirect_to @topic, notice: "Topic was saved successfully."
else
flash[:error] = "Error creating topic. Please try again."
render :new
end
end
def edit
@topic = Topic.find(params[:id])
authorize @topic
end
def update
@topic = Topic.find(params[:id])
authorize @topic
if @topic.update_attributes(topic_params)
redirect_to @topic, notice: "Topic was updated successfully."
else
flash[:error] = "Error saving topic. Please try again."
render :edit
end
end
private
def topic_params
params.require(:topic).permit(:name, :description, :public)
end
end
you are not setting the user
when creating a post, Im not sure about the implementation of your authorize
method. However,
it should be something like
#assuming you have the user as `current_user`
class PostsController < ApplicationController
...
def create
@topic = Topic.find(params[:topic_id])
@post = Post.new(post_params)
@post.user = current_user
@post.topic = @topic
...
end
...
end
your post has no user. you have to check why your post not saved the user. to prevent this error you have to check, user exist in post.
i would prefer to use delegate
and follow the law of demeter
post.rb
class Post < ActiveRecord::Base
has_many :comments
belongs_to :user
belongs_to :topic
delegate :name, :to :user, allow_nil: true, prefix: true
default_scope { order('created_at DESC') }
end
after this, you can receive the users name from the post like post.user_name
and it will be forwarded to the name attribute of the user object.
and change in your show.html
<%= post.user.name %>
to
<%= post.user_name %>
additional: please do not use default_scope. if you dont need the
order()
you always have tounscope
your queries.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.