DMS is designed to make it easy to handle not one, but as many different repositories as you like. To that end, it supports Sheepdip, so you can use custom domain objects to manage the database metadata, making it easy for you to extend and customize the DMS tables. In fact, the default implementation actually uses a simple Sheepdip object, though you don't see it. In this section, we will cover how you can create your own custom Sheepdip object to manage metadata.
Let's say you have an Sheepdip class called
Podcast
. In this case, you want a DMS repo that is
tailored to holding podcast files and data. It is defined as follows:
<table name="Podcast" namespace="Public"> <columns> <column name="contentType" typeid="&text_t;" null="false" default="'text/html'"/> <column name="ctime" typeid="&i32_t;"/> <column name="deleted" typeid="&bool_t;" null="false" default="false"/> <column name="podcastId" typeid="&id_t;"/> <column name="guid" typeid="&text_t;" null="false" default="uuid_generate_v1()"/> <column name="hash" typeid="&string_t;" length="255" null="false" default=""/> <column name="mtime" typeid="&i32_t;"/> <column name="name" typeid="&string_t;" length="255" null="false"/> <column name="size" typeid="&i32_t;"/> <column name="title" typeid="&text_t;"/> <column name="description" typeid="&string_t;" length="255" null="false" default=""/> <column name="date" typeid="&date_t;"/> <column name="bitrate" typeid="&i32_t;"/> <column name="length" typeid="&i32_t;"/> </columns> <indexes> <index name="PRIMARY"> <fields> <field name="podcastId"/> </fields> <constraints> <constraint type="UNIQUE"/> </constraints> </index> </indexes> </table>
The last five columns are custom columns we've added that relate to podcast files. From this, Sheepdip generates the following code:
#------------------------------------------------------------------------------- # THIS CODE WAS AUTOMATICALLY GENERATED: DO NOT MODIFY # # File : podcast.rb # Source : site # Version : 0.0.1 # Created : 2010-07-01 21:09:08 -0500 #------------------------------------------------------------------------------- require 'jw/sheepdip/app' require 'jw/sheepdip/object' module Podcast class Schema < JW::Sheepdip::Schema def initialize(a=nil) super(Podcast, 'public', a, '0.0.1') create('bitrate', Fixnum, false, '') create('contentType', String, false, '') create('ctime', Fixnum, false, '') create('date', String, false, '') create('deleted', ::Object, false, '') create('description', String, true, '') create('podcastId', Fixnum, false, '') create('guid', String, false, '') create('hash', String, true, '') create('length', Fixnum, false, '') create('mtime', Fixnum, false, '') create('name', String, true, '') create('size', Fixnum, false, '') create('title', String, false, '') end end class Object < JW::Sheepdip::Object set_schema Schema.new() def initialize(db, id = -1) super(db) @id = id self.class.addAttribute('bitrate') self.class.addAttribute('contentType') self.class.addAttribute('ctime') self.class.addAttribute('date') self.class.addAttribute('deleted') self.class.addAttribute('description') self.class.addAttribute('podcastId') self.class.addAttribute('guid') self.class.addAttribute('hash') self.class.addAttribute('length') self.class.addAttribute('mtime') self.class.addAttribute('name') self.class.addAttribute('size') self.class.addAttribute('title') end def schema() return self.class.schema end end end # module Podcast
Now we can use this domain object by passing it into the
Repository
class's constructor. It will store a reference
to the class object and use it to create Podcast
objects
which it will pass to new DMS::File
objects. Each file
object carries with it its associated Sheepdip object that represents the
database table for the repository. That object is accessible via the
File.metadata
member. The following code illustrates the
whole process of using our new Podcast
class.
require 'mylib/podcast' db = JW::DBI::Database.new() if db.open(vars) == false raise "Failed to connect: #{db.error()}" end # Create DMS connection dms = JW::DMS::Repository.new(db, path, uuid, Podcast::Object) # Create a podcast file fileId = dms.createFile(name) # Open it and write some data to it. file = dms.openFile(fileId, 'w') file.write(fileData) # Now before we close it, set the custom attributes. The podcast sheepdip object # associated with the file is accessible via the metadata member. podcast = file.metadata podcast.title = 'Is this Your Heart?' podcast.description = 'Real Radio with Jack Hibbs' podcast.date = '2010-07-01' podcast.bitrate = 128 podcast.length = 26*60 # Now close the file. All the metadata will be written to the DB using the # podcast sheepdip object (e.g. to its associated podcast table in this case). file.close() # Example 2: Import a file and set metadata # first is path, second is name fileId = dms.importFile('run', 'run'); assert(fileId != nil) info = dms.fileInfo(fileId) assert info['name'] == 'run' # Get domain object for file from DMS (as opposed to file) podcast = dms.object(fileId) # Make changes podcast.title = 'Is this Your Heart?' podcast.description = 'Real Radio with Jack Hibbs' podcast.date = '2010-07-01' podcast.bitrate = 128 podcast.length = 26*60 # Since we don't have a file object open, use Sheepdip to save object. dip = JW::Sheepdip::App::instance() # Save metadata changes dip.save podcast