事件中的NoMethodError#show | nil的未定义方法`firstname':NilClass

时间:2014-08-14 22:13:39

标签: ruby-on-rails ruby ruby-on-rails-4

我对铁轨上的红宝石很新,如果我的下面的问题非常基本,我会提前道歉,任何帮助都会非常感激。

  1. 在“railscast#154 Polymorphic Association”之后,我现在可以为活动和博客创建评论,

  2. 但我还想做的是,当用户发表评论时,用户的名字(发布评论的人)会显示他们发布的评论......如下所示

  3. 如下详细信息 - 在我的观看/评论/ _comments.html.erb文件中,我放置了<%= comment.user.firstname%> &在索引方法中的controllers / comments_controller.rb我添加了 @ comments.user = current_user ,但无法显示当前用户的姓名及其发布的评论,如下所示

  4.    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 %>
    

    模式

      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
    

    控制器

    #<<<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 / events / show.html.erb中呈现评论部分内容 在_comments.html.erb中,我输入了&lt;%= comment.user.firstname%&gt; ,但收到了错误

    #<<<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 %>
    

1 个答案:

答案 0 :(得分:2)

你几乎就在那里。如果您始终希望用户成为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是一个评论列表的关系,你无论如何都不能设置每一个)