我对rails很新,我有一个基于论坛怪物的简单论坛应用程序。我目前正在将其从rails 3.0.9更新到3.2.11。在修复了这个自我issue后,我遇到了另一个问题。
当我尝试显示一个主题时,用户(来自post.user)对象在它不应该是的时候是nil。
这是错误
Extracted source (around line #17):
14: <% @topic.posts.each do |post| %>
15: <tr>
16: <td class="post_author" rowspan="2">
17: <span class="name"><%= post.user.username %></span>
18: <span class="avatar"><%= image_tag post.user.gravatar_url %></span>
19: <span class="info smaller">
20: <p><strong><%= "Administrator" if post.user.admin? %></strong></p>
这是我的观点app / views / topics / show.html.erb
<div class="right controls"><%= link_to "Back to Forum", forum_path(@topic.forum) %></div>
<div class="module">
<div class="module_header">
<%= @topic.title %>
<span class="right controls">
<%= link_to "Edit", edit_topic_path(@topic) if can? :manage, @topic %>
<%= link_to "Delete", @topic, :confirm => "Are you sure?", :method => :delete if can? :manage, @topic %>
<%= link_to @topic.sticky ? "Unstick" : "Sticky", {:controller => 'topics', :action => 'update', :topic => {:sticky => @topic.sticky ? "false" : "true" }}, :method => :put if can? :moderate, @topic %>
<%= link_to @topic.locked ? "Unlock" : "Lock", {:controller => 'topics', :action => 'update', :topic => {:locked => @topic.locked ? "false" : "true" }}, :method => :put if can? :moderate, @topic %>
</span>
</div>
<div>
<table>
<% @topic.posts.each do |post| %>
<tr>
<td class="post_author" rowspan="2">
<span class="name"><%= post.user.username %></span>
<span class="avatar"><%= image_tag post.user.gravatar_url %></span>
<span class="info smaller">
<p><strong><%= "Administrator" if post.user.admin? %></strong></p>
Posts <%= post.user.posts.size %><br />
Registered <%=l post.user.created_at %><br />
</span>
</td>
<td class="post_header">
<span class="left post_date smaller">Posted <%=l post.created_at %></span>
<span class="right controls">
<%= link_to "Reply", new_topic_post_path(@topic) if can? :create, @topic.posts.new %>
<%= link_to "Quote", new_topic_post_path(@topic, :quote => post) if can? :create, @topic.posts.new %>
<%= link_to "Edit", edit_post_path(post) if can? :update, post %>
<%= link_to "Delete", post, :confirm => "Are you sure?", :method => :delete if can? :destroy, post %>
</span>
</td>
</tr>
<tr>
<td class="post_body">
<%= post.body.bbcode_to_html().html_safe %>
</td>
</tr>
<% end %>
</table>
</div>
</div>
<div class="right controls"><p><%= link_to "Back to Forum", forum_path(@topic.forum) %></p></div>
这里是控制器app / controlers / topics_controller.rb
class TopicsController < ApplicationController
load_and_authorize_resource :forum
load_and_authorize_resource :topic, :through => :forum, :shallow => true
def show
@topic.hit! if @topic
end
def create
@topic.user ||= current_user
if @topic.save
flash[:notice] = "Topic was successfully created."
redirect_to topic_url(@topic)
else
render :action => 'new'
end
end
def update
if @topic.update_attributes(params[:topic])
flash[:notice] = "Topic was updated successfully."
redirect_to topic_url(@topic)
end
end
def destroy
if @topic.destroy
flash[:notice] = "Topic was deleted successfully."
redirect_to forum_url(@topic.forum)
end
end
end
Rails控制台输出确认视图中的代码应该有效,并且帖子确实有用户。
ricky ~/forum $ rails c
Loading development environment (Rails 3.2.11)
irb(main):001:0> Topic.find(1).posts.each do |p|
irb(main):002:1* puts p.user.username
irb(main):003:1> end
Topic Load (0.5ms) SELECT `topics`.* FROM `topics` WHERE `topics`.`id` = 1 ORDER BY sticky DESC, updated_at DESC LIMIT 1
Post Load (0.4ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`topic_id` = 1 ORDER BY created_at ASC
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
admin
=> [#<Post id: 1, body: "Forum Monster is a simple forum generator written i...", forum_id: 1, topic_id: 1, user_id: 1, created_at: "2013-01-19 06:57:23", updated_at: "2013-01-19 06:57:23">]
irb(main):004:0>
我想我可能需要为cancan添加一项能力:读取用户,但我不太确定。
提前感谢帮助这个困惑的Android开发人员0.o
修改
查看完整来源HERE
如下所示,帖子模型确实验证了用户的存在
应用程序/模型/ post.rb
class Post < ActiveRecord::Base
# Associations
belongs_to :forum, :counter_cache => true
belongs_to :topic, :counter_cache => true, :touch => true
belongs_to :user, :class_name => "User", :counter_cache => true
# Accessors
attr_accessible :body
# Validations
validates :body, :presence => true
validates :user, :presence => true
# Default Scope
default_scope :order => 'created_at ASC'
# Scope to display only the last n posts. Used for "Recent Posts" display
scope :recent, lambda {
|c| reorder('created_at desc').limit(c)
}
# Callbacks
before_save :topic_locked?
# Methods
private
def topic_locked?
if topic.locked?
errors.add(:base, "That topic is locked")
false
end
end
end
什么让我觉得数据库中只有一个帖子存在,并且是通过
创建的@current_user = User.find_by_username("admin")
@current_user.topics.create!(...)
答案 0 :(得分:2)
我真的不明白为什么这样可以解决问题,因为数据库中只有一个帖子;但我找到了解决方案。
<% @topic.posts.each do |post| %>
<% if !post.user.blank? %>
...display post here...
<%end%>
<%end%>
答案 1 :(得分:1)
替换为:
<%= post.user.username unless post.user.blank? %>
答案 2 :(得分:0)
在您的视图中,集合@topic.posts
包含至少一个没有用户的帖子,并且视图中的其余代码不会预料到这一点。
可能您的应用程序不允许在没有用户的情况下创建帖子,您应该添加validation以在保存帖子时检查用户是否在场,并防止在没有用户的情况下创建帖子
validates :user_id, :presence => true
如果您的应用应允许不带用户的帖子,请在视图中添加if post.user.present?
:
<% @topic.posts.each do |post| %>
<tr>
<td class="post_author" rowspan="2">
<% if post.user.present? %>
<span class="name"><%= post.user.username %></span>
<span class="avatar"><%= image_tag post.user.gravatar_url %></span>
<span class="info smaller">
<p><strong><%= "Administrator" if post.user.admin? %></strong></p>
Posts <%= post.user.posts.size %><br />
Registered <%=l post.user.created_at %><br />
</span>
<% end %>
</td>
...
答案 3 :(得分:0)
您可以采取两种方式,具体取决于您是希望帖子用户是空白还是空白。
1)如果帖子用户可以为空白:
检查帖子用户是否存在,这样你就不会得到'nil'用户。
'@ userpost = post.user.blank? “”:post.user.username'
2)如果帖子用户不能为空:
在这种情况下,您可以强加关联,例如在帖子模型,'belongs_to:user'和用户模型中,'has_many:posts'以及像'validates_presence_of:post'这样的约束。