rails: AR 4.2.1 .includes give undefined method `each' for nil:NilClass

I use MSSQL as primary db. It use decimal(19, 0) type for ids. I have 2 models:

class TaskCardImportStatus < ActiveRecord::Base
  has_many :poison_records, class: TaskCardImportPoisonRecord
....
end

class TaskCardImportPoisonRecord < ActiveRecord::Base
  belongs_to :task_card_import_status
end

when I try to do

rows = InvoiceImportStatus.includes(:poison_records).all

and after that access each elements like:

 rows.each do |r|
   puts r.id
end

I get exception:

NoMethodError: undefined method `each' for nil:NilClass
    from /Users/viktornazarenko/.rvm/gems/ruby-2.2.1/gems/activerecord-4.2.1/lib/active_record/associations/preloader/association.rb:96:in `block in associated_records_by_owner'
    from /Users/viktornazarenko/.rvm/gems/ruby-2.2.1/gems/activerecord-4.2.1/lib/active_record/associations/preloader/association.rb:94:in `each'
    from /Users/viktornazarenko/.rvm/gems/ruby-2.2.1/gems/activerecord-4.2.1/lib/active_record/associations/preloader/association.rb:94:in `associated_records_by_owner'
    from /Users/viktornazarenko/.rvm/gems/ruby-2.2.1/gems/activerecord-4.2.1/lib/active_record/associations/preloader/collection_association.rb:13:in `preload'
    from /Users/viktornazarenko/.rvm/gems/ruby-2.2.1/gems/activerecord-4.2.1/lib/active_record/associations/preloader/association.rb:20:in `run'
    from /Users/viktornazarenko/.rvm/gems/ruby-2.2.1/gems/activerecord-4.2.1/lib/active_record/associations/preloader.rb:146:in `block (2 levels) in preloaders_for_one'
    from /Users/viktornazarenko/.rvm/gems/ruby-2.2.1/gems/activerecord-4.2.1/lib/active_record/associations/preloader.rb:144:in `each'
    from /Users/viktornazarenko/.rvm/gems/ruby-2.2.1/gems/activerecord-4.2.1/lib/active_record/associations/preloader.rb:144:in `map'

Looks like problem is here:

            records.each do |record, owner_key|
              owners_map[owner_key].each do |owner|
                records_by_owner[owner] << record
              end
            end

I made a small debug and found that owners_map do mapping by ids in float point format like this:

{"38.0"=>[#<InvoiceImportStatus id: #<BigDecimal:7fd29a4e4278,'0.38E2',9(18)>, completedAt:  ...}

But then try to access it with integer id (owner_key == “38” in this case" )

             owners_map[owner_key] 

and it will not be found in map ( “38.0” != “38” )

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 20 (6 by maintainers)

Most upvoted comments

@sgrif Helped me out here by letting me know how to coerce the ID out of the table. So by adding attribute :id, Type::Integer.new on my model (the one with the float as a primary key), I can now properly use includes without hitting the .each error.

YMMV

I’m hitting this error randomly on production, but the cause is a bit obscure. Since I can’t reproduce it locally I added debugging statements and we got an insight on what’s happening, but don’t understand why. We are using Postgres 9.4 and rails 4.2.5.2.

It looks like the associated AR model retrieved from the database has an ID of 0 which causes the owner_key to be 0. And, since the owners_keys has no key with value 0 then we get the exception of undefined methodeach’ for nil:NilClass`.

This is the context we logged:

{
  "key_conversion_required" => false,
  "association_key_type" => "integer",
  "association_key_name" => "id",
  "association_class" => "Company",
  "association_record" => "#<Company id: 0, name: \"Google Inc.\", listed: nil, ... MORE FIELDS>",
  "owner_key_type" => "integer",
  "owner_key_name" => "company_id",
  "owner_key" => 0,
  "owner_class" => "Job",
  "available_owner_keys" => "[3531, 2831,  ...]",
  "klass" => "Company"
}

The problem is that owner_keys does not contain a key=0, which is correct since none of the owners are pointing to a company that has the ID=0. Both fields (primary_key and association_key) are integer, so no key conversion is required.

It seems that the problem is when records_for(ids) is called one of the records comes back with the id=0 even though that value is not in the list of ids.

Any ideas on why does the AR model has an ID of 0?

* Note:* On some other instances the AR model has all fields with the value nil. So either ID=0 or all fields = nil.