Reputation: 3
I have a fairly simple forms-over-data Rails app that calls a remote MySql 5.5 db. Using Rails 3.2.21, Ruby 1.9.3.
One of the pages in the app is throwing the following error:
NoMethodError in GvpController#input
undefined method `has_key?' for nil:NilClass
app/controllers/gvp_controller.rb:9:in `input'
Here is the offending code from the controller:
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
I'm assuming the call to gvp_vendor_names is returning nil.
Here is the Vendor model class:
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
I have searched other posts with this error message and so far haven't found one that seems relevant. I am not overriding the initialize method (one possible cause) and I think the syntax is correct (another).
As an additional wrinkle, I am using vagrant for development, so I thought perhaps I'm not successfully communicating with the database from the vagrant box - maybe an ssh or permissions issue. To test it, I opened an ssh session on the vagrant box, successfully connected with the db via command line ran a select statement and lo and behold, get the full list of results I was expecting. I also tried it with mysql workbench via ssh and had no problems. So, it seems I can communicate remotely with the db, execute queries against it, have the proper permissions etc.
Does anyone have any suggestions as to what the problem might be?
Upvotes: 0
Views: 2098
Reputation: 3
The real problem may just be that I'm a Rails/ActiveRecord n00b. After a little more experimentation, I found the following changes corrected the error.
In the model I added attr_accessible and then used engineersmnky's suggestion of using a method rather than scope, as follows:
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
Then in the controller:
class GvpController < ApplicationController
def input
#irrelevant stuff
@list = Vendor.gvp_vendor_names
#irrelevant stuff
end
end
That fixed it. Thank you everyone for the suggestions!
Upvotes: 0
Reputation: 3374
I assume that you haven't any value on your DB tables. That's why the issue arise in controller action block during you call gvp_vendor_names
mapped value vendor_name
You should handle this type of case by checking the object value rather than accessing 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
In this way you need to compact the nil value. So use this finally if you want to handle the scenario from controller:
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
Upvotes: 2