Class: Lafcadio::DomainObject
- Inherits:
-
Object
- Object
- Lafcadio::DomainObject
- Includes:
- DomainComparable
- Defined in:
- lib/lafcadio/domain/DomainObject.rb
Overview
pkId and committing
Lafcadio requires that each table has a numeric primary key. It assumes that this key is named pkId
in the database, though that can be overridden.
When you create a domain object by calling new, you should not assign a pkId
to the new instance. The pkId will automatically be set when you commit the object by calling DomainObject#commit.
However, you may want to manually set pkId
when setting up a test case, so you can ensure that a domain object has a given primary key.
Naming assumptions, and how to override them
By default, Lafcadio assumes that every domain object is indexed by the field pkId
in the database schema. If you’re dealing with a table that uses a different field name, override DomainObject.sqlPrimaryKeyName. However, you will always use pkId
in your Ruby code.
Lafcadio assumes that a domain class corresponds to a table whose name is the plural of the class name, and whose first letter is lowercase. A User class is assumed to be stored in a “users” table, while a ProductCategory class is assumed to be stored in a “productCategories” table. Override DomainObject.tableName to override this behavior.
Inheritance
Domain classes can inherit from other domain classes; they have all the fields of any concrete superclasses plus any new fields defined for themselves. You can use normal inheritance to define this:
class User < DomainObject
...
end
class Administrator < User
...
end
Lafcadio assumes that each concrete class has a corresponding table, and that each table has a pkId
field that is used to match rows between different levels.
Direct Known Subclasses
Constant Summary collapse
- COMMIT_ADD =
1
- COMMIT_EDIT =
2
- COMMIT_DELETE =
3
- @@subclassHash =
{}
- @@classFields =
{}
Instance Attribute Summary collapse
-
#delete ⇒ Object
Returns the value of attribute delete.
-
#errorMessages ⇒ Object
Returns the value of attribute errorMessages.
-
#fields ⇒ Object
writeonly
Sets the attribute fields.
-
#fields_set ⇒ Object
writeonly
Sets the attribute fields_set.
-
#lastCommit ⇒ Object
Returns the value of attribute lastCommit.
-
#pkId ⇒ Object
Returns the value of attribute pkId.
Class Method Summary collapse
-
.abstractSubclasses ⇒ Object
:nodoc:.
-
.allFields ⇒ Object
Returns an array of all fields defined for this class and all concrete superclasses.
-
.classFields ⇒ Object
:nodoc:.
-
.dependentClasses ⇒ Object
:nodoc:.
-
.getClassField(fieldName) ⇒ Object
:nodoc:.
-
.getClassFieldByDbFieldName(fieldName) ⇒ Object
:nodoc:.
-
.getDomainDirs ⇒ Object
:nodoc:.
-
.getField(fieldName) ⇒ Object
:nodoc:.
-
.getObjectTypeFromString(typeString) ⇒ Object
:nodoc:.
-
.inherited(subclass) ⇒ Object
:nodoc:.
-
.isBasedOn? ⇒ Boolean
:nodoc:.
-
.isConcrete? ⇒ Boolean
:nodoc:.
-
.method_missing(methodId) ⇒ Object
:nodoc:.
-
.objectType ⇒ Object
:nodoc:.
-
.selfAndConcreteSuperclasses ⇒ Object
:nodoc:.
-
.subclasses ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#clone ⇒ Object
Returns a clone, with all of the fields copied.
-
#commit ⇒ Object
Commits this domain object to the database.
-
#get_field(field) ⇒ Object
:nodoc:.
-
#get_getter_field(methId) ⇒ Object
:nodoc:.
-
#get_setter_field(methId) ⇒ Object
:nodoc:.
-
#initialize(fieldHash) ⇒ DomainObject
constructor
fieldHash should contain key-value associations for the different fields of this domain class.
-
#method_missing(methId, *args) ⇒ Object
:nodoc:.
-
#objectType ⇒ Object
Returns the subclass of DomainObject that this instance represents.
-
#postCommitTrigger ⇒ Object
This template method is called after every commit.
-
#preCommitTrigger ⇒ Object
This template method is called before every commit.
-
#set_field(field, value) ⇒ Object
:nodoc:.
-
#to_s ⇒ Object
By default, to_s is considered an invalid operation for domain objects, and will raise an error.
Methods included from DomainComparable
Constructor Details
#initialize(fieldHash) ⇒ DomainObject
fieldHash should contain key-value associations for the different fields of this domain class. For example, instantiating a User class might look like:
User.new( 'firstNames' => 'John', 'lastName' => 'Doe',
'email' => '[email protected]', 'password' => 'l33t' )
In normal usage any code you write that creates a domain object will not define the pkId
field. The system assumes that a domain object with an undefined pkId
has yet to be inserted into the database, and when you commit the domain object a pkId
will automatically be assigned.
If you’re creating mock objects for unit tests, you can explicitly set the pkId
to represent objects that already exist in the database.
271 272 273 274 275 276 277 278 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 271 def initialize(fieldHash) @fieldHash = fieldHash @pkId = fieldHash['pkId'] @pkId = @pkId.to_i unless @pkId.nil? @errorMessages = [] @fields = {} @fields_set = [] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(methId, *args) ⇒ Object
:nodoc:
280 281 282 283 284 285 286 287 288 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 280 def method_missing( methId, *args ) #:nodoc: if ( field = get_setter_field( methId ) ) set_field( field, args.first ) elsif ( field = get_getter_field( methId ) ) get_field( field ) else super( methId, *args ) end end |
Instance Attribute Details
#delete ⇒ Object
Returns the value of attribute delete.
254 255 256 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 254 def delete @delete end |
#errorMessages ⇒ Object
Returns the value of attribute errorMessages.
253 254 255 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 253 def errorMessages @errorMessages end |
#fields=(value) ⇒ Object
Sets the attribute fields
253 254 255 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 253 def fields=(value) @fields = value end |
#fields_set=(value) ⇒ Object
Sets the attribute fields_set
253 254 255 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 253 def fields_set=(value) @fields_set = value end |
#lastCommit ⇒ Object
Returns the value of attribute lastCommit.
253 254 255 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 253 def lastCommit @lastCommit end |
#pkId ⇒ Object
Returns the value of attribute pkId.
253 254 255 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 253 def pkId @pkId end |
Class Method Details
.abstractSubclasses ⇒ Object
:nodoc:
122 123 124 125 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 122 def DomainObject.abstractSubclasses #:nodoc: require 'lafcadio/domain' [ MapObject ] end |
.allFields ⇒ Object
Returns an array of all fields defined for this class and all concrete superclasses.
192 193 194 195 196 197 198 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 192 def DomainObject.allFields allFields = [] selfAndConcreteSuperclasses.each { |aClass| aClass.classFields.each { |field| allFields << field } } allFields end |
.classFields ⇒ Object
:nodoc:
113 114 115 116 117 118 119 120 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 113 def DomainObject.classFields #:nodoc: classFields = @@classFields[self] unless classFields @@classFields[self] = self.getClassFields classFields = @@classFields[self] end classFields end |
.dependentClasses ⇒ Object
:nodoc:
171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 171 def DomainObject.dependentClasses #:nodoc: dependentClasses = {} DomainObject.subclasses.each { |aClass| if aClass != DomainObjectProxy && (!DomainObject.abstractSubclasses.index(aClass)) aClass.classFields.each { |field| if field.class <= LinkField && field.linkedType == self.objectType dependentClasses[aClass] = field end } end } dependentClasses end |
.getClassField(fieldName) ⇒ Object
:nodoc:
143 144 145 146 147 148 149 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 143 def DomainObject.getClassField(fieldName) #:nodoc: field = nil self.classFields.each { |aField| field = aField if aField.name == fieldName } field end |
.getClassFieldByDbFieldName(fieldName) ⇒ Object
:nodoc:
151 152 153 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 151 def DomainObject.getClassFieldByDbFieldName( fieldName ) #:nodoc: self.classFields.find { |field| field.dbFieldName == fieldName } end |
.getDomainDirs ⇒ Object
:nodoc:
216 217 218 219 220 221 222 223 224 225 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 216 def self.getDomainDirs #:nodoc: config = LafcadioConfig.new classPath = config['classpath'] domainDirStr = config['domainDirs'] if domainDirStr domainDirs = domainDirStr.split(',') else domainDirs = [ classPath + 'domain/' ] end end |
.getField(fieldName) ⇒ Object
:nodoc:
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 155 def DomainObject.getField( fieldName ) #:nodoc: aDomainClass = self field = nil while aDomainClass < DomainObject && !field field = aDomainClass.getClassField( fieldName ) aDomainClass = aDomainClass.superclass end if field field else errStr = "Couldn't find field \"#{ field }\" in " + "#{ self } domain class" raise( MissingError, errStr, caller ) end end |
.getObjectTypeFromString(typeString) ⇒ Object
:nodoc:
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 227 def self.getObjectTypeFromString(typeString) #:nodoc: require 'lafcadio/objectStore/CouldntMatchObjectTypeError' objectType = nil typeString =~ /([^\:]*)$/ fileName = $1 getDomainDirs.each { |domainDir| if Dir.entries(domainDir).index("#{fileName}.rb") require "#{ domainDir }#{ fileName }" end } if (domainFilesStr = LafcadioConfig.new['domainFiles']) domainFilesStr.split(',').each { |domainFile| require domainFile } end subclasses.each { |subclass| objectType = subclass if subclass.to_s == typeString } if objectType objectType else raise CouldntMatchObjectTypeError, "couldn't match objectType #{typeString}", caller end end |
.inherited(subclass) ⇒ Object
:nodoc:
200 201 202 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 200 def DomainObject.inherited(subclass) #:nodoc: @@subclassHash[subclass] = true end |
.isBasedOn? ⇒ Boolean
:nodoc:
212 213 214 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 212 def DomainObject.isBasedOn? #:nodoc: self.superclass.isConcrete? end |
.isConcrete? ⇒ Boolean
:nodoc:
208 209 210 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 208 def DomainObject.isConcrete? #:nodoc: (self != DomainObject && abstractSubclasses.index(self).nil?) end |
.method_missing(methodId) ⇒ Object
:nodoc:
138 139 140 141 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 138 def DomainObject.method_missing(methodId) #:nodoc: require 'lafcadio/domain' ObjectType.getObjectType( self ).send( methodId.id2name ) end |
.objectType ⇒ Object
:nodoc:
186 187 188 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 186 def DomainObject.objectType #:nodoc: self end |
.selfAndConcreteSuperclasses ⇒ Object
:nodoc:
127 128 129 130 131 132 133 134 135 136 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 127 def DomainObject.selfAndConcreteSuperclasses # :nodoc: classes = [ ] anObjectType = self until(anObjectType == DomainObject || abstractSubclasses.index(anObjectType) != nil) classes << anObjectType anObjectType = anObjectType.superclass end classes end |
.subclasses ⇒ Object
:nodoc:
204 205 206 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 204 def DomainObject.subclasses #:nodoc: @@subclassHash.keys end |
Instance Method Details
#clone ⇒ Object
Returns a clone, with all of the fields copied.
362 363 364 365 366 367 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 362 def clone copy = super copy.fields = @fields.clone copy.fields_set = @fields_set.clone copy end |
#commit ⇒ Object
Commits this domain object to the database.
370 371 372 373 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 370 def commit require 'lafcadio/objectStore/ObjectStore' ObjectStore.getObjectStore.commit self end |
#get_field(field) ⇒ Object
:nodoc:
310 311 312 313 314 315 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 310 def get_field( field ) #:nodoc: unless @fields_set.include?( field ) set_field( field, @fieldHash[field.name] ) end @fields[field.name] end |
#get_getter_field(methId) ⇒ Object
:nodoc:
290 291 292 293 294 295 296 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 290 def get_getter_field( methId ) #:nodoc: begin self.class.getField( methId.id2name ) rescue MissingError nil end end |
#get_setter_field(methId) ⇒ Object
:nodoc:
298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 298 def get_setter_field( methId ) #:nodoc: if methId.id2name =~ /(.*)=$/ begin self.class.getField( $1 ) rescue MissingError nil end else nil end end |
#objectType ⇒ Object
Returns the subclass of DomainObject that this instance represents. Because of the way that proxying works, clients should call this method instead of Object.class.
330 331 332 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 330 def objectType self.class.objectType end |
#postCommitTrigger ⇒ Object
This template method is called after every commit. Subclasses can override it to ensure code is executed after a commit.
342 343 344 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 342 def postCommitTrigger nil end |
#preCommitTrigger ⇒ Object
This template method is called before every commit. Subclasses can override it to ensure code is executed before a commit.
336 337 338 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 336 def preCommitTrigger nil end |
#set_field(field, value) ⇒ Object
:nodoc:
317 318 319 320 321 322 323 324 325 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 317 def set_field( field, value ) #:nodoc: if field.class <= LinkField if value.class != DomainObjectProxy && value value = DomainObjectProxy.new(value) end end @fields[field.name] = value @fields_set << field end |
#to_s ⇒ Object
By default, to_s is considered an invalid operation for domain objects, and will raise an error. This behavior can be overridden by subclasses.
357 358 359 |
# File 'lib/lafcadio/domain/DomainObject.rb', line 357 def to_s raise "Don't make me into a string unless the type asks" end |