为什么实现ActiveRecord访问器会改变时间的工作方式?

时间:2015-02-11 18:58:27

标签: datetime ruby-on-rails-4 activerecord

我已经将一个错误缩小到一个非常具体的例子。我无法找到这种行为的原因。

行为就是这样:

  1. 假设一个带有日期时间字段的ActiveRecord(在我的情况下它是Offer)(在我的情况下是Scheduled_at
  2. Time.use_zone("UTC")块中设置字段。
  3. 如果没有其他干预措施,请在块内外阅读scheduled_at.hour
  4. 断言块内外的值是相同的。
  5. 重新运行上述内容,但只读取该块的scheduled_at.hour
  6. 断言与步骤4中的值相同。
  7. 一切都很好。

    现在我们打开Offer类并执行以下操作:

    Offer.class_eval do
      def scheduled_at=(scheduled_at)
        write_attribute(:scheduled_at, scheduled_at)
      end
    
      def scheduled_at
        read_attribute(:scheduled_at)
      end
    end
    

    执行上述步骤,注意我们没问题,直到我们进入第6步。

    现在scheduled_at会产生副作用,这对我们第一次读它时很敏感!

    问:这是什么原因造成的?这是预期的吗?一个错误?

    代码如下:

      def test_strangeness
        puts "first run"
        do_stuff
    
        puts "opening class"
        Offer.class_eval do
          def scheduled_at=(scheduled_at)
            write_attribute(:scheduled_at, scheduled_at)
          end
    
          def scheduled_at
            read_attribute(:scheduled_at)
          end
        end
    
        puts "second run"
        do_stuff
      end
    
      def do_stuff
        o1 = Offer.new
        Time.use_zone("UTC") do
          o1.scheduled_at = Time.new(2015, 1, 2, 3, 45, 56, 0)
          o1.scheduled_at.hour
        end
        hour1 = o1.scheduled_at.hour
        puts "hour1 is #{hour1}"
    
        o2 = Offer.new
        Time.use_zone("UTC") do
          o2.scheduled_at = Time.new(2015, 1, 2, 3, 45, 56, 0)
        end
        hour2 = o2.scheduled_at.hour
        puts "hour2 is #{hour2}"
    
        assert_equal hour1, hour2
    
      end
    

0 个答案:

没有答案