カテゴリ別 2003年 | 2004年 | 2005年 | 2006年 | 2007年 | 2008年
知り合いサイト: よんだもの / 暴想 / Linuxでやる夫 / 新宿Vipper / 僕だけが幸せになればいいのに。
ネット接続を光に変えたところ、無線 LAN 設定がうまくいかなかったため、この自宅サーバがしばらく停止していました。今まで使っていた無線 LAN ルータをブリッジ接続させて、自宅サーバがインターネットに繋がるようになりました。無線 LAN ルータは 802.11b なので光の恩恵にはあずかれませんが。
Ruby on Rails で作られたブログツールの typo が 2.5 にバージョンアップしました。試しに設置しています。svn head ベースで ri18n を使った日本語化をしていましたので、後でパッチをアップします。
上に書いた typo 2.5 (一部)日本語化パッチを作りました。
大体こんな感じであててください(下のままではたぶんうまくいきません)。
課題点
Rite(Ruby2.0) の VM 候補である YARV の新バージョンがリリースされました。
とりあえずごく簡単に Language Shootout のベンチマークプログラムで速さを確かめてみました。比較対象は ruby-1.8.2 です。プログラムは計算しまくる系を選んでいます(注:時間がなかったのでそれぞれ一発実行の時間です)。
| プログラム | 1.8.2 | YARV0.3.0 | 1.8.2/YARV0.3.0比 |
|---|---|---|---|
| ackermann | 0m3.979s | 0m0.640s | 6.2 倍 |
| fannkuch | 0m45.853s | 0m24.518s | 1.9 倍 |
| harmonic | 0m30.129s | 0m13.618s | 2.2 倍 |
| mandelbrot | 0m49.869s | 0m25.740s | 1.9 倍 |
| nsieve | 1m16.787s | 0m28.463s | 2.7 倍 |
| nsieve | 3m3.958s | 1m9.861s | 2.6 倍 |
| random | 0m5.582s | 0m2.763s | 2.0 倍 |
| takfp | 4m42.997 | 1m33.555s | 3.0 倍 |
おお。ちゃんと速いしちゃんとプログラムが実行できてます。先が楽しみですね。実行環境は以下の通り。
本文中に空行があると RSS で別々の item になってしまいますね……気をつけないと。
久しぶりに色々まとめ買い。
主キーの命名規則が異なる複数のデータベースに対して、一つのプログラムからアクセスする方法を調べていました。
例えば、以下のようなテーブルがあるとします。
| データベース名 | テーブル名 | 主キー |
|---|---|---|
| foo | mt_entry | entry_id |
| bar | totals | id |
mt_entry は主キーの prefix としてクラス名が付いています。totals は ActiveRecord 標準に合わせた設計です。
さて、主キーの命名規則を指定するには、ActiveRecord::Base の primary_key_prefix_type を変更します。
module MT
class Entry < ActiveRecord::Base
def self.table_name
"mt_entry"
end
end
end
ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "rails",
:password => "rails",
:database => "foo"
)
あるいは直接主キーの名前を指定することもできます(drawnboy さんありがとう)。
module MT
class Entry < ActiveRecord::Base
set_primary_key "entry_id"
end
end
これによって、
MT::Entry.find(1)
を実行すると以下の SQL が発行されることになります。
SELECT * FROM mt_entry WHERE mt_entry.entry_id = 1 LIMIT 1
一方、shukei テーブルに対応するクラスとデータベース接続は以下のようになります。
class Total < ActiveRecord::Base
end
Total.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "rails",
:password => "rails",
:database => "bar"
)
これに対して、find メソッドを実行しようとすると、
Total.find(1)
エラーとなります。
/usr/local/ruby/lib/ruby/gems/1.8/gems/activerecord-1.11
.1/lib/active_record/connection_adapters/abstract_adapter.rb:462:
in `log': Unknown column 'total.total_id' in
'where clause': SELECT * FROM total WHERE total.total_id = 1
LIMIT 1 (ActiveRecord::StatementInvalid)
クラスごとに primary_key_prefix_type を分けるのが無理なのであれば、ファイルに書き出して別のプロセスで読み出すことも考えましたが、カッコ悪いので却下。で、少し ActiveRecord のコードを読んでみました。
primary_key_prefix_type は ActiveRecord::Base のクラス変数として定義されています。これは、アクセサメソッド(cattr_accessor)によって外部からアクセスできるようになっています。Ruby の言語仕様として親クラスで定義されたクラス変数は子クラスで共有されます(注:1.8系のみ。1.9 系ではクラスプライベートです)。つまり、
Total.primary_key_prefix_type = nil # Total のだけ変更したつもり
p ActiveRecord::Base.primary_key_prefix_type
#=> nil
あるいは
class Total
@@primary_key_prefix_type = nil # Total のだけ変更したつもり
end
p ActiveRecord::Base.primary_key_prefix_type
#=> nil
となってしまいます。
と、ここで、primary_key_prefix_type が常にアクセサメソッド経由でアクセスされているのであれば、オーバーライドしてしまえばいいのではないか?と考えました。
class Total < ActiveRecord::Base
def self.primary_key_prefix_type
nil
end
end
Total.find(1)
期待する SQL を発行するようになりました。
SELECT * FROM total WHERE total.id = 1 LIMIT 1
デフォルト設定ではない MT::Entry の方に定義することにして、これまでのまとめのコードを書きます。
module MT
class Entry < ActiveRecord::Base
def self.table_name
"mt_entry"
end
def self.primary_key_prefix_type
:table_name_with_underscore
end
end
end
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "rails",
:password => "rails",
:database => "foo"
)
class Total < ActiveRecord::Base
end
Total.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "rails",
:password => "rails",
:database => "bar"
)
MT::Entry.find(1)
Total.find(1)
副作用が生じるケースがあるかな?
主キーとテーブル名の命名規則の変更を複数のクラスにまとめて適用するならこんな感じ?
module MT
module Common
def table_name_prefix
"mt_"
end
def pluralize_table_names
false
end
def primary_key_prefix_type
:table_name_with_underscore
end
end
class Entry < ActiveRecord::Base
extend Common
end
class Blog < ActiveRecord::Base
extend Common
end
end
2007/08/13 追記: 現在は 1.9 も 1.8 と同じ仕様です。Ruby 1.9 でクラス変数が継承されないのは間違いを参照ください。
備忘録です。以下を foo.rb とします。
class Foo
@@a = 1
def self.a
@@a
end
end
class Bar < Foo
end
p Bar.a
class Bar
def bar
@@a
end
end
p Bar.new.bar
ruby 1.8 での実行結果。
$ ruby18 -v ruby 1.8.2 (2005-02-15) [i686-linux] $ ruby18 foo.rb 1 1
ruby 1.9 での実行結果。
$ ruby19 -v
ruby 1.9.0 (2005-02-14) [i686-linux]
$ ruby19 foo.rb
1
foo.rb:12:in `bar': uninitialized class variable @@a in Bar (NameError)
from foo.rb:15
チケットはもうないものと思って買わなかったのでした。速攻で売り切れたのは夜だけだったんですね。Web+DB Press の Rails 特集を読んだり、積みゲーになっていたひぐらし を進めたりと、まったり過ごしてました。
で、LLDN トラックバックセンター やはてなダイアリーからイベントレポートを読んでたのですが、naoya さんのカリスマっぷりが……どこぞのアイドルですか(笑
ふと、どんな acts_as_ほにゃららがあるか知りたくなりました。
上三つは ActiveRecord 1.11.1 に標準で含まれるものです。下三つは trac に ticket として投げられていますので、今後のバージョンで追加されるかもしれません。
acts_as_* を使うと、モデルクラスを特定のデータ構造として振舞わせることが簡単にできます。ありていに言えば、メソッドを自動的に追加してくれます。例としては、act_as_taggable が分りやすいですね。
この調子だとばかすか acts_as 系が増えていき、使い方も acts_as_list が acts :as => :list などとなってしまったりするのではと思ったりもします。便利な以外の良い点としては、人にとって annotation として機能することでしょうか。acts_as_* を見るとそのモデルクラスのデータ構造と振る舞いが分るというのは、コードを読む上での助けになりますよね。
Wikipedia が存続し、役に立つ情報源となっている未来のために 5000 円寄付。
最近のコメント:
RSS
![]()
This work is licensed under a
Creative Commons License
(note: text only. w/o web design, citations, (re)distributed softwares).
_ むとう [Ruby-GetText-Packageでは、sgettextというのがあるので、課題の1番最初の問題は解決できます..]
_ だて [なるほど。 http://thread.gmane.org/gmane.comp.lang.ruby.rails/1..]