2008年 02月 04日

単体で (Rails をつかわずに) AR::Migration をつかうメモ

(ほぼ)最小構成の例: (acts_as_versioned もふくめて)

# Rakefile

require "rubygems"
require "rake"
require "active_record"

namespace :db do
	"Migrate database."
	task :migrate do
		require "db/connection"
		ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
	end
end
# db/connection.rb

require "logger"

ActiveRecord::Base.establish_connection({
	:adapter => "sqlite3",
	:dbfile  => "wiki.db",
})

ActiveRecord::Base.logger = Logger.new($stderr)

Dir.glob("model/*.rb") do |f|
	require f
end
# db/migrate/001_init.rb

class Init < ActiveRecord::Migration
	def self.up
		create_table :pages do |t|
			t.column :version    , :int
			t.column :title      , :text
			t.column :body       , :text
			t.column :created_at , :datetime
			t.column :updated_at , :datetime
		end
		Page.create_versioned_table
	end

	def self.down
		Page.drop_versioned_table
		drop_table :pages
	end
end
# model/page.rb

require "acts_as_versioned"

class Page < ActiveRecord::Base
	acts_as_versioned
end
  • AR::Migrator は undocumented なので変更される危険性がそれなりにあるかも ( # :nodoc: 指定)
  • AR::Base.logger を設定しないと Migrator うごかないよ

Rack + SQLite な Wiki をつくろうとおもったけどなんかめんどくさくなってしまった……

最もタメになる「初心者用言語」は Lazy-K !

  • Unlambda みたいに統一された書きかたじゃないよ! There is more than one way to do it!
  • Schemeみたいに括弧だらけじゃないよ! でもそこそこ括弧だらけにもできるよ! TIMTOWTDI!
  • Pythonみたいにインデントを強制されたりしないよ!
  • Ruby みたいに lambda がダサくないよ!
  • Javaみたいに「まずクラスを作れ」とか言われないよ!
  • 覚えることがかなりすくないよ! とりあえず S と K と I だけでいいよ!
  • 変数の名前に困らないよ! 変数なんてないよ!
  • チューリング完全だよ!
  • 継続なんて黒魔法ないよ!
  • 関数以外本当に何も存在しないよ!
  • Brainf*ck みたいに下品な名前じゃないよ! FUCK! FUCK!
  • 選べることは正しいんだよ!
  • 今流行りの Y combinator も ```ss`s``s`ksk`k``sii と書いたり、SS(S(S(KS)K))(K(SII)) って書いたり、****i*i*i*ii*i*i*i*ii**i*i*i*ii***i*i*i*ii**i*i*ii*i*i*i*ii*i*i*ii**i*i*ii***i*i*i*ii*ii*ii って書いたり、11111111000111110001111110001111111000111100111110001110011110011111110001111111110000011111111100000 って書いたりできるよ! JavaScript (笑) よりだいたいみじかいね! *1

*1: print-as-unlambda とかしただけで、僕は Y combinator を理解してません

2008年 02月 03日

Lingr メモ

1000speakers を観察

  • あんがい anon なユーザは少ない
  • 結構同一アカウントで別々のセッションをはっている人がいる
    • (o_id が違う==現行の lig.rb だと nick 一覧で重複する)
  • ログインしない状態でルームに入ったあと、ログインすると、o_id は同一のまま、セッションが更新されて認証済みユーザに昇格する
    • このときの system:enter/system:leave が謎い……発生しないっぽい?
      • ログイン済みかどうかで lig.rb は nick を変えているので enter/leave が発生しないなら処理いれてあげないといけない


lig.rb は human かどうかで nick の表示をかえれるようにしたい。というか nick の表示でやるより op でやったほうがいいかなぁ。human だったら @ でそうじゃなかったら @ なし。AWAY かどうかでもいいけどクライアントによっては @ よりわかりにくい。

Suppress system messages にチェックが入ってるチャンネルだと system:enter とかもおくられてこないっぽい?ので、system:enter/system:leave とかはユーザ管理に使用すべきじゃないっぽい。

そのかわり、occupants のリストが更新されると入ってくるので、それをつかって管理すべき

2008年 02月 02日

gerry++

2008年 02月 01日

citrus, UriInformation の分離

いま mixi とか plagger の db から情報とってくるとかが一つのファイルにつっこまれてて非常にダサイので、どうにかする。たぶん UriInformation の中でさらに Plugins インスタンスをもつようになる。

plugins/uri_handlers/{mixi,plagger,image,ftp,http,urn,amazon}

これらは、実行順を持っていて、あるプラグインで処理が確定したら後続のプラグインは実行されない。


ということをやりたいけど眠くてしかたないのでねる……テストどうやってかこう。

リロード可能なぷらぎん

もっといい実装ないかなぁ……

今の方法

  • 匿名モジュールでロード
    • プラギンクラスは、そのファイルとしてはトップレベルの定義になる module::Foobar
  • グローバルな環境からこのクラスにアクセスには困難 (匿名モジュールなので
  • ロードする環境がいつも必ず別々になるのでリロードのときに問題がおこりにくい (とおもう)
  • プラギンがさらにプラギン機構をもとうとするとめんどい。(ベースクラスも匿名モジュール内に入るので、直接参照できず、class_eval とかでロードする必要がある)

つけかえする方法

  • グローバルな名前空間にロード
    • プラギンクラスは Plugin::Foobar みたいになる
  • どこからでもアクセスできる
  • インスタンス化のタイミングとか参照状況によってはリロードしても GC きかない可能性があるかも (デバッグむずい)
  • リロードするときは remove_const / const_set
  • 継承とか依存があるときはそれらもよみなおさないと前の参照がのこる
2008年 01月 30日

chokan

名前変えたい。なんかいいアイデアないかな

いまやってること/やりたいこと (名前がきまらなくてコミットできない)

  • プラグインシステムを改訂 (ファイル名に依存しないように)
  • オレオレ RICE をやめて Net::IRC (これもオレオレ RICE なんだけど) に
  • RSpec 書きまくる。(プラグインも)

citrus (かいはつこーど)

名前来まんないので、citrus というコードで開発することにした。とかいってそのままこの名前に変えるかもしれないけど…… chokan の branches になってるけどオリジナルコードを殆ど使ってないw

http://svn.coderepos.org/share/lang/ruby/chokan/branches/citrus/

プラグイン機構との一番重要なところと、起動部分はできた。テストは全部 RSpec で、rcov でカバレッジみてる。
99.4% (run の部分のテストをどう書いていいかわからないお)

プラグインのテストをどうするか悩んでる。今のところ、プラグインファイルにそのまま書けるようにしてる。

テストを書きやすい設計ってすなわち疎結合で、いいものになる気がする。


あとどうでもいいけど chokan の kan は柑橘のカンであって、cho は IRC で名前を並べたとき、cho45 と並ぶようにしたからだったと思います。

rcov 楽しい

http://lab.lowreal.net/test/citrus/ (citrus の rcov)

やばい。RSpec との組み合わせが最強だなぁ。めんどくせーっておもって例外のところのテストをかかなかったりするけど、100% をめざすと書かざるをえない。

テストファーストはやってみたりやらなったり>< 慣れない

2008年 01月 28日

wikiforme の (だいたい) 最小の syntax 定義と部分編集

セクション編集ができる wiki がほしいなぁとおもって wikiforme だとどうなんかなぁと思いつつ、syntax 定義をもぞもぞ書く (内部でどういう構造になってるのかよくわからないのでためしに)

HTML のセクションから、ソースのその範囲を取得できればいいのだから、トップレベルのセクションを列挙して、番号をふり (直接ふらなくてもいいけど)、それがソースではどの範囲にあたるかをとれればいい。行番号は parse した直後のやつには含まれているけど、それを保存して、構造化 HTML をはく process はないみたいなので自分で書くしかない。


とおもいながら書いていたのだけど、process で行番号がとれないことに気付いた。行番号はエラー表示のためだけにあるみたいだ (assemble.rb L42 あたり)。なおそうと思うと結構広範囲に影響しそうでやりにくい。のでとりあえずやめた。

#!/usr/bin/env ruby

require "pp"

$LOAD_PATH << "core"

require "wikiforme"

wikiforme = WikiForme.new("foobar.4me")

array =  wikiforme.parse(DATA)

params    = {}
root      = :page
root_text = "test"

pp array

p array.assemble(params, root, root_text).process(:html)

__END__
** Foobar

aaa

** Baz

bbb
# foobar.4me/foobar.rb

Format.block :page  do
	contain        :section
	module_eval do
		def process_html
			@children
		end
	end
end

Format.block :section do
	default_syntax "**"
	contain        :@contents, :@blank
	module_eval do
		def preprocess
			super
		end

		def process_html
			p self
			XML[
				:div, {:class => "section"},
					[:div, {:class => "heading"}, @text.process],
					@children
			]
		end
	end
end

Format.block :blank do
	default_syntax :blank
	group          :@blank
	module_eval do
		def process_html
			""
		end
	end
end

Format.block :paragraph do
	group          :@contents
	default_syntax :text
	module_eval do
		def process_html
			XML[:p, @text.process]
		end
	end
end

勝手にブロック引数とって DSL っぽく書けるようにした。(検索しにくくなるのであんまりファイルわけたくない。ファイルわけないとなるとインデントして定義の範囲を明確にしたい。)