Rails: O formato de serialização ActiveSupport :: TimeWithZone em 5.xx não é compatível com versões anteriores de 4.xx

Criado em 27 ago. 2016  ·  3Comentários  ·  Fonte: rails/rails

Comportamento esperado

Temos vários aplicativos usando rails 5.0.0.1 e rails 4.2.7.1 e compartilhando o mesmo banco de dados.

5.0.0.1 está serializando o fuso horário de maneira diferente de 4.2.7.1 introduzido por este commit .

Nosso aplicativo usando rails 4.2.x.x não é capaz de desserializar o novo YAML escrito por nossos rails 5.0.0.1 aplicativos.

Seria bom se o próximo 4.2.x.x pudesse desserializar o novo formato.

Backtrace

NoMethodError: undefined method `period_for_utc' for nil:NilClass
- 40 non-project frames
1
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.7.1/lib/active_support/time_with_zone.rb" line 67 in period
2
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.7.1/lib/active_support/time_with_zone.rb" line 53 in time
3
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.7.1/lib/active_support/time_with_zone.rb" line 365 in respond_to_missing?
4
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.7.1/lib/active_support/time_with_zone.rb" line 357 in respond_to?
5
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.7.1/lib/active_support/time_with_zone.rb" line 357 in respond_to?
6
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 364 in init_with
7
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 357 in revive
8
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 207 in visit_Psych_Nodes_Mapping
9
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/visitor.rb" line 15 in visit
10
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/visitor.rb" line 5 in accept
11
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 31 in accept
12
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 314 in block in register_empty
13
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 314 in each
14
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 314 in register_empty
15
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 140 in visit_Psych_Nodes_Sequence
16
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/visitor.rb" line 15 in visit
17
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/visitor.rb" line 5 in accept
18
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 31 in accept
19
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 321 in block in revive_hash
20
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 319 in each
21
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 319 in each_slice
22
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 319 in revive_hash
23
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 161 in visit_Psych_Nodes_Mapping
24
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/visitor.rb" line 15 in visit
25
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/visitor.rb" line 5 in accept
26
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 31 in accept
27
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 295 in visit_Psych_Nodes_Document
28
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/visitor.rb" line 15 in visit
29
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/visitor.rb" line 5 in accept
30
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/visitors/to_ruby.rb" line 31 in accept
31
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych/nodes/node.rb" line 37 in to_ruby
32
File "/var/app/20160825T221638Z/vendor/ruby-2.2.4/lib/ruby/2.2.0/psych.rb" line 246 in load
33
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.7.1/lib/active_record/coders/yaml_column.rb" line 26 in load
34
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.7.1/lib/active_record/type/serialized.rb" line 19 in type_cast_from_database
35
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.7.1/lib/active_record/attribute.rb" line 104 in type_cast
36
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.7.1/lib/active_record/attribute.rb" line 42 in original_value
37
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.7.1/lib/active_record/attribute.rb" line 37 in value
38
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.7.1/lib/active_record/attribute_set.rb" line 31 in fetch_value
39
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.7.1/lib/active_record/attribute_methods/read.rb" line 93 in _read_attribute
40
File "/var/app/20160825T221638Z/vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.7.1/lib/active_record/attribute_methods.rb" line 50 in __temp__16574696475646f5368616e6765637

Configuração do sistema

Versão Rails : 4.2.7.1

Versão Ruby : 2.2.4

activesupport needs feedback

Comentários muito úteis

@kwent como você disse, seu problema é que você tem instâncias AS :: TWZ que são serializadas por uma aplicação Rails 5.0 sendo lidas por uma aplicação Rails 4.2, pois o contrário não é um problema, já que são lidas como Ruby UTC padrão Instâncias de tempo.

Acho que você terá que corrigir o seu aplicativo Rails 5.0 ou o aplicativo Rails 4.2 para tornar os valores compatíveis entre si. Corrigir para que o Rails 4.2 possa lê-los pode parecer possível, mas você ainda terá problemas porque essas instâncias serão serializadas no formato 4.2 porque não podemos mudar como estão sendo escritas em um lançamento de patch.

Coloque o seguinte código em um inicializador em seus aplicativos Rails 4.2 e tudo deve funcionar:

# https://github.com/rails/rails/issues/26296
ActiveSupport::TimeZone.class_eval do
  def init_with(coder) #:nodoc:
    initialize(coder['name'])
  end

  def encode_with(coder) #:nodoc:
    coder.tag ="!ruby/object:#{self.class}"
    coder.map = { 'name' => tzinfo.name }
  end
end

ActiveSupport::TimeWithZone.class_eval do
  def init_with(coder) #:nodoc:
    initialize(coder['utc'], coder['zone'], coder['time'])
  end

  def encode_with(coder) #:nodoc:
    coder.tag = '!ruby/object:ActiveSupport::TimeWithZone'
    coder.map = { 'utc' => utc, 'zone' => time_zone, 'time' => time }
  end
end

Normalmente, nesses tipos de situações, faremos a migração para frente, por exemplo, quando introduzimos a serialização de sessão JSON em 4.1, oferecemos um híbrido que lia as serializações existentes e as convertia, mas não uma migração para trás, onde uma sessão JSON criada em 4.1 funcionaria com um Aplicativo 4.0.

HTH e desculpe por qualquer incômodo causado.

Todos 3 comentários

r? @pixeltrix

@kwent como você disse, seu problema é que você tem instâncias AS :: TWZ que são serializadas por uma aplicação Rails 5.0 sendo lidas por uma aplicação Rails 4.2, pois o contrário não é um problema, já que são lidas como Ruby UTC padrão Instâncias de tempo.

Acho que você terá que corrigir o seu aplicativo Rails 5.0 ou o aplicativo Rails 4.2 para tornar os valores compatíveis entre si. Corrigir para que o Rails 4.2 possa lê-los pode parecer possível, mas você ainda terá problemas porque essas instâncias serão serializadas no formato 4.2 porque não podemos mudar como estão sendo escritas em um lançamento de patch.

Coloque o seguinte código em um inicializador em seus aplicativos Rails 4.2 e tudo deve funcionar:

# https://github.com/rails/rails/issues/26296
ActiveSupport::TimeZone.class_eval do
  def init_with(coder) #:nodoc:
    initialize(coder['name'])
  end

  def encode_with(coder) #:nodoc:
    coder.tag ="!ruby/object:#{self.class}"
    coder.map = { 'name' => tzinfo.name }
  end
end

ActiveSupport::TimeWithZone.class_eval do
  def init_with(coder) #:nodoc:
    initialize(coder['utc'], coder['zone'], coder['time'])
  end

  def encode_with(coder) #:nodoc:
    coder.tag = '!ruby/object:ActiveSupport::TimeWithZone'
    coder.map = { 'utc' => utc, 'zone' => time_zone, 'time' => time }
  end
end

Normalmente, nesses tipos de situações, faremos a migração para frente, por exemplo, quando introduzimos a serialização de sessão JSON em 4.1, oferecemos um híbrido que lia as serializações existentes e as convertia, mas não uma migração para trás, onde uma sessão JSON criada em 4.1 funcionaria com um Aplicativo 4.0.

HTH e desculpe por qualquer incômodo causado.

Bem, eu fiz o oposto. Fiz um patch em meu aplicativo Rails 5.0.0.1 para escrever este objeto como o Rails 4.2 faria, copiando e adicionando este arquivo ao meu inicializador. Funciona também!

https://github.com/rails/rails/blob/4-2-stable/activesupport/lib/active_support/time_with_zone.rb

Obrigado pelo feedback.

Cumprimentos,

Esta página foi útil?
0 / 5 - 0 avaliações