次の属性を持つItemクラスがあります。
itemId,name,weight,volume,price,required_skills,required_items
。
最後の2つの属性は複数値になるため、それらを削除して次のような新しいスキームを作成します。
itemID,required_skill
(itemID
は外部キー、itemID and required_skill
は主キーです。)
今、私はこの新しいテーブルを作成/使用する方法に困惑しています。私が思いついたオプションは次のとおりです。
1)ItemsとRequired_skillsの関係は1対多であるため、requiredSkillクラスを作成することができます。これは、one_to Itemにn個のRequiredSkillが含まれています。その後、私は行うことができますItem.get(1).requiredskills
。これは私にとって最も論理的に聞こえ、次のようなメソッドとクエリを提供します。
sugar.components.create :raw_material => water.name
sugar.components.create :raw_material => sugarcane.name
sugar.components
sugar.components.count
2)required_skillsは(ルールに似ているため)定数と考えることができるため、ハッシュデータベース、gdbmデータベース、または別のsqlテーブルに入れて、そこからクエリを実行することもできます。
私の質問は:データマッパーのモデルレステーブルのようなものはありますか?データマッパーはテーブルの作成と整合性に責任があり、データマッパーの方法でそれをクエリすることができますが、SQLで行うようにクラスを必要としません?
最初の方法を使用して問題を解決しました。正規化プロセスごとに新しいクラスを作成しました(上記の1対多の関連付けのように見えます)。しかし、私はオブジェクト指向プログラミングに不慣れであり、そのような正規化ごとに新しいクラスを作成することが、データマッパーでそれを行う通常の方法であるのか、それともハックであるのかわかりません。これと、これを行うためのより良い方法があるかどうかは、私が知りたいことです。
あずきっく
再読datamapper.org団体に数回、今私はDataMapperのは確かに参加するために別々のクラスを必要としていることがわかります。だからあなたは私の質問に答えました。しかし、ロバート・ハーベイが賞金を置いたので、私はダイナミックな方法についての応答をもう少し待つ責任を感じています。
あなたのコードは不満を述べましたCannot find the child_model Container for Item in containers
。私はそれを以下のような自己参照関連付けの2番目の例でうまく動作させることができました(他のものへの参照としてここに置く):
class Item
class Link
include DataMapper::Resource
storage_names[:default] = "requirement_links"
belongs_to :require, "Item", :key => true
belongs_to :required, "Item", :key => true
end
include DataMapper::Resource
property :id, Serial
property :name, String, :required => true
has n, :links_to_required_items, "Item::Link", :child_key => [:require_id]
has n, :links_to_requiring_items, "Item::Link", :child_key => [:required_id]
has n, :required_items, self,
:through => :links_to_required_items,
:via => :required
has n, :requiring_items, self,
:through => :links_to_requiring_items,
:via => :require
def require(others)
required_items.concat(Array(others))
save
self
end
def unrequire(others)
links_to_required_items.all(:required => Array(others)).destroy!
reload
self
end
end
だから私はできる:
jelly = Item.get :name => "Jelly"
sugar = Item.get :name => "Sugar"
jelly.require sugar
アイテムを要求し、:
jelly.required_items.each { |i|; puts i.name }
本当に素晴らしい要件をリストアップします。
あなたの答えを読んだ後、私はまだデータベーススキーマをさらに正規化していないようです。正直なところ、原材料と製品の関係を自己参照として定義することのポイントはわかりません。つまり、それが小さなプログラムであれ{:jelly => ":sugar => 3, :water => 5"}
ば、YAGNIの原則に従って、必要なアイテムと金額を反映するようなハッシュを使用することは確かです。最初のオプションのようにそれを行うと、自己参照関連付けによって提供されるものと同じくらい単純なクエリとメソッドがすでに提供されます。(ただし、オブジェクトへのメソッド呼び出しではなく、ストアドプロシージャのように見えることを認めなければなりません。)
それでは、私の単純なアプローチと比較して、理解/実装が難しい自己参照関連付けを使用する利点を説明していただけませんか?私はOOPに不慣れで、私はアンダーモデリングのようなものかと思います。