1

をお願いします:

module MyLog

  def log
    unless @log
      @log = Logger.new(log_path)
      @log.formatter =  proc do |severity, datetime, progname, msg|
        "#{datetime} #{msg}\n"
      end
    end
    @log
  end

end

次のように他のクラス間で再利用するには:

Class A
  def self.log_path; 'log/a.log' end
  def log_path; 'log/a.log' end
  include MyLog
  extend  MyLog

  def some_method
    log.debug 'some thing'
  end

  def self.some_class_method
    log.debug 'in a class method'
  end

end

クラスAの最初の4つのラインよりも短い方法はありますか?

別物

バッチごとにログを記録したい:

def expire
  expired_ids = []
  failed_ids  = []

  all.each do |event|
    if event.expire # saves record
      expired_ids << event.id
    else
      failed_ids << event.id
    end
  end

  log.debug "These ids were expired: #{ expired_ids }"
  log.debug "These ids failed to expire: #{ failed_ids }"
end

これをきれいに行う方法はありますか?メソッドロジックからロギングを分離しますか?

4

3 に答える 3

6

これは、あなたのような問題に直面したときに私が最近行っていることです:

class A
  class << self
    include MyLog

    def log_path
      'log/a.log'
    end
  end

  delegate :log_path, :log, to: "self.class"
end

それ以外の場合、最適なプログラミング アプローチの選択は、状況、スクリプトを再利用する頻度、有効期間中にスクリプトをリファクタリングする必要がある回数などによって異なります。ただし、いずれにせよ、コードを保存しようとしないでください。次にコードを読むときは、問題を自分自身に保存するようにしてください。

2 番目の質問については、あなたが直面している主なジレンマは、わざわざ Events クラスを導入する価値があるかどうかです。

class Events < Array
  def foobar
    each_with_object [[], []] do |event, (expired_ids, failed_ids)| 
      ( event.expire ? expired_ids : failed_ids ) << event.id
    end
  end
end

そして、時が来たら:

def expire
  expired_ids, failed_ids = Events[ all ].foobar
  log.debug "These ids were expired: #{ expired_ids }"
  log.debug "These ids failed to expire: #{ failed_ids }"
end
于 2013-08-07T07:06:06.267 に答える
3

フックを使用して、includedクラス メソッドとインスタンス メソッドを自動的に定義できます。

module MyLog

  def self.included(base)
    base.extend(Methods)
    base.send(:include, Methods)
  end

  module Methods
    def log_path; 'log/a.log' end

    def log
      unless @log
        @log = Logger.new(log_path)
        @log.formatter =  proc do |severity, datetime, progname, msg|
          "#{datetime} #{msg}\n"
        end
      end
      @log
    end
  end

end

このように、モジュールがインクルードされると、クラス メソッドとインスタンス メソッドの両方が自動的に定義されます。

2 番目の問題についてはpartition、値を使用して返し、ログに記録します。

def expire
  all.partition(&:expire)
end

次に、 を呼び出す場所でexpire、戻り値をログに記録できます。

def call_something
  expired, failed = expire
  log.debug "These ids were expired: #{expired.map(&:id)}"
  log.debug "These ids failed to expire: #{failed.map(&:id)}"
end
于 2013-08-07T07:26:08.380 に答える
2

ログ パスが常に であると想定されている場合log/<lower_case_class>.logは、それをモジュールに実装できます。問題はありません。モジュールのメソッドが実行されるとき、self はメソッドが呼び出されたオブジェクトのままであるため、self.class と言って、モジュール名ではなく A を取得できます。

クラスとそのクラスのオブジェクトの両方にメソッドを追加する方法については、この質問に対する受け入れられた回答を確認してください

モジュールの「自己」メソッドがクラスのシングルトンメソッドになれないのはなぜですか?

Enumerable#partition を使用して、「すべて」を分割できます (投稿したコードのどこから来たのかは実際には言いませんでした)

expired, failed = all.partition(&:expire)
于 2013-08-07T05:44:38.527 に答える