オートコンプリート
いくつか、オートコンプリート(オートサジェスト)のライブラリはあるけど、眺めてみた限りではsuggest.jsがよさそう。
- Autocompleter(script.aculo.us.js)
- Prototype.jsが必要。
- 日本語の検索候補のときちょっと動作が怪しい感じ。
- Autocompleter.Localならあらかじめ検索候補を配列で用意しておくタイプなので、とても高速。サーバに負荷もかからない。
- これだけの為にPrototype.jsを用意するのはちょっと・・・
- suggest.js
- 国産だけに、日本語でも完璧に動くのが素敵。日本語変換ソフトとの親和性も高く快適。
- あらかじめ検索候補を配列で用意しておくタイプなので、とても高速。サーバに負荷もかからない。
- ver.2では他のライブラリに依存しない。
並列処理でActiveRecordを使う
※ドキュメントを読みながらこんなもんかな?とやってみたやつなので問題あるかもしれません。何かあればコメント頂けると嬉しいです。
例えば、DBからデータを取り出して逐次メールを送信する場合。
よく知られているようにメールの送信はコネクションの確立やSMTPサーバの処理などの待ち時間が長く、逐次処理をしていると無駄が大きすぎる。
処理を並列化して、あるメールの送信待ち時間を他のメールの構築等に充てて無駄をなくすことを試みる。
環境
- Ruby 1.8.6
- Rails 2.1.0
- PostgreSQL 8.3
処理の並列化
Thread.newを使う。単純に実装すればこんなかんじ。
# 未送信のレコードをそれぞれ別々のスレッドで処理するサンプル threads = [] mails = find(:all, :conditions => ["sent = ?", false]) mails.each do |mail| threads << Thread.new do Thread.pass Mailer.deliver_mail(mail) mail.update_attributes(:sent => true) end end threads.each { |t| t.join } # すべてのスレッドの処理が終わるのを待つ
ActiveRecordの並列化
処理は並列化できたが、これだとDBへのコネクションは1つしかなく、例えばスレッド毎にトランザクションを開始するようなことはできない。ActiveRecordのコードを追ってみたところ、どうやら
ActiveRecord::Base.allow_concurrency = true
とすれば良いようだ。
こうすることで、スレッド毎にコネクションを保持するようになり、スレッド毎に別々のトランザクションを開始することができる。
これらを踏まえたサンプル
コネクションが増えすぎないように、あらかじめ決めておいた数のスレッドで並列処理する。メールの重複送信を防止するため、PostgreSQLの行レベルロックを活用した。
ActiveRecord::Base.allow_concurrency = true # マルチスレッド対応 class Mail < ActiveRecord::Base validates_presence_of :recipients, :from, :subject, :body # 送信時に最大何個のスレッドを作るか cattr_accessor :max_threads @@max_threads = 20 class << self # すべての未送信メッセージを送信 # 送信に成功したメールモデルのインスタンスの配列を返す def send_all! sent_mails = [] threads = [] mails = find(:all, :conditions => ["sent = ?", false]) # 未送信のメールを取り出す # max_threads個のスレッドで並列処理 max_threads.times do threads << Thread.new do Thread.pass while mail = mails.shift sent_mails << mail if mail.send! end clear_active_connections! # 処理が終わったのでコネクションを切断 end end threads.each { |t| t.join } # すべてのスレッドの処理が終わるのを待つ sent_mails end end # メール送信 # 送信前には行レベルロックを行い二重送信を防ぐ def send! self.class.transaction do if new_record? || find(:first, :select => 'status', :conditions => ["id = ?", id]).status false else sended_mail = Mailer.deliver_mail(self) update_attributes(:sent => true) true end end end end
# ひとつだけ送信 mail = Mail.new(:from => 'hoge@mizincogrammer.com', :recipients => 'fuga@mizincogrammer.com', :subject => 'Hello', :body => 'Rails World!!') mail.save mail.send!
# CRON等でまとめて送信 Mail.send_all!
ActionCacheについてきっちり理解する
FragmentCache等に比べ、活用されることの少ないActionCacheですが、正直よく理解してないという方も多いのではないだろうか。
Rails 2.1のActionCacheのコードをざっと眺めて、簡単に特徴をまとめたいと思う。
「ActionCacheはフィルタ」
ActionCacheは、「キャッシュが存在すれば、キャッシュの内容を表示してfalseを返す(処理を止める)」というフィルタとして実装されている。
具体的には、caches_actionを呼び出すと、around_filterでActionCacheFilterのインスタンスが設定される。
これがどういうことかというと、
- キャッシュが存在すれば、アクションは実行されない。つまり、アクション内にボトルネックとなる処理がある場合、有効なキャッシュ手段となる。
- フィルタは実行されるので、「ログイン済みのユーザのアクセスのみページ(キャッシュ)を表示」といった、フィルタを活用する処理は可能。
- ただし、caches_actionよりも前にbefore_filter等を呼び出すか、prepend_before_filterを使用することが必要。(キャッシュが見つかった時点で処理を中断してしまうので、その後に実行されるべきフィルタは実行されない)
PS3のHTMLレンダリングエンジン開発者「PS3ブラウザに対応しました」と言われたい
http://www.itmedia.co.jp/news/articles/0807/28/news016.html
ソニーが開発した独自のエンジンを搭載したタブブラウザで、「PCと同等に使える、テレビに特化したWebブラウザ」を目標に改善を進めている。
Web開発者はInternet ExplorerやFirefoxはもちろん、WiiやiPod touchなども意識し、それぞれに最適化したコンテンツをリリースしている。だがPS3はまだまだ。最適化したいと思ってもらえるぐらいの存在感を打ち出していきたいという。
ふざけんな(゚Д゚)
そっちがIEかFirefoxに合わせろ、といいたい。できればFirefoxで。
ただでさえ各主要ブラウザでのチェックと修正に手間掛かるのに、これ以上無駄な仕事を増やすんじゃねーよ、と。
朝鮮弾入れはなぜ摘発・禁止されないか
パチンコで現金を得るのは違法賭博だと思うのですが、検察が摘発しないのはなぜですか?警察が摘発しないのは、利権関係だと分かるのですが
腐ってるなぁ、日本。
近所にも数件あるけど、百害あって一利なし。
昼間っからパチ屋に行く連中は運転も荒っぽいの多いし。
こんなキャッシュ機能が欲しい
パラメータ(クエリストリング)を考慮したアクションキャッシュが欲しい。
あるのかな?
ないのならつくろうかな。