Rails 3.2 Проверка уникальности вызывает неопределенный метод 'zero?'для ноля: нилькласс - PullRequest
6 голосов
/ 15 февраля 2012

Я использую Rails 3.2.0.

У меня есть простая модель, как показано ниже

class Favorite < ActiveRecord::Base

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

Если я попробую это

f = Favorite.new
f.valid?

Я получаю следующее сообщение об ошибке:

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!'
....
....

1 Ответ

8 голосов
/ 29 февраля 2012

Псевдоним таблицы ActiveRecord AREL прерывается

Ошибка, вероятно, из-за того, что ActiveRecord AREL потерял след того, как суммировать пустой массив.

Соответствующая строка кода находится в файле alias_tracker.rb:

 count.sum

Если count является пустым массивом, строка оценивается как:

 [].sum

В Ruby, который не работает:

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

Rails ActiveSupport Enumerable # sum

В Rails это успешно, потому что ActiveSupport создает Enumerable # sum

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

Ваша проблема, вероятно, в том, что некоторая несвязанная область вашего приложения также создает Enumerable # sum или Array # sum. Несвязанный код переписывает метод Rails.

Это может происходить в вашем коде или в другом камне. Драгоценный камень Rails загружается раньше, обычно первым в вашем Gemfile, и любой последующий гем может мешать Rails.

Как это исправить?

Вы написали метод с именем sum, возможно, в модуле с именем Enumerable или Array? Если так, то это хорошее место для начала. Вы можете переименовать свой метод, или вы можете изменить свой метод, чтобы он соответствовал методу Rails, заменив код #sum следующим кодом:

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

Если вы не написали метод с именем sum в своем коде, то конфликт, скорее всего, в геме, который вы используете. Попробуйте закомментировать используемые вами драгоценные камни и перезагрузите приложение.

Вы можете искать драгоценный камень, который определяет метод с именем sum следующим образом:

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

Вы используете какие-нибудь драгоценные камни с именем sixarm? Если так, свяжитесь со мной, и я исправлю их для вас. Это я, и некоторые из них определяют #sum для использования со статистическими инструментами и утилитами.

Надеюсь, это поможет. Можете ли вы опубликовать здесь, если это решит вашу проблему?

...