Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3.2 Uniqueness validation raises undefined method 'zero?' for nil:Nilclass

I am using Rails 3.2.0.

I have a simple model as show below

class Favorite < ActiveRecord::Base

  validates :lst, :presence => true
  validates :uuid, :presence => true, :uniqueness => {:scope => :lst}                                                                                                                                                                    
end

If I try this

f = Favorite.new
f.valid?

I get the following error message:

NoMethodError: undefined method `zero?' for nil:NilClass
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/associations/alias_tracker.rb:28:in `aliased_name_for'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/associations/join_dependency.rb:17:in `initialize'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/relation/finder_methods.rb:219:in `new'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/relation/finder_methods.rb:219:in `construct_join_dependency_for_association_find'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/relation/finder_methods.rb:192:in `exists?'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.0/lib/active_record/validations/uniqueness.rb:32:in `validate_each'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validator.rb:153:in `block in validate'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validator.rb:150:in `each'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validator.rb:150:in `validate'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:310:in `_callback_before_15'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:429:in `_run__1275595979440079611__validate__42615372200132002__callbacks'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:405:in `__run_callback'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:385:in `_run_validate_callbacks'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.0/lib/active_support/callbacks.rb:81:in `run_callbacks'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validations.rb:212:in `run_validations!'
    from /Users/ragrawal/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.0/lib/active_model/validations/callbacks.rb:53:in `block in run_validations!'
....
....
like image 925
user737128 Avatar asked Feb 15 '12 07:02

user737128


1 Answers

ActiveRecord AREL table aliasing is breaking

The error is likely due to ActiveRecord AREL losing track of how to sum an empty array.

The relevant line of code is in the file alias_tracker.rb:

 count.sum

If count is an empty array then the line evaluates as:

 [].sum

In Ruby that fails:

 $ irb
 > [].sum
 NoMethodError: undefined method `sum' for []:Array

Rails ActiveSupport Enumerable#sum

In Rails that succeeds because ActiveSupport is creating Enumerable#sum

 $ irb
 > require 'active_support/core_ext/enumerable'
 > [].sum  
 => 0

Your problem is likely that some unrelated area of your app is also creating Enumerable#sum or Array#sum. The unrelated code is overwriting the Rails method.

The could be happening in your code or in an unrelated gem. The Rails gem loads early, typically first in your Gemfile, and any later gem can interfere with Rails.

How to fix it?

Have you written a method named sum, perhaps within a module named Enumerable or Array? If so, that's a good place to start. You could rename your method, or you could try changing your method to match the Rails method by replacing your #sum code with this code:

module Enumerable
  def sum(identity = 0, &block)
    if block_given?
      map(&block).sum(identity)
    else
      inject(:+) || identity
    end
  end
end

If you haven't written a method named sum in your code, then the conflict is likely in a gem you're using. Try commenting-out gems that you're using then reload your app.

You can search for a gem that defines a method named sum like this:

$ cd /usr/lib/ruby/gems 
$ find | xargs grep "def sum\b"

Are you using any gems named sixarm? If so, contact me and I'll fix them for you. These are by me, and a few of them do define #sum for use with statistics tools and utilties.

Hope this helps. Can you post here if it solves your issue?

like image 99
joelparkerhenderson Avatar answered Oct 12 '22 23:10

joelparkerhenderson