2008-06-05
has_many :through で別DBの model を設定
内部的に INNER JOIN してるのでエラってひけないなー。Rails 2 でも DB は一つ的な思想なんだろうか。
LazyLoader Mixin
のをもうちょっと汎用的に使えるように拡張。
class Foo
include LazyLoader
lazy_reader :bar
def bar
sleep 1
'bar variable'
end
end
f = Foo.new
puts f.bar
puts f.bar # 二回目は結果がすぐ返る
しかしこの程度では
class Foo
def bar
unless @bar
sleep 1
@bar = 'bar variable'
end
@bar
end
end
でも別にいいじゃん、ということになる。実際は Fiber もしくは Thread (1.8 の Thread でうまくできるかは知らない) 切り替わりのタイミングで、とある Module を include したクラスの LazyLoading を一気に非同期でロードしたい。
cho さんに教えて貰った Io の
a := @foo
みたいなのを手軽にやりたいんだよなー。これができると、Web アププフレームワークで、DB や http から取得等の非同期で平行して走られ、かつ一番時間かかる処理を同時に行える。コントローラ側では意識せずに書くことができ、(erb なら)テンプレートで呼び出されるときにまだ処理が終わってなければそこで処理が終わるまで待ち受けられる。コントローラ処理が終わったらコンテキスト変えて、とかのタイミングで非同期ロード開始すれば実装的にはできそう。
というのが次の世代のWebアプリケーションフレームワークでは標準(頭使わなくて非同期でどんどん書ける)になりそうな気がしてるんだけどどうだろう。もう知らないだけで、そういう実装結構出てきてるのかな。
以下拡張したやつのソース。
module LazyLoader
module ClassMethods
attr_accessor :lazy_reader_methods
def method_added(method_name)
if self.lazy_reader_methods.keys.include?(method_name) && !self.lazy_reader_methods[method_name]
lazy_method method_name
end
end
def lazy_reader(*method_names)
self.lazy_reader_methods ||= {}
method_names.each do |name|
self.lazy_reader_methods[name.to_sym] = nil
end
end
def lazy_method(*method_names)
method_names.each do |method_name|
closure = instance_method method_name
self.lazy_reader_methods[method_name] = closure
define_method(method_name) do
iv_name = "@#{method_name}"
unless instance_variables.include? iv_name.to_sym
self.instance_eval "#{iv_name} = nil"
instance_variable_set iv_name, closure.bind(self).call
end
instance_variable_get iv_name
end
end
end
end
def self.included(base)
base.extend ClassMethods
end
end
iPod
新品になって戻ってきた\(^o^)/
ハト問題
またつがいの鳥があらわれやがった、、、ぜ、、、、