Erubis
gems 使えるコンテキストでは全部 Erubis 使うようにしよう。Erubis::EscapedEruby つかおう。
デメリットがない
gems 使えるコンテキストでは全部 Erubis 使うようにしよう。Erubis::EscapedEruby つかおう。
デメリットがない
なんで gem spec のファイルを YAML にしちゃったのかなぁ。Ruby で eval できるコードを吐けばもっと高速で YAML への依存が減らせるのに
この場合 YAML 使う理由ってなんだろう。他の言語から読みかきするわけじゃないしというか結局吐く YAML が Ruby 依存になるし……
とおもったら、ローカル spec は Ruby で eval できるコード吐いてた (キャッシュは Marshal)。すいませんすいません。サーバとのやりとりだけ YAML なのかな
RubyGems みたいに、あらかじめ spec をキャッシュしておく、みたいなのが許されるなら、こういうのもありなんじゃないかなぁと思った。以下の実装はいろいろだめなところがあるだろうけど…… (プラットホーム依存のところがほげほげとか)
# module 名 -> ファイル名へのハッシュテーブルを作る
# ruby 起動しまくって時間がかかるので前もってキャッシュする
require "pathname"
module_files = {}
$LOAD_PATH.each do |path|
path = Pathname.new(path)
next if path.relative?
Pathname.glob(path + "**/*").each do |t|
next unless t.file?
next if t.to_s =~ /tk/
puts t
ENV.delete("RUBYOPT")
ret = nil
IO.popen("ruby", "r+") do |io|
io.puts <<-CODE
# 自分自身はロード済みにしないと、ループして require している場合にまずい
$LOADED_FEATURES << '#{t.relative_path_from(path)}'
$depend_lib = []
def __modules
ret = []
ObjectSpace.each_object(Module) do |o|
ret << o
end
ret
end
alias _require_orig require
def require(lib)
prev = __modules
ret = _require_orig(lib)
if ret
$depend_lib.concat(__modules - prev)
end
ret
end
def set_trace_func(*)
end
prev = __modules
stdout = STDOUT.dup
STDOUT.reopen($stderr)
begin
_require_orig '#{t}'
ensure
STDOUT.reopen(stdout)
print Marshal.dump((__modules - prev - $depend_lib).map {|i| i.to_s })
STDOUT.flush
exit!
end
CODE
io.close_write
ret = io.read
ret = Marshal.load(ret)
end
ret.each do |m|
(module_files[m] ||= []) << t.to_s
end
end
end
require "pp"
File.open("module.cache", "wb") do |f|
Marshal.dump(module_files, f)
end本体
def use(mod)
mod = mod.to_s
mods = Marshal.load(File.read("module.cache"))
raise LoadError, "#{mod} is not found." unless mods[mod]
mods = mods[mod].map {|i|
[i, i.split(File::ALT_SEPARATOR || File::SEPARATOR).size]
}.sort_by {|i,ii|
ii
}
mods.select {|i,ii| ii == mods.first[1] }.each do |i,ii|
require i
end
end
use %(Test::Unit::AutoRunner)
use %(Test::Unit::TestCase)
class UseTEST < Test::Unit::TestCase
def test_success
use %(Pathname)
assert_kind_of Class, Pathname
use %(Test::Unit::AutoRunner)
assert_kind_of Class, Test::Unit::AutoRunner
use %(ERB)
assert_kind_of Class, ERB
use %(ERB::Util)
assert_kind_of Module, ERB::Util
use %(WEBrick)
assert_kind_of Module, WEBrick
use %(Net::HTTP)
assert_kind_of Module, Net
assert_kind_of Class, Net::HTTP
assert_raise(LoadError) do
use %(NotInTableModule)
end
end
end
Test::Unit::AutoRunner.run($0 != "-e" && $0)テーブルは require しているファイルに定義されているクラスを除いているので、test/unit.rb みたいな require をしている場合、そのファイルにいくら定義があっても「クラスの再定義/上書き」という判断しかできないので、use "Test::Unit" とかしても test/unit.rb は読みこまれない。
あとは webrick なんかを例にとると webrick.rb は他のファイルを require するだけなので、直接はこのファイルはモジュールハッシュ上にあらわれない。use では同じ深さを持っていて、WEBrick を定義している全てのファイルを require してる。
もっとたくさんテスト書いて、実装精密にすればつかえるかなぁ……
どっかのサーバで rubyforge の gems をミラーして解析して、このテーブルをつくっておいて、パッケージ検索できるようにするとか、あるいはそのままパッケージシステムにしてしまうとかがおもしろいかなぁ。既存の gems をそのままもってこれてたのしそう。
C-f (Vim の Command モードとかのバインド) で開くようにしてみた。
でも input type="text" には無力なんだなぁ
require "rubygems" require "pathname" require "active_record" ActiveRecord::Base.establish_connection( :adapter => "sqlite3", :database => "test.db" ) class Article < ActiveRecord::Base end
~/tmp を定期的に晒すとか面白そう。でもだいたい公開できない。
はらいたい
#!ruby
require "nkf"
data = DATA.read.split(/¥n/)
def copy(str)
puts str
str = NKF.nkf("-s", str)
IO.popen("pbcopy", "w") do |io|
io.print str
end
str
end
copy(data.shift)
board = `pbpaste`
loop do
boardn = `pbpaste`
boardn = nil if boardn.empty?
unless board == boardn
str = data.shift
copy(str)
end
board = `pbpaste`
sleep 0.3
end
__END__
1
2
3NSPasteboard はデータ取得がいまいち安定しない。
よくわかんないなぁ。変更して「まだあるかもしれない」とおもってリリースしないでいると、「あれどこまでの変更をリリースしたっけ」とか思ってしまう。うーん
リリースしようとするとエラーでるなぁ。普通にウェブからやってもエラーでる。rubyforge (gem のほう) は、hpricot とか使って Error: の部分を出すようにすべきだ……