ActiveRecord未定义的方法`has_key?'为nil:NilClass错误

时间:2015-05-26 17:04:09

标签: mysql ruby-on-rails ruby activerecord vagrant

我有一个相当简单的数据形式Rails应用程序,它调用远程MySql 5.5 db。使用Rails 3.2.21,Ruby 1.9.3。

应用程序中的一个页面抛出以下错误:

NoMethodError in GvpController#input
   undefined method `has_key?' for nil:NilClass
   app/controllers/gvp_controller.rb:9:in `input'

以下是来自控制器的违规代码:

class GvpController < ApplicationController
  def input
    # irrelevant stuff
    @list =  Vendor.gvp_vendor_names.map { |x| x.vendor_name }
    # more irrelevant stuff
  end      
  # other irrelevant methods
end

我假设对gvp_vendor_names的调用返回nil。

以下是供应商模型类:

class Vendor < ActiveRecord::Base
  establish_connection :vendor_sql
  self.table_name = 'reporting_dw.vp_vendor_mapping'
  scope :gvp_vendor_names, -> {
    select('reporting_dw.vp_vendor_mapping.vendor_name')}
end

我使用此错误消息搜索了其他帖子,到目前为止还没有找到一个看似相关的帖子。我没有覆盖initialize方法(一个可能的原因),我认为语法是正确的(另一个)。

作为一个额外的皱纹,我正在使用vagrant进行开发,所以我想也许我没有成功地与流氓盒中的数据库进行通信 - 可能是ssh或权限问题。为了测试它,我在vagrant box上打开了一个ssh会话,通过命令行与db成功连接运行了一个select语句,然后看看,得到我期望的完整结果列表。我也通过ssh尝试使用mysql workbench,没有任何问题。所以,似乎我可以与数据库远程通信,对它执行查询,拥有适当的权限等。

有没有人对这个问题有什么建议?

2 个答案:

答案 0 :(得分:2)

我假设您的数据库表没有任何价值。这就是您在调用gvp_vendor_names映射值vendor_name

期间在控制器操作块中出现问题的原因

您应该通过检查对象值而不是访问firstclass

来处理这种情况
GvpController < ApplicationController
  def input
    # irrelevant stuff
    @list =  Vendor.gvp_vendor_names.map { |x| x.vendor_name if x.present?}
    # more irrelevant stuff
  end      
  # other irrelevant methods
end

这样你需要压缩nil值。如果你想从控制器处理场景,最后使用它:

class GvpController < ApplicationController
  def input
    # irrelevant stuff
    @list =  Vendor.gvp_vendor_names.map { |x| x.vendor_name if x.present?}.compact
    # more irrelevant stuff
  end      
  # other irrelevant methods
end

答案 1 :(得分:0)

真正的问题可能只是我是Rails / ActiveRecord n00b。经过一些实验,我发现以下更改纠正了错误。

在模型中我添加了attr_accessible,然后使用了engineermnky建议使用方法而不是范围,如下所示:

class Vendor < ActiveRecord::Base
  establish_connection :vendor_sql 
  attr_accessible :vendor_name
  self.table_name = 'reporting_dw.vp_vendor_mapping'

  def self.gvp_vendor_names
    pluck(:vendor_name).sort
  end
end

然后在控制器中:

class GvpController < ApplicationController
  def input
    #irrelevant stuff
    @list = Vendor.gvp_vendor_names 
    #irrelevant stuff
  end
end

修复了它。谢谢大家的建议!

相关问题