« Northern Ireland Trophy | メイン | Rails勉強会@東京 第10回 »

2006年09月21日 (木)

DepotにABDを適用してハマった [テクニカル]

RailsによるアジャイルWebアプリケーション開発(通称AWDwR)」にサンプルとして載っているDepotアプリケーションにABDを適用して作り直したらどうなるだろう?というのを少し前にやっていたのだが、意外なところでハマったのでメモ。

テーブル設計はもともとのがこんな感じ。典型的なマスタ・ディテール形式。
DepotのER図

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

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 : 2006年09月21日 17:53 このエントリーを含むはてなブックマーク

トラックバック

このエントリーのトラックバックURL:
http://www.4bit.net/x/mt/mt-tb.cgi/141

コメント

コメントしてください




保存しますか?