요즘은 코코아, 루비, 그리고 jquery에 꽂혀 있다.
꽂혀만 있고 공부는 잘 안한다. ...
업무 중에 시간이 좀 남아서 일과 직접적으로 연관되는 jquery와 루비가 공부 후보로 올라왔는데
낮에 jquery를 처음 써보면서 공부를 약간 했었기 땜에 남는 저녁시간은 레일스를 보기로 했다.
액티브서포트부터 시작해서 내키는 데까지 코드를 쭉 훑어보기로 했다.
눈으로만 훑으면 나중에 다 까먹으니까 간단히 정리만 해 두기로 했다.
abc 순으로 제일 위에 있는 b*.rb 들을 봤다. a로 시작하는 파일은 없었다.
lib/buffered_logger.rb
- module ActiveSupport
# Inspired by the buffered logger idea by Ezra
class BufferedLogger
module Severity
DEBUG = 0
INFO = 1
WARN = 2
ERROR = 3
FATAL = 4
UNKNOWN = 5
end
include Severity - ...
class 안에 module 선언해서 enum처럼? 혹은 C의 define처럼? 활용한다. 오오.
- module ActiveSupport
# Inspired by the buffered logger idea by Ezra
class BufferedLogger - ...
- for severity in Severity.constants
class_eval <<-EOT, __FILE__, __LINE__
def #{severity.downcase}(message = nil, progname = nil, &block)
add(#{severity}, message, progname, &block)
end
def #{severity.downcase}?
#{severity} >= @level
end
EOT
end - ...
메서드 선언을 class_eval로 하는 코드.
logger.warn, logger.info, logger.warn? logger.info? 등의 메서드를 정의한다. 심플한 코드라 나중에 쉽게 참조하기 좋을듯.
- # Set the auto-flush period. Set to true to flush after every log message,
# to an integer to flush every N messages, or to false, nil, or zero to
# never auto-flush. If you turn auto-flushing off, be sure to regularly
# flush the log yourself -- it will eat up memory until you do.
def auto_flushing=(period)
@auto_flushing =
case period
when true; 1
when false, nil, 0; MAX_BUFFER_SIZE
when Integer; period
else raise ArgumentError, "Unrecognized auto_flushing period: #{period.inspect}"
end
end
auto_flushing= 은 period를 인자로 받는 것 같지만 boolean 값도 받아서 처리한다.
메서드는 한가지 일을 해야 하지만, 한 종류의 인자를 받을 필요는 없다. 하튼 자기 할 일만 잘하면 된다. 개발자 헛갈리지 않게.
이같은 코드는 생성자에도 존재하는데 바로 @log를 생성하는 부분.
- def initialize(log, level = DEBUG)
@level = level
@buffer = []
@auto_flushing = 1
@no_block = false
if log.respond_to?(:write)
@log = log
elsif File.exist?(log)
@log = open(log, (File::WRONLY | File::APPEND))
@log.sync = true
else
FileUtils.mkdir_p(File.dirname(log))
@log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
@log.sync = true
@log.write("# Logfile created on %s" % [Time.now.to_s])
end
end
write가 있으면 그냥 쓴다. 왜냐면 우린 @log.write만 쓸 꺼니까..
그렇지 않으면 파일 이름으로 간주하고, 찾아본다. 그래도 없으면 디렉토리+파일 이름으로 간주하고 디렉토리도 만들고 찾는다.
파일이 없는 경우 이 로그 파일은 새 것이므로 맨 윗줄에 주석까지 달아주는 센스를 보여준다.
후에 write외에 다른 메서드를 쓸 일이 생기는데... 바로 close할 때다.
- def close
flush
@log.close if @log.respond_to?(:close)
@log = nil
end
@log가 IO 객체? 라면 아마 close를 모두 가지고 있을 것이다. 위위 코드에서 두번째와 세번째 경우는 모두 close를 가지고 있을 것이다.
하지만 직접 구현한 객체라면? 이 객체는 write는 있는데 close는 없다면?
그런 경우에 위 close 메서드의 두번째 줄 같은 코드가 필요하다.
duck type을 이용하여 @log를 생성하여 쓰고... close는 있으면 하고 없으면 말고.
아.. 아름답다. (라고 세뇌한다.-_-)
오늘은 비도 오고 하니까 이만
References
이 글은 스프링노트에서 작성되었습니다.

