新手问题 使用 acts_as_commentable 给 post 添加评论,comment 对应一个 user,如何获得 user 的相关信息信息

tailang · 2013年07月14日 · 最后由 xiaoniuniu 回复于 2013年09月04日 · 6935 次阅读

我用 devise 进行登录注册,生成一个 user 表,我又给 user 表添加了 username 这个字段。
----------------------------------小割一下------------------------------------------------------------------------
现在我用 acts_as_commentable 给 post 添加评论,按照 github 上步骤,我执行了一下步骤

rails g comment
rake db:migrate

在 post model 中添加了

class Post < ActiveRecord::Base
  acts_as_commentable
end

model 的内容分别如下
user.rb

class User < ActiveRecord::Base

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  attr_accessible :email, :password, :password_confirmation, :remember_me,  :username

  validates :username, presence: true,  
                   length: {maximum: 16},
                   uniqueness: true
end

post.rb

class Post < ActiveRecord::Base
  acts_as_commentable

  default_scope :order => 'id DESC'

  attr_accessible :body, :title
end

comment.rb

class Comment < ActiveRecord::Base

  include ActsAsCommentable::Comment

  belongs_to :commentable, :polymorphic => true

  default_scope :order => 'created_at ASC'


  # NOTE: Comments belong to a user
  belongs_to :user

  validates :comment, :presence => true

  attr_accessible :comment, :title
end

comment 的表单是这样写的

<% @comment ||= @post.comments.build %>
    <%= form_for([@comment.commentable, @comment]) do |f| %>
     <%= f.label :comment, "添加回应" %>
     <%= f.text_area :comment %><br>
     <%= f.submit %>
<% end -%>

comment 的 controller 是这样写的

def create
      @comment = commentable_record.comments.create(params[:comment])
      @comment.user = current_user #当前用户

      respond_to do |format|
        if @comment.save
          format.html {redirect_to commentable_record, notice: '创建评论成功'}
          format.json {render json: @comment, status: :created, location: commentable_record}
        else
          format.html { render action: :new }
          format.json { render json: @comment.errors, status: :unprocessable_entity }  
        end
      end
    end

    protected

    def commentable_record
      Post.find(params[:post_id])
    end
end

最后我想在 view 中显示 comment 的内容和对应的 user 的用户名

<% @post.comments.each do |comment| %>
     <%= comment.user %><br>
     <%= comment.comment %><br>
 <% end -%>

如果写成<%= comment.user %>好像显示的是 user 的对象,评论内容可以正常显示,如下图

如果改成<%= comment.user.username %> 则会提示错误:

请问该如何正确显示 user 表的内容比如 username,email 等

是因为创建 comment 的时候用户未登录,所以当时的 current_user 为空?

@loveky 我登录了,如果用<%= comment.user %>也可以显示对应的 user 的对象如#User:0xb59971e4

@loveky 是否我的 model 有问题啊?但也一直没找到问题

#3 楼 @tailang 那你可以进到 rails console 里找到那个 commit 看看对应的 user 里到底保存了什么

@loveky 原来都没写进数据库,我用 devise 注册用户登入用户都可以,acts_as_commentable 也可以写评论,但是我到 rails c 中看了下数据表发现都没写进去,这是什么原因

@loveky 非常感谢,谢谢你提示,我找到原因了,原来我的数据表被我“搞坏”了,导致 current_user 为空了

#6 楼 @tailang 嗯,看到你的 users 表也是空的,我估计数据库是被你 reset 了。。

有数据之后没有错,如果没数据还不是一样错的啊?我觉得应该在提取数据时验证一下是否为空,提取到前端就不会报错了

@amcsc 嗯嗯,我考虑的不全,现在就改,谢谢

#9 楼 @tailang 请问你的问题最后怎么解决的?我遇到和你一样的问题呢。。。

@xiaoniuniu 你好 我当时是因为之前 rake db:reset 了一下导致数据库中的 user 全没了,所以导致

@comment.user = current_user #当前用户

中的 current_user 的找不到,后来我重新重启服务,添加数据就行了。但是你要注意 8 楼的问题,验证 comment 的 user 不能为空,

validates :user, :presence => true

#11 楼 @tailang hello 你的意思是说 user 必须要验证吗?这个 validates 语句放在哪里啊?我查了我的数据库,username 都在的。

<% @post.comments.each do |comment| %>
     <%= comment.user_id %><br>
     <%= comment.comment %><br>
 <% end -%>

改成 comment.user_id 的时候会显示 user_id 出来,但是写成 comment.user.username 就失败了。为什么呢。

@xiaoniuniu 这个验证写在 comment.rb 中,让 comment 的 user 必须存在,防止创建的 comment 没有对应的 user。像我的帖子一样 把你的内容贴出来看看,还有 log 也给我看看

#13 楼 @tailang 我是完全学习你的内容的。。。唯一的问题就是在 show.html.erb 的时候,没有办法显示 username

#13 楼 @tailang 我的 comment belongs_to :commentable 和 user,我觉得如果 comment.user_id 能显示出对应的 id,说明 comment 的时候是有 user 对应的。可是就是不知道为何无法显示 username...我现在没有代码 晚些给你看:)

@xiaoniuniu user.rb 下有没有写 has_many :comments

#16 楼 @tailang 应该是写了,不会这么粗心吧。。。我查一下 晚点回复你~~~

#18 楼 @tailang 这个是 user.rb

class User < ActiveRecord::Base

  has_many :comments
  validates :email, :presence => true, :uniqueness => true

  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable    :authentication_keys

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable,
         :validatable
  attr_accessible :username, :email, :password, :password_confirmation, :remember_me
  attr_accessor :login
  attr_accessible :login

  def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:login)
      where(conditions).where(["username = :value OR lower(email) = lower(:value)", { :value => login }]).first
    else
      where(conditions).first
    end
  end

### This is the correct method you override with the code above
### def self.find_for_database_authentication(warden_conditions)
### end

end

出错是 undefined method `username' for nil:NilClass log 信息

@xiaoniuniu 不好意思啊 刚刚上课回来 我看了你这些也看不出什么 看否给我看看你的 user 表 (rails c // User) 和 comment_controller

#20 楼 @tailang 好~我搞了半天刚想放弃。。大牛出现了!感动啊~~~~

class CommentsController < ApplicationController
  def show
    @product = Product.find(params[:product_id])
    @comments = @product.comments.all
  end

  def new
    @comment = Comment.new
  end

  def edit
    @comment = Comment.find(params[:id])
  end

  def update
    @product = Product.find(params[:product_id])
    @comment = Comment.find(params[:id])
    @comment.update_attributes(params[:comment])
    redirect_to @product
  end

  def create
    @comment = commentable_record.comments.create(params[:comment])
    @comment.user = current_user #当前用户

    respond_to do |format|
      if @comment.save
        format.html {redirect_to commentable_record, notice: '创建评论成功'}
        format.json {render json: @comment, status: :created, location: commentable_record}
      else
        format.html { render action: :new }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end

  protected

  def commentable_record
    Product.find(params[:product_id])
  end
end



@xiaoniuniu 不是大牛,是个初学者,呵呵。看了以后我也没看出问题,这个问题就是没找到对象,产生原因很多,这是我上次写的博客用到了 acts_as_commentable https://github.com/tailang/Tblog 你看一下,有不懂的地方你再问我,不好意思啊

#22 楼 @tailang 好的 我也觉得奇怪。我在 show.html.erb 中调用 comment.user_id 能正确显示出 user 的 id 号。但是用 comment.user.username 就错了 然后我 check 了 commentable,用 comment.commentable.title 也能正确显示,奇怪啊。。。。

@xiaoniuniu 恩恩,能看到 user 的对象不?直接用 comment.user,记一下对象号,然后刷新几下,看一下对象号有没有变

#24 楼 @tailang 变了 这是为什么?

那你

rake db:reset

一下 在重新注册新用户,记得新用户要填 username 值 再试试

#26 楼 @tailang 啊 reset 的后果是啥?我对数据库搞不太懂。。。最怕弄这个了。。我试了一下 comment.user.email 也是错的。。。

reset 后清空了所有的数据 但数据库的表还是在的

#28 楼 @tailang 好的 我看看试试看

#29 楼 @tailang 看过了。。。我试试看哈

需要 登录 后方可回复, 如果你还没有账号请 注册新账号