【问题标题】:Overriding ActiveRecord Column Methods with a Mixin使用 Mixin 覆盖 ActiveRecord 列方法
【发布时间】:2011-03-10 02:05:30
【问题描述】:

我正在尝试这样做,以便我可以配置一些列以始终根据用户设置转换为不同的时区。我希望配置如下:

class MyClass
  include TimeZonify
  tz_column :col1, :col2
end

我的 mixin 显然不正确,但它看起来像这样:

module TimeZonify
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods

    def tz_column(*columns)
      columns.each do |column|
        instance_eval do   # <-- obviously this block does not get executed
          <<-CODE
            def #{column}
              super.in_time_zone("Lima")
            end
          CODE
        end
      end
    end

  end

end

所以现在,当我调用 MyClass.new.col1 时,它将不再是 UTC,而是用户个人资料中的任何时区。

【问题讨论】:

    标签: ruby-on-rails ruby activerecord metaprogramming


    【解决方案1】:

    如果您使用的是 Rails,则时区支持必须开箱即用。你可以有different time zone for each user


    我不建议覆盖日期/时间方法访问器,因为那样您还需要覆盖 setter。

    如果不这样做,每次执行时(例如,更新时)都会导致无效的结果。

    original = it.effective_at
    it.effective_at = it.effective_at # it +TimeZone
    it.effective_at = it.effective_at # it +TimeZone
    original == it.effective_at # => false - every assignment actually changes the time by +TimeZone
    

    但如果您需要一个快捷方式来显示,我建议您使用此方法的扩展:

    it.effective_at_local

    可以用mixin来实现:

    module TimeZonify
      def self.included(base)
        base.extend(ClassMethods)
      end
    
      module ClassMethods
    
        def tz_column(*columns)
          columns.each do |column|
            instance_eval do
              <<-CODE
                def #{column}_local
                  #{column}.in_time_zone("Lima")
                end
              CODE
            end
          end
        end
    
      end
    
    end
    

    顺便说一句,在相关说明中您可以使用TimeZone

    【讨论】:

    • mixin 实际上根本无法定义方法。所以 abc_local 方法永远不会被定义。我想做的主要事情是能够通过tz_column :col1, :col2 进行配置
    猜你喜欢
    • 2016-06-04
    • 2010-09-27
    • 1970-01-01
    • 2011-07-02
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多