【问题标题】:How to eliminate the use of this class variable如何消除使用这个类变量
【发布时间】:2014-07-28 09:08:38
【问题描述】:

Ruby 2.0.0、Rails 4.0.3、Windows 8.1 更新、PostgreSQL 9.3.3

我已经构建了一个 XLog 类,它允许我从我的应用程序中的任何控制器内将记录写入 PostgreSQL。但是,它是围绕类变量的使用而构建的。我想知道是否可以将其转换为实例变量。

在ApplicationController中,我实例化类变量并写入第一条记录:

  @@xaction = XLog.new
  @@xaction.info(
      controller: self.class.name,
      action:     "start",
      status:     "success"
  )

在应用程序中的任何时候,我都可以使用散列引用@@xaction.info 来记录任何事务的成功或失败。它有效...

XLog 是:

class XLog < ActiveRecord::Base
  def info hash
    logger.info "XLog " << hash.collect { |key, value| "#{key}: #{value}; "}.join  # map?
    XLog.create(
        controller: hash[:controller],
        associate:  hash[:associate],
        proxy:      hash[:proxy],
        object:     hash[:object],
        value:      hash[:value],
        action:     hash[:action],
        status:     hash[:status],
        message:    hash[:message]
    )
  end
end

【问题讨论】:

    标签: ruby-on-rails ruby postgresql logging


    【解决方案1】:

    您可以在类范围内使用实例变量:

    class << self
    
      def xaction
        @xaction ||= XLog.new
      end
    
    end
    
    def xaction
      self.class.xaction
    end
    
    xaction.info(
          controller: self.class.name,
          action:     "start",
          status:     "success"
    )
    

    如果我有我的 Ruby 权限,这应该允许您从控制器方法内以 xaction 访问 xaction,或从任何地方以 ApplicationController.xaction 访问 xaction。


    编辑:也许是更清洁的解决方案

    #app/controllers/application_controller.rb
    before_filter :start_log
    def start_log
      XLog.info(
          controller: self.class.name,
          action:     "start",
          status:     "success"
      )
    end
    
    
    
    
    #app/models/x_log.rb
    class XLog < ActiveRecord::Base
      def self.info(hash)
        @logger ||= Xlog.new
        @logger.info hash
      end
    
      def info(hash)
        logger.info "XLog " << hash.collect { |key, value| "#{key}: #{value}; "}.join  # map?
        XLog.create(
            controller: hash[:controller],
            associate:  hash[:associate],
            proxy:      hash[:proxy],
            object:     hash[:object],
            value:      hash[:value],
            action:     hash[:action],
            status:     hash[:status],
            message:    hash[:message]
        )
      end
    end
    

    只要在任何地方使用 XLog.info(hash) 即可。如果您愿意,可以在应用程序控制器中添加一些语法糖。

    【讨论】:

    • @A Fader Darkly。为了澄清,您会说将所有这些代码放在 ApplicationController 中,然后在每个控制器中将其作为 xaction 引用?或者,在模型或视图中作为 ApplicationController.xaction?
    • 如果您想将此行为保留在 ApplicationController 中,可以。感觉它应该做自己的初始化,为了方便起见,只是在 ApplicationController 中引用。请参阅@maringan 的单身想法。
    • 我添加了一个不太显眼的解决方案供您考虑。
    【解决方案2】:

    我认为 Xlog 应该调用 Singleton 类:

    class Log
      include Singleton
    
      def info(hash)
        Xlog.create(
            controller: hash[:controller],
            associate:  hash[:associate],
            proxy:      hash[:proxy],
            object:     hash[:object],
            value:      hash[:value],
            action:     hash[:action],
            status:     hash[:status],
            message:    hash[:message]
        )
      end
    end
    

    您可以在应用程序控制器中使用around_filter:

     around_filter :wrap_actions
    
     def wrap_actions
        x_log = Log.instance
        begin
          yield
          x_log.info(hash_success)
        rescue
          x_log.info(hash_fail)
        end
      end
    

    【讨论】:

    • 我喜欢使用单例来避免混乱和 around_filter。但是,您似乎缺少 logger.info 行,我不确定您为什么将 Xlog.create(...) 分配给 Xlog。
    • 我认为这是正确的方向?修改可以解决问题吗?
    猜你喜欢
    • 2015-07-04
    • 1970-01-01
    • 2020-06-20
    • 2022-01-13
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多