2007년 12월 3일 월요일

컨닝 페이퍼 (cheet sheets)


멋진 RubyGem 을 발견했습니다.
http://cheat.errtheblog.com/
Cheet Sheet 란 것인데, 저에겐 루비/레일스 개발을 위한 최고의 선물입니다.
$ cheat rspec
rspec:
INSTALL
=======
INSTALL rspec
=============
$ sudo gem install rspec
OR
$ ./script/plugin install -x
svn://rubyforge.org/var/svn/rspec/tags/CURRENT/rspec

INSTALL rspec_on_rails plugin
=============================
$ ./script/plugin install -x
svn://rubyforge.org/var/svn/rspec/tags/CURRENT/rspec_on_rails

... 이하 생략
$ cheat sheets 해 보시면 많은 커닝 페이퍼를 얻을 수 있습니다. 

2007년 11월 28일 수요일

blogger.com 에 Syntax Highlight 코드 사용 사투기


blogger.com 에 포스팅한 내용에 Syntax Highlight 된 루비 코드를 보기 위해서 한나절이 걸렸다.

deepblue 님의 블로그를 보니까 코드 내용을 이쁘게 보여주는 SyntaxHighlighter 라는 Javascript 를 사용하고 있는걸 발견하고, 그걸 도입해 보기로 했다. 하지만 css, javascript 를 연결을 해줘야 하는데, blogger.com 에 추가 파일을 올리는 방법을 찾을 수 없었다. 그럼 일단 이건 포기...

그렇다면 ruby 를 syntax highlight 된 html 로 변환해 주는 변환 모듈을 찾아봤는데, rubyforge 에서 Syntax 라는 gem module 를 발견했다. 그리고 Howto format ruby code for blogs 를 참고해서 ruby2html 을 만들었다. 그런데 ruby2html 로 만들어낸 html 이 indent 문제가 있었다. indent 처리를 잘 못하는 것이다. 


#!/usr/bin/env ruby

require 'rubygems'
require 'syntax/convertors/html'

if ARGV.size > 0
@ruby_file = ARGV[0]
code = File.read(@ruby_file)
else
puts 'Usage: ruby ruby2html [file]'
exit(0)
end

convertor = Syntax::Convertors::HTML.for_syntax('ruby')
html = convertor.convert(code)

@html_file = File.split(@ruby_file)[1] + ".html"
open(@html_file, 'w') do |f|
begin
f.puts(html)
ensure
f.close
end
end

다시 SyntaxHighlighter 에 도전해 보기로 했다. 일단 css, javascript 를 개인 웹 서버에 올려놓고 blogger.com 에서 링크를 거는 방법으로 처리하기로 했다(그냥 설치형 블로그를 쓸가 잠시 고민했음). 이 방법을 잘 될것 같았는데, 이번에는 blogger.com 의 xml 템플릿이 말썽을 일으키는 것이다. blogger.com 이 '\n' 을 자동으로 바꾸면서 코드를 제대로 표시 못하는 것이다. 하지만 투자한 시간이 아까워서 해결 방법을 좀 더 찾아보기로 했다.

SyntaxHighlighter 의 Issue 를 검색해서 해결 방법을 찾았다. dp.SyntaxHighlighter.HighlightAll 함수를 패치 하고 나니까 제대로 동작하게 됐다. 휴우~  똑같은 문제로 고민하는 사람에게 도움이 됐으면 한다.

구글 입사 문제 그리고 Fixnum 확장 후 profile


우연히 구글 입사 문제 라는 블로그를 보다가 소스 코드에서 사용하고 있는  scan 함수가 왠지 어색해 보였다. 그래서 Fixnum 을 확장해 봤는데, 내가 만든 코드로 돌려보고 좌절했다.
 
Regexp::scan 함수는 c source 로 작성이 되어 있고, 내가 만든 코드는 ruby 를 확장한 거라서 코드를 읽기는 쉬우나 속도에 문제가 있다. 다시 한번 느끼는 거지만 속도가 중요하다면 반드시 c source 로 모듈을 개발해야 한다. 


- 원본 소스와 profile 결과


require 'profile'

i = 0
(1..999999).each do |m|
i += m.to_s.scan(/1/).length
if i == m and i != 1
puts i
break
end
end

$ ruby quiz1.rb -r profile
199981
% cumulative self self total
time seconds seconds calls ms/call ms/call name
67.67 27.17 27.17 1 27170.00 40150.00 Range#each
7.97 30.37 3.20 199981 0.02 0.02 String#scan
6.45 32.96 2.59 199982 0.01 0.01 Fixnum#to_s
6.18 35.44 2.48 199981 0.01 0.01 Fixnum#+
6.13 37.90 2.46 199983 0.01 0.01 Fixnum#==
5.60 40.15 2.25 199981 0.01 0.01 Array#length
0.00 40.15 0.00 1 0.00 0.00 Kernel.puts
0.00 40.15 0.00 2 0.00 0.00 IO#write


- fixnum_ex.rb 를 사용한 소스와 profile 결과


class Fixnum
def to_a
number = self
digits = []
while true
ret = number.divmod(10)
digits.unshift(ret[1])
break if ret[0] == 0
number = ret[0]
end
digits
end

def each
number = self
while true
ret = number.divmod(10)
yield(ret[1])
break if ret[0] == 0
number = ret[0]
end
end
end



require 'profile'
require 'fixnum_ex'

i = 0
(1..999999).each do |m|
m.each { |n| i += 1 if n == 1 }
if i == m and i != 1
puts i
break
end
end

$ ruby quiz2.rb -r profile
199981
% cumulative self self total
time seconds seconds calls ms/call ms/call name
64.79 202.36 202.36 199981 1.01 1.48 Fixnum#each
14.21 246.76 44.40 3066362 0.01 0.01 Array#[]
10.79 280.47 33.71 2377545 0.01 0.01 Fixnum#==
5.19 296.68 16.21 1088781 0.01 0.01 Fixnum#divmod
4.12 309.55 12.87 1 12870.00 312350.00 Range#each
0.90 312.35 2.80 199981 0.01 0.01 Fixnum#+
0.00 312.35 0.00 1 0.00 0.00 Kernel.puts
0.00 312.35 0.00 1 0.00 0.00 Fixnum#to_s
0.00 312.35 0.00 2 0.00 0.00 Module#method_added
0.00 312.35 0.00 1 0.00 0.00 Kernel.require
0.00 312.35 0.00 2 0.00 0.00 IO#write
0.00 312.35 0.00 1 0.00 312350.00 #toplevel