« Northern Ireland Trophy | メイン | Rails勉強会@東京 第10回 »
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の将来の版ではこういうのが載るようになるのかな。
トラックバック
このエントリーのトラックバックURL:
http://www.4bit.net/x/mt/mt-tb.cgi/141