事件中的无方法错误#显示 |nil:NilClass 的未定义方法 'firstname'



我是ruby on rails的新手,如果我下面的问题是非常基本的,我提前道歉,任何帮助都会非常感激。

  1. 在"railscast #154多态关联"之后,我现在可以为事件和博客创建评论,

  2. 但我还想做的是,当用户发布评论时,用户(谁发布评论)的名称出现与他们发布的评论....比如下面的

  3. 详情如下- in my views/comments/_comments.html。<%=comment.user。firstname %>,控制器/comments_controller。我在索引方法中添加了@comments。user = current_user,但是不能让它显示current_user的名字和他们发布的评论如下

emma thompson很棒的活动,非常享受!

emma Thompson是current_user

很棒的活动,非常喜欢!作为注释

-问题:我如何调用发表评论的用户的名字?

错误消息

NoMethodError in Events#show
Showing /Users/ARTLoe/00_GitH/00_Projects/spefz_app/app/views/comments/_comments.html.erb where line #5 raised:
undefined method `firstname' for nil:NilClass
    <ul>
    <% @comments.each do |comment| %>
      <li>
        <%= comment.user.firstname %>          #<--------------error appears on this line
        <%= simple_format comment.content %>
      </li>
    <% end %>
<<p> 模式/strong>
  create_table "comments", force: true do |t|
    t.text     "content"
    t.integer  "commentable_id"
    t.string   "commentable_type"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
  add_index "comments", ["commentable_id", "commentable_type"], name: "index_comments_on_commentable_id_and_commentable_type", using: :btree
  create_table "events", force: true do |t|
    t.string   "name"
    t.text     "description"
    t.date     "date"
    t.time     "time"
    t.text     "city"
    t.decimal  "price",       precision: 8, scale: 2
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "user_id"
  end
  create_table "users", force: true do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "firstname"
    t.string   "lastname"
    t.date     "dob"
    t.string   "gender"
    t.text     "description"
    t.string   "role"
  end

class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
  belongs_to :user
end
class Event < ActiveRecord::Base
  belongs_to :user
  has_many :comments, as: :commentable
end
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable  
  has_many :events
  has_many :comments, as: :commentable
end
<<p> 控制器/strong>
#<<<COMMENT CONTROLLER
class CommentsController < ApplicationController
  before_action :set_comment, only: [:show, :edit, :update, :destroy]
  before_filter :load_commentable
  def index
    @comments = @commentable.comments
    @comments.user = current_user
  end
  def show
  end
  def new
    @comment = @commentable.comments.new
  end
  def edit
  end
  def create
    @comment = @commentable.comments.new(comment_params)
    respond_to do |format|
      if @comment.save
        format.html { redirect_to [@commentable], notice: 'Comment was successfully created.' }
        format.json { render :show, status: :created, location: @comment }
      else
        format.html { render :new }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end
  def update
    respond_to do |format|
      if @comment.update(comment_params)
        format.html { redirect_to @comment, notice: 'Comment was successfully updated.' }
        format.json { render :show, status: :ok, location: @comment }
      else
        format.html { render :edit }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end
  def destroy
    @comment.destroy
    respond_to do |format|
      format.html { redirect_to events_url, notice: 'Comment was successfully destroyed.' }
      format.json { head :no_content }
    end
  end
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_comment
      @comment = Comment.find(params[:id])
    end
    # Never trust parameters from the scary internet, only allow the white list through.
    def comment_params
      params.require(:comment).permit(:content, :user_id)
    end
    def load_commentable
      resource, id = request.path.split('/')[1, 2]
      @commentable = resource.singularize.classify.constantize.find(id)
    end
end

#<<<EVENT CONTROLLER
class EventsController < ApplicationController
  before_action :set_event, only: [:show, :edit, :update, :destroy]
  before_filter :authenticate_user!
  def index
    @events = Event.order(:date)
    # @events = current_user.events | displays only events by current user
  end
  def show
    @commentable = @event
    @comments = @commentable.comments
    @comment = Comment.new
  end
  def new
    @event = Event.new
  end
  def edit
  end
  def create
    @event = Event.new(event_params)
    respond_to do |format|
      if @event.save
        format.html { redirect_to @event, notice: 'Event was successfully created.' }
        format.json { render :show, status: :created, location: @event }
      else
        format.html { render :new }
        format.json { render json: @event.errors, status: :unprocessable_entity }
      end
    end
  end
  def update
    respond_to do |format|
      if @event.update(event_params)
        format.html { redirect_to @event, notice: 'Event was successfully updated.' }
        format.json { render :show, status: :ok, location: @event }
      else
        format.html { render :edit }
        format.json { render json: @event.errors, status: :unprocessable_entity }
      end
    end
  end
  def destroy
    @event.destroy
    respond_to do |format|
      format.html { redirect_to events_url, notice: 'Event was successfully destroyed.' }
      format.json { head :no_content }
    end
  end
  private
    def set_event
      @event = Event.find(params[:id])
    end
    def event_params
      params.require(:event).permit(:name, :description, :date, :time, :city, :price)
    end
end

views我正在渲染views/events/show.html.erb中的注释部分在_comments.html中。我键入<%= comment.user.firstname %>,但收到一个错误

#<<<VIEWS/COMMENTS/_COMMENTS.HTML.ERB
<div>
  <ul>
  <% @comments.each do |comment| %>
    <li>
      <%= comment.user.firstname %>
      <%= simple_format comment.content %>
    </li>
  <% end %>
  </ul>
</div>
#<<<VIEWS/COMMENTS/_FORM.HTML.ERB
<%= form_for [@commentable, @comment] do |f| %>
  <% if @comment.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
      <ul>
      <% @comment.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
  <div class="field">
    <%= f.text_area :content, rows: 8 %>
  </div>
  <div class="actions">
    <%= f.submit "Post" %>
  </div>
<% end %>

你就快成功了。如果您始终希望用户为current_user

,则需要在创建操作上设置用户。
def create
  @comment = @commentable.comments.new(comment_params)
  @comment.user = current_user
  respond_to do |format|
    if @comment.save
      format.html { redirect_to [@commentable], notice: 'Comment was successfully created.' }
      format.json { render :show, status: :created, location: @comment }
    else
      format.html { render :new }
      format.json { render json: @comment.errors, status: :unprocessable_entity }
    end
  end
end

此外,您还需要删除索引操作上的@comments.user = current_user。你想阅读它的方式,你已经在视图:comment.user.firstname,而不是写它在索引动作(这实际上不会做任何事情,因为@comments是一个评论列表的关系,你不能设置每一个,无论如何)

最新更新