Rails4 动作控制器 - nil:NilClass 的未定义方法"length"



我正在为我的一个项目从头开始构建一个消息传递系统。一切都工作得很好,但我只是有以下错误:NoMethodError in MessagesController#index跟着undefined method 'length' for nil:NilClass。遗憾的是,我找不到符合我情况的答案。

我给你conversations_controller.rb, messages_controller.rb,模型和路线(和日志):

conversations_controller.rb

class ConversationsController < ApplicationController
  before_action :authenticate_user!
  def index
    @users = User.all
    @conversations = Conversation.all
  end
  def create
    if Conversation.between(params[:sender_id], params[:recipient_id]).present?
      @conversation = Conversation.between(params[:sender_id], params[:recipient_id]).first
    else
      @conversation = Conversation.create!(conversation_params)
    end
    redirect_to conversation_messages_path(@conversation)
  end
  private
  def conversation_params
    params.permit(:sender_id, :recipient_id)
  end
end

messages_controller。rb:

class MessagesController < ApplicationController
  def index
    if @messages.length > 10
      @over_ten = true
      @messages = @messages[-10..-1]
    end
    if params[:m]
      @over_ten = false
      @messages = @conversation.messages
    end
    if @messages.last
      if @messages.last.user_id != current_user.id
        @messages.last.read = true;
      end
    end
    @message = @conversation.messages.new
  end
  def new
    @message = @conversation.messages.new
  end
  def create
    @message = @conversation.messages.new(message_params)
    if @message.save
      redirect_to conversation_messages_path(@conversation)
    end
  end
  private
  def message_params
    params.require(:message).permit(:body, :user_id)
  end
end

的谈话。rb:

class Conversation < ActiveRecord::Base
  belongs_to :sender, foreign_key: :sender_id, class_name: 'User'
  belongs_to :recipient, foreign_key: :recipient_id, class_name: 'User'
  has_many :messages, dependent: :destroy
  validates_uniqueness_of :sender_id, scope: :recipient_id
  scope :between, -> (sender_id,recipient_id) do
    where("(conversations.sender_id = ? AND conversations.recipient_id = ?)
            OR (conversations.sender_id = ? AND conversations.recipient_id = ?)",
            sender_id,recipient_id, recipient_id,sender_id)
    end
end

消息。rb:

class Message < ActiveRecord::Base
  belongs_to :conversation
  belongs_to :user
  validates_presence_of :body, :conversation_id, :user_id
  def message_time
    created_at.strftime("%m/%d/%y at %l:%M %p")
  end
end

路线。rb:

Rails.application.routes.draw do
  get 'messages/index'
  get 'messages/new'
  get 'conversations/index'
  get 'dashboard/index'
  get 'dashboard/trips'
  get 'dashboard/messages'
  get "welcome/index"
  resources :conversations do
    resources :messages
  end
  devise_for :users
  authenticated :users do
    root to: 'dashboard#index', as: :authenticated_root
  end
  root "welcome#index"
end

在这里,日志:

Started GET "/conversations/5/messages" for ::1 at 2016-11-13 16:45:38 +1030
Processing by MessagesController#index as HTML
  Parameters: {"conversation_id"=>"5"}
Completed 500 Internal Server Error in 5ms (ActiveRecord: 0.0ms)
NoMethodError (undefined method `length' for nil:NilClass):
  app/controllers/messages_controller.rb:4:in `index'

  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_source.erb (3.7ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.1ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.7ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (53.1ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/_markup.html.erb (0.5ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (0.3ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (0.4ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/style.css.erb within layouts/inlined_string (0.3ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/console.js.erb within layouts/javascript (40.4ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/main.js.erb within layouts/javascript (0.4ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/error_page.js.erb within layouts/javascript (0.7ms)
  Rendered /Users/JUSTINE/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/index.html.erb (91.6ms)

我希望这将对你有帮助,我们将能够找到答案:)

欢呼

没有设置MessagesController中的@messages实例变量。首先需要将其初始化为current_user.messages:

  def index
    @messages = current_user.messages # or something like this
    if @messages.length > 10
      @over_ten = true
      # ...

当你在ruby中看到如下格式的错误消息时:

undefined method 'method_name' for nil:NilClass

你被告知你正在尝试调用一个nil对象,所以你的注意力应该集中在为什么这个对象是nil。在日志中还会告诉您错误发生的位置:

app/controllers/messages_controller.rb:4:in `index'

就是这一行:

if @messages.length > 10

所以@messages是nil在这个例子中它是nil因为它还没有被声明

在if块之前执行如下操作:

@messages = Message.all