Обновление Rails 3.2 до 4.0: неопределенный метод datetime для false:FalseClass

Я обновляю приложение Rails, которое я унаследовал от 3.2 до 4.0.1. Я последовал и закончил руководство края здесь:

http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-3-2-to-rails-4-0

я получил все исправлено, за исключением одной ошибки, которую я не могу найти основную причину. Когда я пытаюсь сохранить объект модели пользователя, я столкнулся со следующей ошибкой:

[1] pry(main)> User.create(name: "test user", email: "testuser@frobnitz.com", password: "testPassword123", password_confirmation: "testPassword123")                                                                                                                               

(0.6ms)  BEGIN
(0.9ms)  ROLLBACK
NoMethodError: undefined method `to_datetime' for false:FalseClass
from /home/cmhobbs/src/serve2perform/.gem/ruby/2.3.0/gems/activesupport-4.0.1/lib/active_support/core_ext/date_time/calculations.rb:161:in `<=>'

activesupport 4.0.1-и 4.0.1 есть. Я использую chgems, и я очистил свой и Gemfile.lock прежде чем снова связывать.

здесь суть модели пользователя.

и вот все выходные данные backtrace я мог бы получить от pry.

здесь ссылка на схему таблицы пользователя.

2 ответов


как только вы нашли оскорбительный обратный вызов, чтобы быть этим:

  before_create :activate_license

  def activate_license
    self.active_license = true
    self.licensed_date = Time.now
  end

вещи начинают проясняться. The activate_licence это до обратный. до обратные вызовы могут остановите всю цепочку обратных вызовов, вернувшись false (или создание исключения).

если мы внимательно посмотрим в выводе отладки, который вы предоставили, вручную добавив некоторые puts линии в код обратного вызова Rails, мы действительно можем найдите сравнение этого результата обратного вызова с false (здесь - я удалил некоторые несущественные части кода):

result = activate_license
halted = (result == false)
if halted
  halted_callback_hook(":activate_license")
end 

потому что поддержка остановки перед обратными вызовами путем возврата false (т. е. код рельсов, показанный выше) практически не изменился с рельсы 3.2 to рельсы 4.0.1, проблема должна заключаться в самом сравнении.

обратный вызов возвращает DateTime object (это последнее назначение в метод, который также возвращается). И, действительно, сравнение DateTimes значительно изменился между двумя версиями Rails (также обратите внимание, что == оператор обычно оценка <=> оператор):

  • в Rails 3.2 это было этой:

    def <=>(other)
      if other.kind_of?(Infinity)
        super
      elsif other.respond_to? :to_datetime
       super other.to_datetime
      else
        nil
      end
    end
    

    заметьте, особенно respond_to? проверить, если other объект также является объектом даты или времени при возврате в противном случае nil.

  • тогда как в Rails 4.0.1 это изменено на голый код ниже:

    def <=>(other)
      super other.to_datetime
    end
    

    → все проверки ушли!

теперь все ясно: результат обратного вызова (a все должно работать как ожидается.


вы можете связать даже в основных классах, пожалуйста, сделайте что-то вроде этого и проверьте, что other, откуда он взялся.

/ главная / cmhobbs / src / serve2perform/.gem / ruby / 2.3.0/gems/activesupport-4.0.1/lib/active_support/core_ext/date_time / вычисления.rb

def <=>(other)
  binding.pry
  if other.kind_of?(Infinity)
    super
  elsif other.respond_to? :to_datetime
    super other.to_datetime rescue nil
  else
    nil
  end
end