我想:
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级开始时,是否有比这四行短的方式?
我想按批次登录:
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
有没有办法可以干净利落地做到这一点?从方法逻辑中分离日志记录?
答案 0 :(得分:5)
这是我在遇到像你这样的问题时一直在做的事情:
class A
class << self
include MyLog
def log_path
'log/a.log'
end
end
delegate :log_path, :log, to: "self.class"
end
否则,选择最佳编程方法取决于您的情况,您重复使用脚本的频率,在其生命周期内需要重构多少次,等等。但无论如何,请不要尝试保存代码的行,尝试在下次自己阅读代码后为自己省去麻烦。
关于你的第二个问题,你面临的主要困境是,是否值得你介绍事件类:
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
答案 1 :(得分: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
像这样,一旦包含模块,类和实例方法都会自动定义。
对于第二个问题,请使用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
答案 2 :(得分:2)
如果您的日志路径始终应该是log/<lower_case_class>.log
,那么您可以在模块中实现它,您应该没问题。当执行模块的方法时,self仍然是调用该方法的对象,因此您可以说self.class并获取A而不是您的模块名称。
查看此问题的已接受答案,了解如何为您的班级以及该班级的对象添加方法
Why 'self' method of module cannot become a singleton method of class?
您可以使用Enumerable#partition来分解您的所有&#34; (你实际上没有说明你发布的代码中的位置)
expired, failed = all.partition(&:expire)