我是Ruby的新成員,甚至是DataMapper的新成員,或者任何針對此問題的ORM。我來自Perl背景,並不是真正的OOP類型的開發人員。所以我在這裏遊蕩在未知的領域。對於長期問題的歉意......Ruby DataMapper:模型關聯評論,完成後的模型更新以及關聯稍微自主的記錄
在這個項目中,我有設備類和設備的概念,這些設備類將被映射到deviceclasses下。設備類需要能夠擁有子設備類。通用根設備類名稱(換句話說,所有設備類來自的根)稱爲「FOO」或「BAR」(在此示例代碼中),並且每個設備類都可以有一組任意子設備類。最後,設備類最終包含設備。
所以: Deviceclasses有很多deviceclasses Deviceclasses有許多設備 一個設備類的有一個deviceclass_name 許多設備屬於設備類的
因此,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
這裏的地方我卡住...設備和設備類必須能夠自動添加到數據庫並且它們的關聯將在稍後執行。所以,我不能這樣做
deviceclass = MyDB::Deviceclass.new
device = MyDB::Device
deviceclass.device.new(blah)
我的模塊,它包含了相關的模型,其中我立足本組問題...
問題1 - 我這樣做對嗎?請注意,Deviceclass下的self.validate_root_deviceclasses方法。我必須先在數據庫中安裝n
根設備類,然後才能使用此方法創建它們。不幸的是,屬性更新不起作用。我會喜歡這方面的一些方向。
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,並通過更新到相關的設備類相關聯,它做它的強硬的方式有些神奇的方式?
問題3:有沒有辦法在表已遷移之後向模型中添加屬性,以便通過添加以下內容來有效更改表:default(請參閱上面的失敗案例)。如果沒有,有什麼方法可以在創建模型期間獲得我的默認值。可以想到Lambda,但只有當表已經存在並且已經添加了ROOT_DEVICENAMES時纔可以使用。
不錯!我將檢查dm-is-tree和dm-sweatshop模塊。感謝這些指針!至於#3,我基本上試圖完成的是將默認記錄插入表中,其中:default將從屬性的其中一個記錄中派生:parent_deviceclass_id。在這方面有什麼額外的想法? – Jim 2013-03-22 17:19:35