私は Ruby の初心者であり、DataMapper やその他の ORM の初心者です。私は Perl のバックグラウンドを持っており、実際には OOP タイプの開発者ではありません。だから私はここで未知の領域をさまよっています。長文の質問で申し訳ありません...
このプロジェクトでは、deviceclasses と deviceclasses の下にマップされるデバイスの概念があります。Deviceclasses は、子 deviceclasses を持つことができる必要があります。共通のルート deviceclass 名 (つまり、すべての deviceclass が由来するルート) は "FOO" または "BAR" (このサンプル コードでは) と呼ばれ、それぞれに任意の子 devicesclasses のセットを含めることができます。最後に、deviceclass には最終的にデバイスが含まれます。
Deviceclasses には多くの deviceclass があります Deviceclasses には多くのデバイスがあります deviceclass には 1 つの deviceclass_name があります 多くのデバイスは deviceclass に属します
だから、IE:
FOO
JOHNSHOUSE
UPSTAIRS
device1
device2
DOWNSTAIRS
device1
device2
MANYHOUSES
JOE
GARAGE
device1
device2
SUZY
BEDROOM
device1
device2
device3
TIM
LIVINGROOM
device1
ARBITRARY
device1
SOMEPLACE
device1
device2
BAR
ENGLAND
LONDON
MYHOUSE
BEDROOM
device1
device2
device3
そして、ここで私は立ち往生しています...デバイスとデバイスクラスはDBに自律的に追加できる必要があり、それらの関連付けは後で実行されます。だから、私はできません
deviceclass = MyDB::Deviceclass.new
device = MyDB::Device
deviceclass.device.new(blah)
この一連の質問の基礎となる関連モデルを含む私のモジュール...
質問 1 - 私はこれを正しく行っていますか? Deviceclass の下の self.validate_root_deviceclasses メソッドに注意してください。n
何よりも先に DB にルート デバイスクラスを用意する必要があるため、このメソッドでそれらを作成します。残念ながら、プロパティの更新は機能しません。私はそれについて何らかの方向性が欲しいです。
module DeviceDB
ROOT_DEVICECLASSES %w{FOO BAR}
class Deviceclass
include DataMapper::Resource
property :id, Serial
property :hw_id, String, :unique => true
property :root_deviceclass, Boolean, :default => false
property :parent_deviceclass_id, Integer
property :deviceclass_name, String
property :updated_at, DateTime
property :created_at, DateTime
has n, :devices, :through => Resource
has n, :deviceclasses, :through => Resource
has 1, :deviceclass, self, {:through=>:deviceclasses, :via=>:parent_deviceclass_id}
def self.validate_root_deviceclasses
root_deviceclasses = all(:root_deviceclass => true)
if root_deviceclasses.count > 0
# get whats in the db now
db = Array.new(root_deviceclasses.map(&:deviceclass_name))
# match it against the global list (top of this file)
missing = ROOT_DEVICECLASSES.map{|root| root unless db.grep(/#{root}/i)[0]}.compact
# if something's missing, add it.
missing.each do |missing|
begin
create(:deviceclass_name => missing, :root_deviceclass => true).save
rescue DataMapper::SaveFailureError => e
@error = [e.resource.errors.map{|err| err}].join(', ')
return(false)
end
end
else
begin
ROOT_DEVICECLASSES.each do |root|
create(:deviceclass_name => root, :root_deviceclass => true).save
end
rescue DataMapper::SaveFailureError => e
@error = [e.resource.errors.map{|err| err}].join(', ')
return(false)
end
end
begin
default = first(:deviceclass_name => 'PTS').id
property :parent_deviceclass_id, Integer, :default => default # fail
DataMapper.finalize # fail
return(self)
rescue DataMapper::SaveFailureError => e
@error = [e.resource.errors.map{|err| err}].join(', ')
end
return(true)
end
end
class Device
include DataMapper::Resource
property :id, Serial
property :deviceclass_id, Integer
property :device_id, String, :unique => true
property :devicename, String
... more properties...
property :updated_at, DateTime
property :created_at, DateTime
belongs_to :deviceclass, :required => false
end
DataMapper.finalize
DataMapper.auto_upgrade!
Deviceclass.validate_root_deviceclasses
end
質問 2: deviceclasses とデバイスを関連付ける魔法のような方法はありますか? それとも、デバイスの ID を取得し、更新を介して関連付けられた deviceclass に関連付けるという難しい方法で行う必要がありますか?
質問 3: :default を追加することでテーブルを効果的に変更する、テーブルが既に移行された後にモデルにプロパティを追加する方法はありますか (上記の失敗例を参照)。そうでない場合、モデルの作成中にデフォルト値を取得する方法はありますか? ラムダが思い浮かびますが、それはテーブルが既に存在し、ROOT_DEVICENAMES が既に追加されている場合にのみ機能します。