【问题标题】:NoMethodError in Events#show | undefined method `firstname' for nil:NilClass事件中的 NoMethodError#show | nil:NilClass 的未定义方法“名字”
【发布时间】:2014-10-08 17:10:02
【问题描述】:

我对 ruby​​ on rails 很陌生,如果我的以下问题非常基本,我提前道歉,任何帮助将不胜感激。

  1. 按照“railscast #154 多态关联”,我现在可以为活动和博客创建 cmets,

  2. 但我还想做的是,当用户发表评论时,用户的姓名(发表评论的人)与他们发表的评论一起出现......类似于下面的内容

  3. 详细信息如下 - 在我的 views/cmets/_cmets.html.erb 文件中,我将 和 controllers/cmets_controller.rb 放在我添加了 @cmets.user = current_user 的索引方法,但无法让它显示 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 我在 view/events/show.html.erb 中呈现评论部分 在 _cmets.html.erb 我输入了 但收到错误

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

【问题讨论】:

  • 我很确定在您的索引操作中@comments.user = current_user 会给您一个错误。您在那里有一个活动记录 collection,并正在尝试为其设置一个值。一方面,您的索引操作不应该在模型上设置属性 - 另一方面,如果您想设置一个值,它需要在每个单独的模型上。请参阅@tehfailsafe 的回答。

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


【解决方案1】:

你快到了。如果您始终希望它是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,而不是在索引操作中写它(实际上不会做任何事情,因为@cmets 是 cmets 列表的关系,你不能设置反正都是这样)

【讨论】:

    猜你喜欢
    • 2021-11-05
    • 2013-11-14
    • 2013-01-14
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多