2007年08月05日 (日)
裸リムーバブル [テクニカル]
「裸リムーバブル」と呼ばれる、SATAのHDDをそのまま(インナートレイとか無しで)着脱できるリムーバブルラックをついに導入してみた。ほんとは買ったのは上のじゃなくて同一品のツクモのEX-SARC1B。玄人志向のと比べて500円ほど高いのでなんか損したかも。
まだSATAのHDDは2台しか持っていないのだが、それでもこれは予想以上に便利だね。今までパラレルATAのときはインナートレイ式のを使っていてトレイをいっぱい買っていたのだが、なんか今までがバカみたいに思えてくる。
まあ裸だと基板が剥き出しなのでそれなりに扱いには気をつけないといけないし、あと予想以上に熱くなるので(フォーマットしたあと取り出したら熱くて火傷しそうになった)注意しなきゃいけないというのもある。
でもやっぱりとても便利なのでなんかちょっとうれしい気分。
参考:
投稿者 4bit : 23:30 | コメント (0) | トラックバック (0)
2006年12月17日 (日)
Rails勉強会@東京 第13回&忘年会 [テクニカル]
前回に引き続き、毎月恒例のRails勉強会に参加。今回は日本Rubyの忘年会も開催。
ポジションペーパーは、「URIにidを使いたくない場合」ということで前のエントリそのまま。
前半セッション「AWDwR 2ndを読む」
最初セッション案があまり出ていなかったので、なんとなく僕が挙げた「Agile Web Development with Rails 2nd Editionを読む」が選択されて、オーナーを務めることになった。
しかしやっぱり全部読めるわけはないんで、読む場所は絞っておかなきゃいけないね~。リクエストのあったActiveRecordとActionController(ルーティングとRESTとか)あたりの改訂箇所を中心に読んでいったが、かなりグダグダな進行になってしまって、高橋さんにはだいぶ助けていただいた。ありがとうございました。
後半セッション「RSpec」
後半はもろはしさんにリクエストして前回出られなかったRSpecのセッションをもう一度。RSpecというのはBDD(Behaviour Driven Development)のためのフレームワーク。実行可能な仕様の記述とでもいうのだろうか。詳細はかくたにさん翻訳のチュートリアルを参照。
context "コードが4つともwhiteで、…" do
setup do
...
end
specify "blackの判定は4であること" do
@score.black.should_equal 4
end
...
end
- オブジェクトが複数のstateをもつ場合(複数インスタンス)Unit Testより自然に書ける
- Rubyの場合、テストの名前に日本語が使える(Javaなら普通にできるけど)
- 従来の単体テスト(Unit Test)に相当する。Integration Testに適用するものも開発中
- データがいっぱいある場合、Test::Base(secondlifeさん作)のほうが楽
- should_equalはオブジェクトの一致比較なので、文字列比較には should == または should_eql を使う
日本Rubyの忘年会2006
総勢50人弱という大人数で盛大に忘年会が行われた。幹事のもろはしさん、Yuguiさん、ありがとうございました。
投稿者 4bit : 23:59 | コメント (0) | トラックバック (0)
2006年12月15日 (金)
URIにidを使いたくない [テクニカル]
Railsでmap.resourcesを使っているとURIが /users/1 とか /articles/99 って感じになる。
でも、URIに数字のid使うのダセeeeeeeeeeeee
/users/tkawa みたいにユニークな文字列が使いたい!!!!
ってことがあるはず。(そもそも内部的な値であるはずのidをURIに使っていいのかという議論もある)
そこでルーティングのidの部分を差し替えられるコードを簡単に書いてみた。
使い方
idの代わりにnameというカラムを使う場合、このように書く。
map.resources :users, :id => "name"
これで例えば GET /users/tkawa というリクエストがあった場合、{ "controller" => "users", "action" => "show", "name" => "tkawa" } というパラメータが渡される。よってfindするときはUser.find_by_name(params[:name])とすればOK。
ただし、ヘルパーメソッドはなぜかuser_path(@user)って書くとうまく動かないので、user_path(@user.name)としなければならない。
でもこれで「URIにはユーザ名を使いたい!」とか「Wiki作るからURIにはページ名使えなきゃ困る!」ってときもバッチリ。
コード
プラグインでもenvironments.rbに直接書き込みでもお好きなようにどうぞ。ってか公開svnレポジトリ作らないとなー。
ActionController::Resources::Resource.module_eval do
def id
@options[:id] || "id"
end
def member_path
@member_path ||= "#{path}/:#{id}"
end
def nesting_path_prefix
@nesting_path_prefix ||= "#{path}/:#{singular}_#{id}"
end
end
投稿者 4bit : 19:23 | コメント (0) | トラックバック (1)
Singleton Resourcesが実装された [テクニカル]
「Railsのmap.resourcesに単数形リソース必要じゃん~」って2ヶ月前から言っていてプラグインとか作ったりしていたのだが、それが通じたのか(偶然だけど)Rick OlsonがSingleton Resourcesを実装してくれた!(Changeset 5701)
A singleton resource is global to the current user visiting the application, such as a user's /account profile.
そうそう、そういうことなんだよ~。やっぱり考えることは同じだね。
使い方
routes.rbに、map.resourcesと違って単数形で書く。
map.resource :account # map.resourcesと紛らわしいので注意
すると、こんな感じのルーティングが生成される。
| HTTPメソッドとURL | AccountControllerのアクション | ヘルパーメソッド |
|---|---|---|
| GET /account | show | account_url account_path |
| GET /account;edit | edit | edit_account_url edit_account_path |
| PUT /account | update | account_url account_path |
| DELETE /account | destroy | account_url account_path |
ちなみに、ヘルパーメソッドの*_urlと*_pathの違いは、前にRails勉強会で「よくわかんないけど*_pathに変わってきてるみたい」とか言っていたのだが、調べてみると*_urlがスキーム・ホスト名などを含んだURL(http://example.com/account)で*_pathがルートからのパスのみ(/account)になる。
これでセッションに存在する単数リソースや、現在ログイン中のユーザに紐づくリソースも表現できるようになった。めでたしめでたし。
投稿者 4bit : 12:34 | コメント (0) | トラックバック (0)
2006年11月25日 (土)
第九回XML開発者の日 [テクニカル]
「第九回XML開発者の日」で発表してきた。なんか予想外に緊張しまくりで、声も震えるしもう今考えると相当恥ずかしい。拙い発表ですみません。会場にRuby関係の方はあまりおられなかったようで、そういう意味では新鮮に聞いていただけた方も多かったのではと勝手に思っていますがどうだったでしょうか。
発表資料はこちら。
- 「Ruby on RailsにみるRESTfulアプリケーションの方向性」(PDF 約2MB)
スライド中の単数リソース対応プラグイン“map_singular_resource”についてはこちらの記事を参照。
以下各セッションのメモ・感想など。
REST Best Practices(山本陽平さん)
- Cool URI by TBL
- WebアプリとWeb API(Webサービス)を分けないのが重要
- resource orientedな設計
実際のWebサービスを取り上げての指摘はわかりやすかった。「WebアプリとWebサービスを分けない」というのはなるほど!と思った。Railsの方向性にも通じるところがある。
SOAのカウンターパートとしてのROA(Resource Oriented Architecture)はおもしろいかもしれない。
Ruby on RailsにみるRESTfulアプリケーションの方向性
発表資料参照
xfy カレンダーアプリへのGData実装(Masa and Takさん)
- GData: Google Data APIs
- OpenSearch1.1対応(q=文字列 など)
- hCalendar in RSS/Atom Feed
ジャストシステムが作っているxfyというXMLアプリを動かすためのプラットフォーム製品。そのカレンダーアプリにGDataを実装。
Plaggar: the duct tape of the Web(宮川達彦さん)
- Just like UNIX Pipe
- the UNIX Shell for Web2.0
- RSS(Feed) is the Standard I/O of the Web
「RSS(Feed)はWebのスタンダードI/O」という考え方にはなるほどと思った。それにマッチしているPlaggarが支持されるのもうなずける。
SkypeとMacromediaのBreezeというソフトを使ってサンフランシスコからのリモートプレゼンだった。映像も音声もクリアでかなり実用的と感じた。
ODFとOOXMLの標準化戦争(村田真さん)
- ODF(Open Document Format): OASIS, Sun, IBM
- OOXML(Office Open XML): ECMA, Microsoft
- 2006年5月にODFがISO標準になることが確実に
- 日本の官公庁はあんまり深く考えずWordを使ったりしてる。経産省は少し考えている。でも影響力のあるのは総務省
- 内部利用…コストが大事
- 国民向け…差別がないことが大事
- OOXMLがISO提出されたとき日本はどうするか?
規格の技術的な話ではなかったが、ストーリーとしておもしろかった。現状では公文書などにMS Wordなどが使われているのはやはりおかしい。会場の意見としても出ていたが、MSがOOXMLをオープン化することで、MS以外にOOXMLを生成できるツールが現れるかどうかがポイントではないかと思った。
microformatsに触れてみよう(上ノ郷谷太一さん)
- XFN: 人脈情報
- hCard: コンタクト情報
- hCalendar: スケジュール
- human readable first. machine second.
写真などをふんだんに使用したわかりやすくておもしろいプレゼンだった。手軽に使えるのであればMicroformatsを使ってみようかなと思わせる内容だった。
Syndy Chronicleの実装に見るMicroformats(山口琢さん)
- 年表をマシン処理可能にする(hCalendar)
- オーサリングツールが進化すれば…
- Syndy: OPMLベースのアプリラウンチャー
- Syndy Chronicle: 年表ビューア・エディタ
ブログエディタへのMicroformatsの実装(後藤康成さん、室田直匡さん)
- feedpathのブログエディタ。ブログサービスにMicroformatsでpostできる
- WSSE認証のパターンで困る
- hReview(本・雑誌・音楽…)
- hCalendar
- テンプレートも自由に編集可
非常に機能が充実したブログエディタだった。ブログツールもそれぞれ記事作成・編集用のWebサービスを持っていることから、このような外部エディタが出てくるのは必然ともいえるが、それ以外にも地図APIやページのスクリーンショットを撮るAPIなども利用していることから、大いにWebのメリットを活かしているアプリケーションだと感じた。このようにMicroformatsが利用しやすくなっていけば、もっと普及するのではないかと感じた。
投稿者 4bit : 08:53 | コメント (1) | トラックバック (0)
2006年11月20日 (月)
ActiveResourceはRails1.2ではリリースされません [テクニカル]
via id:moroさんの日記&id:secondlifeさんの日記。
Changeset 5554 - Ruby on Rails - TracActive Resource will not ship with Rails 1.2
うはw
発表にActiveResource含めなくてよかった~。まあ、どっちにしても僕は1.2の目玉はActiveResourceじゃなくてmap.resourcesだと勝手に思っていたので、問題ないんだけどね。
投稿者 4bit : 16:38 | コメント (0) | トラックバック (0)
2006年11月19日 (日)
Rails勉強会@東京 第12回 [テクニカル]
ポジションペーパーは、ネタがなかったというのもあるが時間がなく、初めて持っていけなかった。反省。
前回ノートパソコンをまたまた購入しなかったと言っていたのだが、今度こそ購入した(10/22)。中古だけど。Let's note R3。小さくて軽くてバッテリー持っていいぞ~。このマシンで前半セッションのプレゼン。
前半セッション「Ruby on RailsにみるRESTfulアプリケーションの方向性」
前半セッションは、今度の金曜日に開催される「第九回XML開発者の日」の発表の練習のセッションということで、オーナーを務めさせてもらった。人数は僕を含めて3人とかなり少なかったのだが、まあ練習ということもあるし本番では時間の都合でカット予定のところも含めて発表した。
緊張感がなかったせいか(?)かなりグダグダなしゃべりになってしまったのだが、そのへんは本番での修正事項としておいて、いろいろ意見ももらえたのでよかった。RSpecのセッションのほうにも出たかったけど、もろはしさんにぜひもう1回開催してもらおう。
後半セッション「いまこそARと外部キーについて考える」
後半は、舞波さんの外部キーについての提言&コーディングセッション。郵便番号や都道府県などのデータを持たせる場合、
- テーブルを作ってオートナンバーのidをサロゲートキー(代替主キー)とする
- テーブルを作って郵便番号や都道府県JISコードを主キーとする
- テーブルを作らずハッシュなどですませる
のどれにするか? という問題で、従来のRailsの考え方では1だったが、2のほうが便利なこともあるのでは?という提言。たしかに○○コードを使う場面では2もアリなのかなぁと思った。
そして、それを実現するためbelongs_toに:association_foreign_keyオプションを持たせるコーディング。スピード感のあるコーディングだった。
そして、あとはパッチを投げるだけなのだが、問題はコミッタにこのパッチが必要だということを英語で説得するのが難しいということ(笑)。has_one :throughにも同じようなことが言えるが、方向性の違いがあるとなかなかつらいね、こういうのは。
懇親会その後
関西のRails勉強会のようすを聞いたり、PythonのDjangoというフレームワークについて話したり。t-wadaさんがいらっしゃっていたので、最後にちょっとだけ挨拶できたのでよかった。
XML開発者の日で発表します
ということで、24日(金)の「第九回XML開発者の日」で、「Ruby on RailsにみるRESTfulアプリケーションの方向性」というタイトルで発表します。内容は、日本Rubyカンファレンス2006でのDHHの発表のREST関係部分+αという感じです。Rubyにあまり関わりがない人にも、あのDHHの発表の重要な方向性を少しでも伝えられればと思っています。あまり慣れていないので拙い発表になるとは思いますが、よろしくお願いします。
投稿者 4bit : 23:22 | コメント (0) | トラックバック (0)
2006年10月16日 (月)
Rails勉強会@東京 第11回 [テクニカル]
前回に引き続き、毎月恒例のRails勉強会に参加。今回で第0回から数えるとちょうど1年経つことになるのかな。Railsの世界は流れが速い。
ポジションペーパーは、「Nested Resourcesとmap_singular_resourceプラグイン」ということで前のエントリそのまま。
前回ノートパソコンを購入するとか言っておきながらいまいち踏ん切りがつかずまだ購入できていない…。ということでまたノートなしでの参加。
前半セッションは「map.resourcesを知っておきたくはないか?+Beast」。map.resourcesといえば一応僕の得意分野ということでオーナーのもろはしさんを差し置いてのりおさんと2人でダラダラと進めちゃった感じ。参加された方はあんな感じでわかってもらえたでしょうか?わからなかったらすみません。
map.resourcesやRESTfulについてよくまとまっていた「PeepCode RESTful Rails Cheat Sheet」をポジションペーパーの裏側に印刷しておいたので、それに挙がっていることを一通り説明していった。
あとそれに沿ってRESTfulに作られた掲示板システムであるBeastについてもソースを読む予定だったが、そこまでたどり着かず。個人的にチラッと見た印象ではコード量も少ないしシンプルでわかりやすいなと思った。
後半セッションは「激論ABD」。最初はダラダラセッションかと思われていたがまったくそんなことはなく、まさしく激論が交わされた。たぶんあのメンバーの中であんまりついていけてなかったのは自分だけ。なんか頭が働いてなかった…。心より恥じる。ていうかこんなことではABD飲み会についていけないぞ。ってことで復習するので他の方(もろはしさんとかYuguiさんとか)のレポートを期待。
懇親会ではYuguiさんの記事の原稿を見せてもらった。おもしろい。Principle of least surpriseやConvention over Configurationなどのことについて、突っ込んだらここまで書けるのかと感心した。またもろはしさんには今自分の中でちょっとひっかかっているワークフロー・ワークステートとRailsの関係について聞いた。やっぱり理想的にはモデル(DB)から導出できるべきって感じか。今はまだ深追いできないかなという感じがした。
投稿者 4bit : 15:11 | コメント (0) | トラックバック (0)
2006年10月05日 (木)
map_singular_resourceプラグイン [テクニカル]
きのうのエントリに書いたが、Railsのmap.resourcesに対応するリソースは複数形で、複数あることが前提とされていた。それじゃ単数(1つしかない)リソースの場合どうするんだよ、ってことで、単数リソースに対応するmap_singular_resourceプラグインを作ってみた。
使い方
routes.rbに、map.resourcesと違って単数形で書く。
map.resource :person # 紛らわしいので map.singular_resource :person も可
すると、だいたいこんな感じのルーティングが生成される。
| HTTPメソッドとURL | PersonControllerのアクション | Route Name |
|---|---|---|
| GET /person | show | person |
| POST /person | create | person |
| GET /person;edit | edit | edit_person |
| PUT /person | update | person |
| DELETE /person | destroy | person |
map.resourcesからnewとindexを除いたような感じ。省略したけど、拡張子の:formatにももちろん対応している。:controller指定やアクション追加などのオプションももちろん使える。
has_one関係に使う
実はあんまり単体で使うことは少ないかもしれない。使われるとすればNested Resourcesで、モデル間の関係がhas_oneになっているときだ。
例えばUser has_one :profileというモデルの関係があったとすると、routes.rbにこのように書く。
map.resources :users do |user| user.resource :profile end
すると、こんな感じのルーティングになる。
| HTTPメソッドとURL | ProfileControllerのアクション | Route Name |
|---|---|---|
| GET /users/:user_id/profile | show | profile |
| POST /users/:user_id/profile | create | profile |
| GET /users/:user_id/profile;edit | edit | edit_profile |
| PUT /users/:user_id/profile | update | profile |
| DELETE /users/:user_id/profile | destroy | profile |
きれいなURLでhas_oneの関係に対応しているのがわかる。
ソースは思いっきり手を抜いてactionpack/lib/action_controller/resources.rbからコピー&ペーストで作ったのでDRYじゃないし、相変わらずテストもないので不具合あるかも。でも使う機会はきっとあるような気がするなー。
投稿者 4bit : 17:43 | コメント (0) | トラックバック (0)
2006年10月04日 (水)
Nested Resources (map.resourcesのススメ その3) [テクニカル]
「map.resourcesのススメ」シリーズ第3回。
前回map.resourcesのオプションの利用方法を解説した中に、このようなものがあった。
特定のパラメータを必須にしたい場合
例えば、特定のグループ(ID)に属するユーザの一覧を表示したいとき、
map.resources :usersとするとURLは
/users?group_id=1
のようにgroup_idをパラメータに取ることになるが、あるグループに属するというのを標準にしたければ、
map.resources :users, :path_prefix => "/groups/:group_id"とすると、URLは
/groups/1/users
とすっきりと表記できる。
これは、モデルがhas_manyの関係のときに非常に一般的なので、Nested Resourcesとして、このようにシンプルに書けるようになった。
map.resources :groups do |group| group.resources :users end
これは、
map.resources :groups map.resources :users, :path_prefix => "/groups/:group_id"
と書いたのと同じ効果を持つ。この場合はモデルはGroup has_many :usersって感じになる。
そこでふと思ったのだが、has_manyに対応するものがあるのに、has_oneに対応するものはないのか? そもそもRailsでのリソースって複数形のみで、単数(1つしかない)リソースが想定されてない気がする。has_oneもしくはカラム単体に対応するリソースがあれば、もっとモデルを柔軟に表現できるんじゃないか?
単数限定リソースを実現するmap_singular_resourceプラグインでも作ってみるか…。
投稿者 4bit : 17:10 | コメント (0) | トラックバック (0)
2006年09月28日 (木)
scaffold_resource_generator [テクニカル]
Edge Railsに、scaffold_resource_generatorというリソース(map.resourcesで指定するもの)用のscaffold generatorが新しくできた(Changeset 5147)。これを使えばコントローラとモデル(とマイグレーション)を一気に作ってくれるというシロモノ。
使い方
ruby script\generate scaffold_resource <リソース名> [カラム名:型名] ...
第3引数にリソース名(※単数形であることに注意)、第4引数以降にテーブルのカラム名と型名を“:”で区切ったものを並べていく。型名はマイグレーションで指定するものと同じ。例えば、AWDwR本のDepotアプリケーションのproductを作るならこんな感じ。
ruby script\generate scaffold_resource product title:string description:text image_url:string price:float date_available:datetime
これでモデルとマイグレーション、さらに通常のscaffoldのRESTバージョンともいえるコントローラ(ProductsController)とビュー、テストの雛形が生成される。生成後にroutes.rbにmap.resources :productsを書くのを忘れないように。こっちは複数形。
前のmap.resourcesの紹介記事の中では通常のscaffoldを使うパターンを紹介したが、これからはscaffold_resourceで一発になりそうだ。個人的には通常のscaffoldがリソース対応に書き直されるのかなと思っていたが、別にリソース専用のscaffoldができたということは、Railsで作る全部がリソースになるのではなく、リソースの場合とそれ以外の場合とを区別して使ってねという意図の表れなのかもしれない。とはいえ、個人的には全部リソースというのがすっきりして好きなんだけどね。リソースにするとActiveResourceでアクセスできるというおまけもつくし。
投稿者 4bit : 09:57 | コメント (0) | トラックバック (0)
2006年09月25日 (月)
Rails勉強会@東京 第10回 [テクニカル]
ポジションペーパーは、「DepotにABDを適用してハマった」ということで前のエントリそのまま。
いつもノートPCなし(すげえ古いのしか持ってない)で参加しているのだが、今回は特にノートなしでは厳しかった。前半セッションは「Rails1.2を先取り」でChangesetをひたすら読んだ。後半セッションは「AWSに挑む」でActionWebServiceのソースを読んだ。
Rails1.2はなんかかなり早く出る予定らしくて、map.resourcesばかり見てたけどActiveResourceとかresource_feederだとかscaffold_resourceだとかいろいろあるらしくて、今後のRailsの方向性に注目してる身としてはちゃんと追っかけないとやばい。
AWSは正直ぜんぜんついていけてなかった…。個人的にRESTafarianではあるけど今後仕事でSOAPとかもやりそうなのでこのへんは理解しておかないといけないのだが…。まあ実際やるときはJavaでやることになると思うけど。
懇親会ではJavaのグチの話になったりして、「XMLを設定ファイルに使うのはやめよう!」という僕と同じことを考えている方がいたりした(笑)。
次回までにはノートPCを購入している予定なのでやっと持っていけるかなー。
投稿者 4bit : 11:22 | コメント (0) | トラックバック (0)
2006年09月21日 (木)
DepotにABDを適用してハマった [テクニカル]
「RailsによるアジャイルWebアプリケーション開発(通称AWDwR)」にサンプルとして載っているDepotアプリケーションにABDを適用して作り直したらどうなるだろう?というのを少し前にやっていたのだが、意外なところでハマったのでメモ。
テーブル設計はもともとのがこんな感じ。典型的なマスタ・ディテール形式。

ABDを適用したら、このようになる(はず)。line_itemsからFKが消えて、FKを集約したorder_activitiesというテーブルができる。

LineItemクラスではこんな感じで has_one :through 使ってる。Yuguiたんプレゼンツ。
class LineItem < ActiveRecord::Base has_one :order_activity has_one :product, :through => :order_activity ... end
問題は、CartというDBには載らないクラスの存在。このオブジェクトはセッションに入っていて、内部にLineItemの配列を持つ。その使い方は、カートに商品が入るたびに、すでにある商品ならすでに入ってるLineItemのquantityを+1し、新しい商品ならLineItemをnewして入れるという感じ。そして、注文を確定するときにOrderを作ってそこにCartに入っていたLineItemをまとめてくっつけて一気にsaveするのだ。つまりCartに入っている間はLineItemはsaveされていないというのがポイント。
さて、もともとのテーブル設計ならLineItemにはproduct_idが入っているので問題ないのだが、ABD版では入っていない(FKがないんだから当然だが)。そこで has_one :through でproductをたどれるようにしたいのだが、LineItemはsaveされていないからidが無い! よってOrderActivityが作れないのだ。ガーン。
かといってLineItemをsaveしてしまうのも、CartがDBに入ってない単なる一時データなのにその中にあるLineItemがいちいちDBに入るってのはどうなんだ、と。さてこういうときどうするのが一番いいのでしょう?
まあ端的に言えばDB上にないデータの関連はたどれませんよってだけなのだが、ActiveRecordはnewして一時的にsaveせずに使うという使い方もけっこう想定されてるような気がする。それともレアケース?
あと直接関係ないけどDepotアプリのREST適用版ってのも試作していて、そっちはなかなかいい感じ。AWDwRの将来の版ではこういうのが載るようになるのかな。
投稿者 4bit : 17:53 | コメント (0) | トラックバック (0)
2006年08月27日 (日)
Rails勉強会@東京 第9回 [テクニカル]
ポジションペーパーは、「祝・SimplyRestfulプラグインマージ記念 map.resourcesのススメ」。以前の2つの記事を「URLのaction撲滅しようよ(Cool URI)」という観点から簡単にまとめたもの。
前半セッションは「LL Ringの家計簿アプリの中身を詳しく」。きのう開催されたLL Ringの「キミならどう書く」セッションで作成された家計簿アプリをかずひこさんの紹介で見てみる。
- テーブル設計
- 勘定科目
- id、名前、種類
- 仕訳
- id、日付、金額、借方id、貸方id
- あらゆるタグ
- 日付もタグ(!)
- 検索インターフェイスが統一される
- acts_as_taggable(gem版)利用
- rake stats便利
- annotate_modelsプラグイン
- rake annotate_models でモデルクラスの先頭に対応テーブルのスキーマコメントを埋め込んでくれる
- Lightbox Jojoで「ドドドド」「ドッギャァ~ン」(笑)
- グラフを描くにはgruffプラグインを利用
あらゆるタグ利用で、検索インターフェイスが統一されるというアイデアはすごい。
最後のほうでかずひこさんが話を振ってくださってmap.resourcesについて少ししゃべる時間をもらった。RESTセッションできたらいいなぁとか思いつつぜんぜんできてないけど…。ノートPCがないというのもあるし。もう買うしか。
後半セッションは、「has_one :throughを作る」。Yuguiさんが作っているhas_one :throughを正式にRailsのパッチとして提出するために、既存のActiveRecordの単体テストのどのモデルを利用するべきかなどいろいろ話し合った。
舞波さんも加わってABDの話題(はぶさんがしばらく封印とか言ってるし。。)も出て、どういうモデリングが必要なのか議論。とりあえずhas_one :throughのテストの方針は決まり、あとはパッチを受け入れてもらうためのユースケースを考えねばということに。それとは別に、このままいくと消えかねないhabtmの復活案も出て、内容の濃い時間だった。ちょっと後から思い出して整理しとこう…。
投稿者 4bit : 22:21 | コメント (0) | トラックバック (0)
2006年08月04日 (金)
舞波本きたー [テクニカル]
「優しいRailsの育て方」、通称「舞波本」購入。
あと最初に断っておきますが、そういうのは無いです。至って真面目な本です、ごめんなさい。
いや、最初のほうAA満載なんですけどwww AAで解説って斬新すぎw しかも舞波とか桃子とか至るところに出てくるしw
内容はRails一通りおさえたリファレンスって感じで役に立ちそう。「パッチを作る」なんてセクションもあるし。最初少しだけ書いたhtpasswdプラグインも載ってる。
あと、一緒にyoheiさんおすすめ(というか執筆なさった)WEB2.0キーワードブックも購入。著者陣が豪華。
「RESTって何?」って聞かれたときに、これ読んでってyoheiさんの章を安心して見せられます。
投稿者 4bit : 20:51 | コメント (0) | トラックバック (0)
2006年08月02日 (水)
map.resourcesのススメ(「SimplyRestfulプラグインのススメ」改め) [テクニカル]
前の記事に引き続き、map.resourcesのオプションの利用方法を解説。DHHによってRails本体にマージされちゃったので、「SimplyRestfulプラグインのススメ」って言えなくなっちゃった…。てことで改題。
コントローラ名を変える
コントローラにモデル名の複数形をつけるのが気に入らない場合、コントローラ名を好きな名前に変えることもできる。map.resourcesにオプションでこのように指定してやるだけだ。
map.resources :people, :controller => "person"
特定のパラメータを必須にしたい場合
例えば、特定のグループ(ID)に属するユーザの一覧を表示したいとき、
map.resources :users
とするとURLは
/users?group_id=1
のようにgroup_idをパラメータに取ることになるが、あるグループに属するというのを標準にしたければ、
map.resources :users, :path_prefix => "/groups/:group_id"
とすると、URLは
/groups/1/users
とすっきりと表記できる。
このとき同時にオプション :name_prefix => "groups_" と指定すれば、名前付きルートの名前の最初に groups_ がつき、通常と区別することができる。よって、
map.resources :users # 通常のユーザ map.resources :users, :path_prefix => "/groups/:group_id", :name_prefix => "groups_" # グループに属するユーザ
のように2種類同時に使うことも可能。
CRUDから外れたアクションを追加する場合
DHH曰く、「ここは敢えて CRUD から外れよう、と判断するのはありだと思う。こういうのはバランスの問題で、極端に走るのがいいとは限らない」。
例えば、ユーザにマークをつけるmarkアクションを追加する場合、このように指定する。
map.resources :users, :member => { :mark => :post }
これで mark_user という名前付きルートで
/users/1;mark
という形のURLがHTTP POSTに限って使えるようになる。
オプションとして与えるハッシュのキーはそれぞれ以下のように対応している。
| キー | URL |
|---|---|
| :member | /users/1;アクション名 |
| :collection | /users;アクション名 |
| :new | /users/new;アクション名 |
ハッシュの値のハッシュ(ややこしい)は、{ アクション名 => 許可されるHTTPメソッド } の形で指定する。
あんまりすっきりした形で指定できないなあと思うけど、そもそもCRUDから外れたアクションはあまり追加しないほうがいいわけで、乱用は禁物だ。
最後に
Rails本体にマージされたということで、いよいよRailsアプリがCRUDに、RESTfulになる日が近づいてきている感じがする。正直個人的には1.2の機能ではActiveResourceよりこっちのほうがうれしい。Edge Railsを厭わない人は今からでもどんどん使ってみて、CRUDな設計・実装をぜひ実現してください。僕もいろいろ使ってみてABDとの相性などを調べていきたいと思う。
参考
- Refactoring to REST
IconBuffet.comというサイトをSimplyRestfulプラグインを使ってRESTにリファクタリングしてみましたというメモ。 - Getting RESTful on Rails (Part 1)
英語でのSimplyRestfulプラグインの解説。こっちのほうがわかりやすいかも? - SimplyRestful plugin backport
SimplyRestfulプラグインのRails1.1.4向けバックポート。ルーティングのセパレータにセミコロンやピリオドが使えないのでなかなかつらいようだ。使ったことないのでどなたか使ってみてください。 - Request Routing Plugin
上のバックポートを動かすのに必要なプラグイン。ルーティングの:conditionsに:subdomain, :domain, :method, :port, :remote_ip, :content_type, :accepts, :request_uri, :protocolが指定できるようになるという、なかなか使えそうなプラグイン。
投稿者 4bit : 19:04 | コメント (0) | トラックバック (0)
2006年07月31日 (月)
SimplyRestfulプラグインのススメ [テクニカル]
はじめに
日本Rubyカンファレンスから早2ヶ月弱、DHHのセッションに衝撃を受けた人(僕)もそうでない人もいたと思うが、このセッションで繰り返し語られたCRUDな設計・実装がこれからのRails界の潮流になっていくのは間違いないと思う。
ちなみにまだ見てない人はこちら。
- 「Discovering a world of Resources on Rails」スライド (PDF)
- 日本語による解説 by あんどうさん
そこで、このDHHのセッションに出てくるCRUDな実装をサポートするプラグインが、SimplyRestfulプラグインだ。
(って書き始めたのはいいのだが、Edge Rails専用だと後で知ってちょっと一般には薦められないかも…と思い始める。まあでも書いちゃったので載せる)
8/2追記:ついにRails本体にSimplyRestfulプラグインがマージされてしまった(Changeset 4637)。やってくれるぜDHH!ということで少し使い方が変更されているので修正。
インストール
インストールは不要。そのかわり最新のEdge Railsを使おう。ruby script/plugin install http://dev.rubyonrails.org/browser/plugins/simply_restful
rake rails:freeze:edge
基本的な使い方
[Model名の複数形]Controllerがあることを前提とする(名前の変更も可能)。例えばPeopleControllerであれば、routes.rbにこのように書く。
ActionController::Routing::Routes.draw do |map|map.resource :personmap.resources :people # 複数形に変更 end
この1行だけで、以下のルート、名前付きルートが生成される。
Routes
| Route | Significant Keys | Requirements | Conditions |
|---|---|---|---|
| /people | [:controller, :action] | {:controller=>"people", :action=>"create"} | {:method=>:post} |
| /people.:format | [:format, :controller, :action] | {:controller=>"people", :action=>"create"} | {:method=>:post} |
| /people | [:controller, :action] | {:controller=>"people", :action=>"index"} | {:method=>:get} |
| /people.:format | [:format, :controller, :action] | {:controller=>"people", :action=>"index"} | {:method=>:get} |
| /people/new | [:controller, :action] | {:controller=>"people", :action=>"new"} | {:method=>:get} |
| /people/new.:format | [:format, :controller, :action] | {:controller=>"people", :action=>"new"} | {:method=>:get} |
| /people/:id;edit | [:id, :controller, :action] | {:controller=>"people", :action=>"edit"} | {:method=>:get} |
| /people/:id.:format;edit | [:id, :format, :controller, :action] | {:controller=>"people", :action=>"edit"} | {:method=>:get} |
| /people/:id | [:id, :controller, :action] | {:controller=>"people", :action=>"destroy"} | {:method=>:delete} |
| /people/:id | [:id, :controller, :action] | {:controller=>"people", :action=>"update"} | {:method=>:put} |
| /people/:id | [:id, :controller, :action] | {:controller=>"people", :action=>"show"} | {:method=>:get} |
| /people/:id.:format | [:id, :format, :controller, :action] | {:controller=>"people", :action=>"show"} | {:method=>:get} |
Named Routes
| Name | Route | Significant Keys | Requirements | Conditions |
|---|---|---|---|---|
| edit_person | /people/:id;edit | [:id, :controller, :action] | {:controller=>"people", :action=>"edit"} | {:method=>:get} |
| formatted_new_person | /people/new.:format | [:format, :controller, :action] | {:controller=>"people", :action=>"new"} | {:method=>:get} |
| new_person | /people/new | [:controller, :action] | {:controller=>"people", :action=>"new"} | {:method=>:get} |
| formatted_people | /people.:format | [:format, :controller, :action] | {:controller=>"people", :action=>"index"} | {:method=>:get} |
| people | /people | [:controller, :action] | {:controller=>"people", :action=>"index"} | {:method=>:get} |
| person | /people/:id | [:id, :controller, :action] | {:controller=>"people", :action=>"show"} | {:method=>:get} |
| formatted_person | /people/:id.:format | [:id, :format, :controller, :action] | {:controller=>"people", :action=>"show"} | {:method=>:get} |
| formatted_edit_person | /people/:id.:format;edit | [:id, :format, :controller, :action] | {:controller=>"people", :action=>"edit"} | {:method=>:get} |
Scaffoldから使う
PeopleControllerに必要なアクションメソッドは、index, show, new, create, edit, update, destroyの7つ。これはScaffoldで生成されるコントローラとほぼ対応しているのでScaffoldから使ってみるのがお手軽。Scaffoldから使う場合、変更するところは以下の通り。
- listアクションはindexアクションに変更
コントローラのlistメソッドの中身は全部indexメソッドに移す。コントローラとビューのaction => 'list'もすべてaction => 'index'もしくはpeople_url(後述の名前付きルートURL)に書き換える。結構いっぱいあるので注意。そしてビューのlist.rhtmlをindex.rhtmlにリネーム。 - コントローラの
verifyを消す - edit.rhtmlの
start_form_tagにオプション:method => :putをつける
<%= start_form_tag :action => 'update', :id => @person %>
↓<%= start_form_tag({ :action => 'update', :id => @person }, :method => :put) %><%= start_form_tag person_url(@person), :method => :put %>
でも可。 - index.rhtmlの
link_to 'Destroy'にオプション:method => :deleteをつける
<%= link_to 'Destroy', { :action => 'destroy', :id => person }, :confirm => 'Are you sure?', :post => true %>↓<%= link_to 'Destroy', { :action => 'destroy', :id => person }, :confirm => 'Are you sure?', :post => true, :method => :delete %><%= link_to 'Destroy', person_url(person), :confirm => 'Are you sure?', :post => true, :method => :delete %>
でも可。
ほかにもあるかもしれません…。
名前付きルートURLを活用する
名前付きルートがたくさん定義されているので、付随してxxx_urlメソッドが使える。例えばperson編集画面へのリンクは、
link_to 'Edit', :action => 'edit', :id => person
の代わりに、
link_to 'Edit', edit_person_url(person)
と書ける。可読性もよくなるのでぜひ使うようにしよう。
ということで
このSimplyRestfulプラグインを使うことで、CRUDな設計・実装をせざるを得なくなるというのが重要なところだ。Constraints are liberating. 制約が自由をもたらす。
(次回、オプションの利用方法に続く)
投稿者 4bit : 18:56 | コメント (0) | トラックバック (0)
2006年07月24日 (月)
Rails勉強会@東京 第8回 [テクニカル]
昨日行われたRails勉強会に参加。
ポジションペーパーは、「ABDはやり過ぎてもいいのか否か」。結論から言うと「やり過ぎてもよい」なのだが、詳細は調べてあとで書く(つもり)。
今回ちょっとセッション選びを間違えちゃったかな…。「RailsでABD実践」のセッションが後半にも行われると聞いて前半選ばなかったのが失敗だった。結局前半は「Rails Chatのソースを読む」を選択。のりおさん作のRails Chatのソースを読んだ。Flashのxmlsocketを使って、サーバとブラウザ間にコネクションを張ってリアルタイムにページの更新を行ったりできる「Juggernaut」(の古いバージョン)を使っているのが特徴。詳細な情報はこのへんに。
後半は「BackgrounDRbを触ってみる」。よしみかんさんのまとめ「I sort my thought... - BackgrounDRbについて調べてみた」を見ながらみんなで動かしてみた。僕はノートPCを持っていなかったこともあり少しうとうとしてしまった。心より恥じる。
相変わらずREST好きな僕としては、もろはしさんの「ABDとCRUD/Railsは相性がいい」やYuguiさんの「ABDはアジャイルで変更に強いDB設計だ」あたりの意見にかなり強い興味があるので、次回もセッション希望というか、次回までに自分でもそのへん(とくにRailsやRESTにどう生かせるのか)を予習して臨みたい。というか予習したらblogに書く。あと個人的におすすめのSimplyRestfulプラグインの(ある程度詳細な)紹介をURLのaction撲滅運動(?)と絡めて書く。
追記:デブサミでのはぶさんのセッション資料にABDの記述を発見。デブサミのときからあったのか…。Seasar Conferenceの資料はあるみたいだけどサーバが死んでるのか見れません。見れました。
- Developer Summit 2006 - 楽々ERDレッスンLive (PDF)
- Seasar Conference 2006 Spring - EJB3時代のERDレッスン~Activity Based Datamodel (PowerPoint)
投稿者 4bit : 14:00 | コメント (0) | トラックバック (0)
2006年06月19日 (月)
Rails勉強会@東京 第7回 [テクニカル]
ポジションペーパーは、ここのブログに書いてた「DHH loves REST!?」をマイナーチェンジしたものです。ogijunさん曰く「カンファレンスに行ってないのに煽ってる人がいる」とズバリ。はい、煽ってるつもりです(笑)。
今回は初めて恵比寿のドリコム東京事務所での開催。入ったらいきなりエントランスホールにビリヤード台が置いてあってびっくり。なんか煮詰まったときには遊んだりするそうだが、もし僕がこんな環境にいたらずっと遊んでしまいそうで恐い。スヌーカー台だったらもっとよかったのに(大きすぎて無理)。他も非常にきれいですばらしい環境でした。
前半セッションは「DHHふたたび」。先日の日本RubyカンファレンスのDHHの講演の音声をおおもりさんが録音されていたので、それを聴こうというセッション。
非常に聞き取りやすい英語だった…と思うのだが、自分の英語力のショボさで「とりあえず聞いただけー」に終わる。情けない…。翻訳Wikiのあんどうさんのまとめを手元に置きながら聞いたのだが、これがなかったらぜんぜんわからなかった。感謝。
講演の内容でDHHがCRUDとは何回も言っていたがRESTとは言っていないことが少し気になったが、正確な意味でのRESTではないので避けた説、RESTの宗教論争に巻き込まれるのがイヤだった説とかいろいろ挙がっていた。あとで懇親会のときに高橋さんに聞いたら「深く考えてないだけでは」ということだったが(笑)。
あとカンファレンス参加者が多かったせいか、このセッションの参加者が5人と少し寂しかった気がした。
後半セッションは「ActiveRecordモデリング」。ソーシャルブックマークを作るならというお題で、DB設計とモデリング、実際にActiveRecordを使ったコード例を書いてみようという趣旨。
UserとPageがあって、多対多の関係なのでBookmarkを追加し、habtmはやめてhas_many throughを使おう…、みたいな感じ?(詳細はあまりメモってなかった)
あとの懇親会も含めて、YuguiさんがABD(Activity Based Datamodel; はぶさん提唱のDB設計法)を連呼していたのが印象的だった。不勉強だったのでちょっと調べてみるとなかなかエキセントリック(は言い過ぎか)で興味深い。
懇親会では、はぶにっきを読みつついろいろ話した。DHHの講演内容に関連してREST話も少し出た。高橋さんがREST原理主義(?)だというのが判明して、意外だった。
で、結論としてはとりあえず「楽々ERDレッスン」読もうね、ということに(笑)。買おう。
ヤドカリの人とほとんど一緒にいたのでかぶってしまってる(^^; とくに2次会が詳細です。
投稿者 4bit : 16:23 | コメント (0) | トラックバック (1)
2006年06月15日 (木)
DHH loves REST!? その2(ActiveResource) [テクニカル]
その1のつづき。ActiveResourceはさらにヤバイ。
ActiveResource
moroの日記 - 日本Rubyカンファレンス2006 二日目より
- ActiveResouce!!
- one more thingとか言うあたりがマカー
- Webサービスで得られる情報をActiveRecordライクに。
- 当然CRUDできる。
- Rails 1.2の目玉。
- 6/11 22:00 JST時点ではsvnツリーにもない模様。
- ValidationとかAssociationも使えるんですかね? Validationは大丈夫そう。
- RESTしか対応しない。SOAPとかXML-RPCは嫌いらしい。
- ちゃんと使う似は厳しい規約が必要(HTTPメソッドだけでCRUDできるとか)。Rails製アプリケーション間での使用が中心になるのかなぁ。
UIE Japan Developer Blog: 日本Rubyカンファレンス2006レポート (2006/06/11)よりDHH > 「XMLRPCもSOAPも使いたくない」
Rails1.2のtrunkにもまだ上がっていない様子のActiveRecordからCRUDを操作できるActiveResourceの話が面白い。URLをモデルの中に隠蔽して後は気にせず、AR同様に使うことができる。認証周りは、HTTP Authentication, Digest認証, SSLを誰かが作ってくれるかも。
Person = ActiveResorce::Struct.new do |p|
p.uri "http;//www.example.com/people"
p.credentials :name => "dhh", :password => "secreat"
end
david = Person.new(:name => "David")
# GET http://www.example.com/people
# <person><name>David<name></person>
# => Location: http://www.exapmle.com/people/2
david.find(:name => "David")
# PUT http://www.example.com/people
# <person><name>David Heinemeier Hasson</name></person>
# => (200 OK)
david.save
class ActiveResource::Base
uri "http://www.example.com"
credentials :name =>"dhh", :password => ""
end
何がヤバイって、「ActiveResourceでアクセス可能なAPI」という合意を得て、REST APIのデファクトスタンダードを形成する可能性があるってこと。細かいことを言えばfindの規約とかどうするかわからないけど、OpenSearchでもいいし、とにかくRailsの機能として実装すればそれがデファクトになりうる。
例えばすごく単純に、columnカラムがquerywordなリソースを取ってくるには/controller?column=querywordとかでもいいんじゃない?pageとかとバッティングするのがちょっとまずいけど。
実はActiveResourceに似た構想はちょっと前に考えてたんだけど(とか言ってみるテスト)。僕の着想のベースは、Ajaxのクロスドメイン制約を回避するために、proxyのようなものが必要なので、それをRailsベースで作れないかなぁということだった。ActiveResourceができればproxyどころかもっと便利に使える。さすがDHH。ぜひ実現してほしい。
投稿者 4bit : 12:49 | コメント (0) | トラックバック (0)
DHH loves REST!? その1(RESTプラグインの紹介) [テクニカル]
日本Rubyカンファレンス2006。DHHのセッション内容がヤバイ。チケットが入手できなかったので聞けなかったけど(発表資料くれー)。タイトルが「One controller, many ins, many outs」→「Discovering a world of Resources on Rails」。うひょー。世界リソース発見。
Blogなどでレポートを書いてるみなさんありがとうございます。以下関係部分を引用。
moroの日記 - 日本Rubyカンファレンス2006 二日目より
- CRUD素晴らしい
- HTTPのメソッドで、既にCRUDできるじゃん。HTTPのPOST GET PUT DELETEメソッドとコントローラのアクションcreate show update destroy、SQLのINSERT SELECT UPDATE DELETEは直接に対応してるじゃん。
- これを繰り返すのはDRYじゃないよね?
- ActionController::Routing::Routes.draw{|map| map.resource "/controller/:id" }という宣言をすると、HTTPの各メソッドによって"/controller"を叩くことでCRUDのお好きな操作をば。
UIE Japan Developer Blog: 日本Rubyカンファレンス2006レポート (2006/06/11)よりREST
HTTPメソッドだけでCRUDできるよね。複数個所に分かれているのはDRYじゃないし、POST /peopleform_forでmethodを定義 ブラウザのformでputやdeleteできないのでmethodはhiddenで渡す (javascriptで~~と言いかけて訂正していたのでjsのputやdeleteも使うようになるのかも) また、CRUDはゴールでなくゴールを目指す肝であり設計の技法ですよ。
GET /people/1
PUT /people/1
DELETE /people/1
このへんから推察するに、Simply RESTfulプラグイン、RESTful Railsプラグインの機能(に近いもの)を標準に取り込むということでは?
Simply RESTfulプラグイン
routes.rbにmap.resourceというメソッドを追加。map.resource :itemと書くと以下のようなルーティングが生成される。
| VERB | URL structure | Rails method |
|---|---|---|
| Display | ||
| GET | /items | index |
| GET | /items/1 | show |
| Create | ||
| GET | /items/new | new |
| POST | /items | create |
| Remove | ||
| DELETE | /items/1 | destroy |
| POST | /items/1?_method=DELETE | destroy (synonym) |
| Update | ||
| GET | /items/1;edit | edit |
| PUT | /items/1 | update |
| POST | /items/1?_method=PUT | update (synonym) |
| POST | /items/1;complete | complete |
これはDHHの言ってるルールと符合する。
RESTful Railsプラグイン
routes.rbにmap.connect_resourceというメソッドを追加。map.connect_resource :item と書くと以下のようなルーティングが生成される。
| URL structure | Rails method |
|---|---|
| /item | new |
| /items | collection |
| /items/1 | by_id |
さらにコントローラに
resource :collection do |r|
conditions << @books = Book.find(:all)
r.post do
...
end
end
resource :by_id do |r|
r.put do
...
end
r.delete do
...
end
end
などと書いて処理を行う。
その他条件リクエスト処理機能(リクエストされたリソースが更新されていなければ304 Not Modifiedを返すなど)など。詳しい使い方はXML.com: Putting REST on Rails参照。
その2へつづく。
投稿者 4bit : 11:49 | コメント (0) | トラックバック (0)
2006年05月25日 (木)
簡単認証プラグイン試作 [テクニカル]
「ヽ( ・∀・)ノくまくまー(2006-05-21)」より本格的な認証機能は不要なので、のーにゅーまでもう時間がない!みたいな必死なときに30秒くらいでとりあえずな認証をかけられるものがあると便利だとゆいたいです。とりあえず .htaccess でBasic認証をちょこっと置いてます、みたいな。
class AdminController < ApplicationController htpasswd :user=>"maiha", :pass=>"berryz" # 認証(何行でもかけて上から随時実行) htpasswd :file=>"/var/www/passwd/.htpasswd" # 外部ファイル指定も可能(htpasswd 互換) end
Basic認証でよければ、ってことで認証まわりの練習がてらプラグインをでっちあげてみた。
だいたい上の使用例の感じで動くはず。動かなかったらごめんなさい。
追記:くまくまーの中の人に添削してテストも書いてもらった!感謝! てことで使うときはこちらをどうぞ→「ヽ( ・∀・)ノくまくまー(2006-05-25)」
コード。汚いので添削希望。
module Htpasswd
def self.included(base)
base.extend(ClassMethods)
end
class Error < StandardError
define_method(:message) { 'Authorization is required' }
end
module ClassMethods
def htpasswd(options={})
if options[:file]
type = options[:type] || :crypted
IO.foreach(options[:file]) do |line|
user, pass = line.chomp.split(':', 2)
write_inheritable_array(:htpasswd, [{:user => user, :pass => pass, :type => type }])
end
else
write_inheritable_array(:htpasswd, [{:user => options[:user], :pass => options[:pass], :type => :plain }])
end
skip_before_filter :htpasswd_authorize rescue nil
before_filter :htpasswd_authorize
end
end
protected
def htpasswd_authorize
raise Htpasswd::Error unless auth_header = request.env['HTTP_AUTHORIZATION']
auth_type, auth_data = auth_header.split(' ', 2)
user, pass = Base64.decode64(auth_data).split(':', 2)
raise Htpasswd::Error unless pass.length > 0
auth_users = self.class.read_inheritable_attribute(:htpasswd)
auth_success = false
auth_users.each do |h|
case h[:type]
when :plain
if h[:user] == user and h[:pass] == pass
auth_success = true
break
end
when :crypted
if h[:user] == user and h[:pass] == pass.crypt(h[:pass])
auth_success = true
break
end
end
end
raise Htpasswd::Error unless auth_success
return true
rescue Htpasswd::Error => error
realm = "Authorization"
response.headers['WWW-Authenticate'] = response.headers['WWW-Authenticate'].to_a
response.headers['WWW-Authenticate'].push("Basic realm=\"#{realm}\"")
#headers['Status'] = '401 Unauthorized'
render :nothing => true, :status => 401
return false
end
end
投稿者 4bit : 16:34 | コメント (1) | トラックバック (0)
2006年05月21日 (日)
Rails勉強会@東京 第6回 [テクニカル]
ポジションペーパーは、「RESTプラグイン試作」というもので一応試作したのを置いときます。ただしモデルのテーブルのカラム名により動かない可能性あり。ソースも汚いです。
前半セッションは高橋さんの「Typoの改造」。Railsで作られているBlogシステムのTypoを改造してますという話。実は僕もTypoを改造しようかと思って(思っただけでやってない)、svn trunkのソースを眺めてみたことがあったので興味深い話だった。あとでruby-listを見てみたら関連スレッド([ruby-list:42174] i18n Typo and Ruby-GetText)を発見。
- 改造対象バージョンは2.6.0(stable)
- svn trunk(ver4系列)はテーブル構造とかすごくいろいろ変わってて追っかけるのが大変
- I18N化改造
- メッセージを日本語化
- Ruby-Gettext-Package(GNU gettextライクなツール)を使用
- RailsにインストールするとRakefileができる
- updatepo…viewの _(...) からpotファイルを生成
- makepo…poファイルからmoファイルを生成
- マルチユーザ化改造
- URIにユーザIDを含めて、ArticlesやCommentsテーブルのuser_idから該当のユーザのデータだけを抽出して表示する
僕は存じ上げなかったのだが、JIS文字コード関係などで有名な芝野先生が来ていらっしゃって、国際化(多言語化)の話でなかなか激論が交わされた。
後半はsecondlifeさんの「Mongrelのソースを読む」。Ruby(一部C)のWebサーバであるMongrelの紹介とソース読み。しかし僕はノートパソコンを持っていなかったこともあってちょっと取り残された感じ。ほとんどメモも取っていなかった。
- Mongrelは高速でRailsにも対応してるのですぐ使える
- WEBrickは起動が遅い→開発意欲低下
- Mongrelならさくさく起動するので快適
- でも信頼性はまだ疑問?
- lighttpdよりは遅いのでdevelopment環境用に使うとGOOD
都合で懇親会は遠慮させてもらったが(井上さんすみませんでした)、有意義な一日だった。僕もRESTプラグインがもう少し実用的になればそれをネタに1セッションやりたいなぁとも思ったのだがなかなか難しそうだ…。
投稿者 4bit : 23:59 | コメント (0) | トラックバック (1)
2006年04月17日 (月)
Controller#respond_toはWeb ApplicationとWeb Serviceの垣根をなくす!? [テクニカル]
昨日のRails勉強会のポジションペーパーの内容を起こしてみた。内容はほとんどヽ( ・∀・)ノくまくまーからのインスパイヤなんですが。なので詳しくは元記事を見てください。このblogの記事の流れとしてはずいぶん前の「RESTful Web Applicationの可能性」からの続きの内容という感じです。
Rails 1.1からの新機能として、Controller#respond_toというメソッドができた。どういうものかというと、
- HTTP/1.1リクエストヘッダ中のAcceptフィールドを見る
- Content-Typeに応じてリクエストのデータ形式を自動変換してくれる
- 従って、コントローラは同じロジック(action)で対応できる
- Acceptの種類(mimeタイプ)に応じて、実行する描画処理を指定できる
- "*/*"が指定された場合はrespond_toの最初の定義を実行する
respond_to do |type|
type.html { render }
type.yaml { render :text => @resource.to_yaml }
type.xml { render :text => @resource.to_xml }
end
さらにREST的インターフェイスを実現するために自前でコントローラを実装する。
class RestController < AbstractRestController
def resource
model_name = params[:model].camelize
model = eval(model_name) # *超危険*
if params[:id] # idがあればMember URI
id = params[:id]
@resource = model.find(id)
case request.method
when :get
# Retrieving a Resource
respond_to do |type|
type.xml { render :text => @resource.to_xml }
type.yaml { render :text => @resource.to_yaml }
#type.json { render :text => @resource.to_json }
#残念ながらtype.jsonはまだ対応していない
end
when :put
# Updating a Resource (省略)
when :delete
# Deleting a Resource (省略)
end
else # idがなければCollection URI
case request.method
when :get
# Listing Collection Members (省略)
when :post
# Creating a Resource
new_resource = model.new(params[params[:model].to_sym])
if new_resource.save
render_post_success(:id => new_resource.id)
else
render :text => new_resource.errors.full_messages.join("\n"), :status => 406
end
end
end
end
さらにroutes.rbをこんな感じに設定。
map.connect 'rest/:model/:id',
:controller => 'rest', :action => 'resource', :id => nil
/rest/<モデル名>/<ID> という統一されたURI(Atom ProtocolでいうMember URI)でリソースにアクセスでき、さらに"Accept: application/xml"をつけるとXMLで取得、"Accept: application/x-yaml"をつけるとYAMLで取得したりできる。(JSONのMIMEタイプにまだ対応していないのが惜しいが、application/javascriptでもいいかな)
さらに取得だけではなく、/rest/<モデル名>というURI(Collection URI)に"Content-Type: application/xml"をつけてXMLをPOSTすれば、通常のFORM形式に変換してデータをCREATEしてくれる(くまくまーでは「うまく動きませんでした」って書いてあるけど、Rails 1.1.2で動作を確認。ただしContent-Lengthヘッダが必要)。
アプリケーションのすべてがRESTである必要はないが(というか無理)、Ajaxで使われるインターフェイスなどはとくにこんな感じで簡単にRESTが使えると、Webアプリケーションが即Webサービスとしても使えるようになるのでうれしい。
参考:
投稿者 4bit : 11:21 | コメント (2) | トラックバック (0)
Rails勉強会@東京 第5回 [テクニカル]
第0回以来、久しぶりにRails勉強会に参加。ポジションペーパーの内容はこちら
前半のセッションは、僕がなにげなく発した「Rails 1.1の新機能って前回やったんですっけ?」の一言からセッションオーナーになってしまい、たいした準備もないままぐだぐだのセッションになってしまった。参加してくださった皆さんすいませんでした。そしてサポートしてくださったIさん(名前間違ってたらすいません)本当にありがとうございました。内容はこんな感じ。
- Cascaded Eager Loading (ActiveRecordでは最も大きな変更点) 参考1 参考2
- 実際のアプリのDB構成では2階層以上のリレーションを持つ場合がほとんどなので、今まではSQLを書いていたが、これによって書く手間が省ける。とてもうれしい。使いまくり
- paginateで使えるの? →ソースを見てみた結果、findを呼んでるだけなので使えるはず。OFFSET, LIMITをつけたときの挙動などはSQLの問題
- Rakeコマンドのnamespaceが変更
rake -Tでタスク一覧を見てみるとコロンでつなぐ形式に変わっているのがわかる- tmp:sessions:clearとかrails:updateとかいろいろ使えそう
- Rails 1.1(というかRake 0.7)になってタスクがかなり増えている?
- 「Rakeを使いこなす」って感じで独立セッションにしてもおもしろそう
- 国際化
- 1.1でもあまり変わっていない
- ActiveHeartは使えるはずなので使いましょう
- Controller#respond_to
- 僕が個人的に注目してます(ポジションペーパー参照)
後半のセッションは、かくたにさんの「俺と一緒にRecipe 43を一緒に読まないか」。Rails Recipesという本の主にIntegration Tests関係の話題。
- Testing Across Multiple Controllers
- 今までModel(unit)とController(function)単位のテストサポートだったが、Integration Testsとしてストーリーレベルのテストをサポート
- ストーリーに沿ってテストを可読性の高い形で記述しよう。そうするとテストがもっと楽しくなるよ
- DSLマンセー
- Make your URLs Meaningful
- 名前つきルートを効果的に使おう
url_for :action => :loginのかわりにlogin_urlとか書けるので可読性がさらにアップ
終わった後は恒例の懇親会。なんとなく、みんなJavaには苦労してるんだなーと思ったり、意外な人のつながりがわかったり、出版業界の裏話とか聞けたりしておもしろかったです。みなさんありがとうございました。そして幹事の井上さんありがとうございました。
投稿者 4bit : 10:14 | コメント (0) | トラックバック (0)
2006年04月04日 (火)
Maven2のホームディレクトリ設定 [テクニカル]
そろそろJavaを使い始めなければならないのでMaven2でプロジェクトを作ってみる。昔Maven1は使っていたんだけどもうJava自体かなり忘れているのでわからないことだらけ。「Maven2のTipsを集めるWiki - CookBook」を見てプロキシなどを設定。
「nobeansの日記 - Windows環境でのローカルリポジトリ」よりデフォルトでは C:\Documents and Settings\<ユーザID>\.m2 配下なのはいいんですが、HOME環境変数を設定しても変わってくれません。なんで?
cygwinつかってるので、cygwin上での /home/<ユーザID>/.m2 にあたるディレクトリに変更したいんですけど。
激しく同感。Maven2から認識されるホームディレクトリは環境変数HOMEではなくてUSERPROFILEから取ってるらしい。ただこれを変えるのはちょっとまずそうなので、mvn.batをのぞいてみるとMAVEN_OPTSという環境変数を見てくれるらしい。よってこの値に -Duser.home=C:\path\to\cygwin\home\<ユーザID> と入れてやれば、ちゃんと変わってくれた。
参考:
投稿者 4bit : 17:40 | コメント (0) | トラックバック (0)
2006年03月30日 (木)
TypeKey認証を使ってみる [テクニカル]
「TypeKeyによる認証 :: wiki.rails2u.com」を参考に、RailsでTypeKey認証を利用してみたのでメモ。
最初TypeKey側でエラーが出ていっこうにログインできるようにならなかったのだが、TypeKeyアカウント設定の「コメント登録するウェブログの指定」にURLを登録しなければいけなかったらしい。現在localhostで実験中なので http://localhost:3000/ てな感じで指定する。
次に、Windows環境のため /tmp/tk_key_cache がないというエラー。type_key.rbの55行目あたりをこんな感じに変更。
tempdir = ENV['TMPDIR'] || ENV['TMP'] || ENV['TEMP'] || '/tmp'
@key_cache_path = tempdir + '/tk_key_cache'
最後に、サンプルコードの redirect_top メソッドがないエラーが出たので、 redirect_to top_url and returnに書き直して終了。動作OK。
認証とかめんどいので他に任せてしまいたい僕としてはTypeKeyはかなりうれしい。便利だなー。
投稿者 4bit : 17:49 | コメント (0) | トラックバック (0)
2006年02月28日 (火)
RailsによるアジャイルWebアプリケーション開発 [テクニカル]
買いました。英語の原著も買ってたんだけど、やっぱり日本語のほうが安心感がある。Rails1.0に対するフォローも入っていていい感じ。
Pragmatic Bookshelf (2005/09/22)
売り上げランキング: 3,522
せっかく買ったんだから、来月のリハビリ期間には何か作ってみたいなぁ。Typoっていうブログツールはよくできているので、これをいじってみるかな。今はこのブログはMovable Typeを使ってるけど、結局Rubyという言語が好きなので、Typoに移行するかも。
投稿者 4bit : 12:06 | コメント (0) | トラックバック (0)





