7

Я обновляю приложение Rails, которое унаследовано от 3.2 до 4.0.1. Я последовал и закончил направляющую здесь:Рельсы от 3.2 до 4.0 Обновление: Неопределенный метод to_datetime для false: FalseClass

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: "[email protected]", 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 rals установлены. Я использую chgems, и я очистил свой каталог .gem/ и Gemfile.lock перед тем, как снова собрать.

Вот Gist of the User model.

И here is all of the backtrace output я мог бы получить от pry.

Описание: link to the User table schema.

+0

Это происходит из-за 'created_at' и' updated_at' – uzaif

+0

@uzaif, не могли бы вы объяснить далее? Благодаря! – cmhobbs

+0

Вы можете показать схему для таблицы пользователей. Также вы перезагрузили сервер, можете ли вы попытаться создать пользователя на консоли – coderVishal

ответ

7

После того как вы Мы обнаружили, что оскорбительный ответ должен быть следующим:

before_create :activate_license 

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

все становится более ясным. activate_licence является до обратного вызова. До обратные вызовы могут halt the whole callbacks chain by returning false (или создание исключения).

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

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

Поскольку поддержка остановки перед тем обратными вызовами путем возврата false (т.е. код рельсов показан выше) практически не изменился с Rails 3.2Rails 4.0.1 на этот вопрос должен находиться в самом сравнении.

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

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

    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 это changed to голый код ниже:

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

    → все проверки здравомыслие ушли!

Теперь все понятно: результат обратного вызова (а DateTime объекта) сравнивается с использованием оператора <=> с false и под Rails 4.0, сравнение пытается преобразовать false объект DateTime без каких-либо проверок здравомыслия , который, конечно же, терпит неудачу и выдает исключение.

Чтобы устранить эту проблему, просто убедитесь, что ваш обратный вызов возвращает то, что Rails может сравниться с false без каких-либо проблем., например. true, так как ваш обратный вызов никогда не должны остановить цепь:

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

Теперь все должно работать, как ожидается, еще раз.

2

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

/home/cmhobbs/src/serve2perform/.gem/ruby/2.3.0/gems/activesupport-4.0.1/lib/active_support/core_ext/date_time/calculations.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