Note that there are some explanatory texts on larger screens.

plurals
  1. PORuby DataMapper: model associations review, model updates after finalize, and associating slightly autonomous records
    primarykey
    data
    text
    <p>I am brand new to Ruby and even newer to DataMapper, or any ORM for that matter. I come from a Perl background and am not really an OOP type of developer. So I'm wandering in unknown territory here. Apologies for the long-winded question...</p> <p>In this project, I have the concept of deviceclasses and devices which will be mapped under the deviceclasses. Deviceclasses need to be able to have child deviceclasses. The common root deviceclass names (in other words the root from which all deviceclasses come) are called "FOO" or "BAR" (in this example code) and each of those can have an arbitrary set of children devicesclasses. Finally, deviceclasses eventually contain devices.</p> <p>So: Deviceclasses have many deviceclasses Deviceclasses have many devices A deviceclass has one deviceclass_name many devices belong to a deviceclass</p> <p>So, IE:</p> <pre><code>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 </code></pre> <p>And here's where I'm getting stuck...devices and deviceclasses <em>must</em> be able to be autonomously added to the DB and their associations will be performed later. So, I can't do </p> <pre><code>deviceclass = MyDB::Deviceclass.new device = MyDB::Device deviceclass.device.new(blah) </code></pre> <p>My module, which contains the pertinent models for which I'm basing this set of questions...</p> <p>Question 1 - Am I doing this right? Note that self.validate_root_deviceclasses method under Deviceclass. I have to have the <code>n</code> root deviceclasses in the DB before anything else so this method creates them. Unfortunately, the property update does not work. I would love some direction on that.</p> <pre><code>module DeviceDB ROOT_DEVICECLASSES %w{FOO BAR} class Deviceclass include DataMapper::Resource property :id, Serial property :hw_id, String, :unique =&gt; true property :root_deviceclass, Boolean, :default =&gt; false property :parent_deviceclass_id, Integer property :deviceclass_name, String property :updated_at, DateTime property :created_at, DateTime has n, :devices, :through =&gt; Resource has n, :deviceclasses, :through =&gt; Resource has 1, :deviceclass, self, {:through=&gt;:deviceclasses, :via=&gt;:parent_deviceclass_id} def self.validate_root_deviceclasses root_deviceclasses = all(:root_deviceclass =&gt; true) if root_deviceclasses.count &gt; 0 # get whats in the db now db = Array.new(root_deviceclasses.map(&amp;: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 =&gt; missing, :root_deviceclass =&gt; true).save rescue DataMapper::SaveFailureError =&gt; e @error = [e.resource.errors.map{|err| err}].join(', ') return(false) end end else begin ROOT_DEVICECLASSES.each do |root| create(:deviceclass_name =&gt; root, :root_deviceclass =&gt; true).save end rescue DataMapper::SaveFailureError =&gt; e @error = [e.resource.errors.map{|err| err}].join(', ') return(false) end end begin default = first(:deviceclass_name =&gt; 'PTS').id property :parent_deviceclass_id, Integer, :default =&gt; default # fail DataMapper.finalize # fail return(self) rescue DataMapper::SaveFailureError =&gt; 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 =&gt; true property :devicename, String ... more properties... property :updated_at, DateTime property :created_at, DateTime belongs_to :deviceclass, :required =&gt; false end DataMapper.finalize DataMapper.auto_upgrade! Deviceclass.validate_root_deviceclasses end </code></pre> <p>Question2: is there some magical way to associate the deviceclasses and devices or do I need to do it the tough way by grabbing an id of the device and associating it via update to an associated deviceclass?</p> <p>Question3: Is there a way I can add a property to the model after the table has already been migrated which would effectively change the table by adding :default (see the fail case above). If not, is there any way I can obtain my default value during the creation of the model. Lambda comes to mind but that would only work if the table already exists and the ROOT_DEVICENAMES have already been added.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload