lafcadio 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. data/lib/lafcadio.rb +32 -0
  2. data/lib/lafcadio.rb~ +32 -0
  3. data/lib/lafcadio/TestSuite.rb +16 -0
  4. data/lib/lafcadio/dateTime.rb +2 -0
  5. data/lib/lafcadio/dateTime/Month.rb +93 -0
  6. data/lib/lafcadio/domain.rb +119 -0
  7. data/lib/lafcadio/domain.rb~ +119 -0
  8. data/lib/lafcadio/domain/DomainObject.rb +375 -0
  9. data/lib/lafcadio/domain/DomainObject.rb~ +371 -0
  10. data/lib/lafcadio/domain/MapObject.rb +22 -0
  11. data/lib/lafcadio/domain/ObjectType.rb +80 -0
  12. data/lib/lafcadio/includer.rb +18 -0
  13. data/lib/lafcadio/mock.rb +2 -0
  14. data/lib/lafcadio/mock/MockDbBridge.rb +78 -0
  15. data/lib/lafcadio/mock/MockDbBridge.rb~ +74 -0
  16. data/lib/lafcadio/mock/MockObjectStore.rb +20 -0
  17. data/lib/lafcadio/objectField.rb +14 -0
  18. data/lib/lafcadio/objectField/AutoIncrementField.rb +25 -0
  19. data/lib/lafcadio/objectField/BooleanField.rb +83 -0
  20. data/lib/lafcadio/objectField/DateField.rb +33 -0
  21. data/lib/lafcadio/objectField/DateTimeField.rb +25 -0
  22. data/lib/lafcadio/objectField/DecimalField.rb +41 -0
  23. data/lib/lafcadio/objectField/EmailField.rb +28 -0
  24. data/lib/lafcadio/objectField/EnumField.rb +62 -0
  25. data/lib/lafcadio/objectField/FieldValueError.rb +4 -0
  26. data/lib/lafcadio/objectField/IntegerField.rb +15 -0
  27. data/lib/lafcadio/objectField/LinkField.rb +92 -0
  28. data/lib/lafcadio/objectField/LinkField.rb~ +86 -0
  29. data/lib/lafcadio/objectField/MoneyField.rb +13 -0
  30. data/lib/lafcadio/objectField/MonthField.rb +16 -0
  31. data/lib/lafcadio/objectField/ObjectField.rb +142 -0
  32. data/lib/lafcadio/objectField/PasswordField.rb +29 -0
  33. data/lib/lafcadio/objectField/StateField.rb +13 -0
  34. data/lib/lafcadio/objectField/SubsetLinkField.rb +25 -0
  35. data/lib/lafcadio/objectField/TextField.rb +23 -0
  36. data/lib/lafcadio/objectField/TextListField.rb +21 -0
  37. data/lib/lafcadio/objectField/TimeStampField.rb +15 -0
  38. data/lib/lafcadio/objectStore.rb +100 -0
  39. data/lib/lafcadio/objectStore/Cache.rb +81 -0
  40. data/lib/lafcadio/objectStore/Committer.rb +65 -0
  41. data/lib/lafcadio/objectStore/CouldntMatchObjectTypeError.rb +4 -0
  42. data/lib/lafcadio/objectStore/DbBridge.rb +140 -0
  43. data/lib/lafcadio/objectStore/DbBridge.rb~ +140 -0
  44. data/lib/lafcadio/objectStore/DomainComparable.rb +25 -0
  45. data/lib/lafcadio/objectStore/DomainObjectInitError.rb +9 -0
  46. data/lib/lafcadio/objectStore/DomainObjectNotFoundError.rb +4 -0
  47. data/lib/lafcadio/objectStore/DomainObjectProxy.rb +62 -0
  48. data/lib/lafcadio/objectStore/DomainObjectSqlMaker.rb +74 -0
  49. data/lib/lafcadio/objectStore/ObjectStore.rb +207 -0
  50. data/lib/lafcadio/objectStore/ObjectStore.rb~ +207 -0
  51. data/lib/lafcadio/objectStore/SqlValueConverter.rb +30 -0
  52. data/lib/lafcadio/objectStore/SqlValueConverter.rb~ +30 -0
  53. data/lib/lafcadio/query.rb +203 -0
  54. data/lib/lafcadio/query/Compare.rb +55 -0
  55. data/lib/lafcadio/query/CompoundCondition.rb +39 -0
  56. data/lib/lafcadio/query/Condition.rb +66 -0
  57. data/lib/lafcadio/query/Condition.rb~ +66 -0
  58. data/lib/lafcadio/query/Equals.rb +45 -0
  59. data/lib/lafcadio/query/In.rb +20 -0
  60. data/lib/lafcadio/query/Like.rb +48 -0
  61. data/lib/lafcadio/query/Link.rb +20 -0
  62. data/lib/lafcadio/query/Max.rb +32 -0
  63. data/lib/lafcadio/query/Max.rb~ +25 -0
  64. data/lib/lafcadio/query/Not.rb +21 -0
  65. data/lib/lafcadio/query/Query.rb +92 -0
  66. data/lib/lafcadio/schema.rb +2 -0
  67. data/lib/lafcadio/schema/CreateTableStatement.rb +61 -0
  68. data/lib/lafcadio/schema/CreateTableStatement.rb~ +59 -0
  69. data/lib/lafcadio/test.rb +2 -0
  70. data/lib/lafcadio/test/LafcadioTestCase.rb +17 -0
  71. data/lib/lafcadio/test/testconfig.dat +13 -0
  72. data/lib/lafcadio/util.rb +180 -0
  73. data/lib/lafcadio/util/Context.rb +61 -0
  74. data/lib/lafcadio/util/ContextualService.rb +33 -0
  75. data/lib/lafcadio/util/English.rb +117 -0
  76. data/lib/lafcadio/util/HashOfArrays.rb +48 -0
  77. data/lib/lafcadio/util/LafcadioConfig.rb +25 -0
  78. data/lib/lafcadio/util/QueueHash.rb +67 -0
  79. data/lib/lafcadio/util/UsStates.rb +29 -0
  80. data/lib/lafcadio/xml.rb +2 -0
  81. metadata +135 -0
@@ -0,0 +1,140 @@
1
+ require 'rubygems'
2
+
3
+ require 'dbi'
4
+ require_gem 'log4r'
5
+ require 'lafcadio/util/LafcadioConfig'
6
+
7
+ module Lafcadio
8
+ class DbBridge #:nodoc:
9
+ @@dbh = nil
10
+ @@lastPkIdInserted = nil
11
+ @@dbName = nil
12
+ @@connectionClass = DBI
13
+
14
+ def DbBridge.setDbName(dbName)
15
+ @@dbName = dbName
16
+ end
17
+
18
+ def DbBridge._load(aString)
19
+ aString =~ /dbh:/
20
+ dbString = $'
21
+ begin
22
+ dbh = Marshal.load(dbString)
23
+ rescue TypeError
24
+ dbh = nil
25
+ end
26
+ new dbh
27
+ end
28
+
29
+ def DbBridge.flushConnection
30
+ @@dbh = nil
31
+ end
32
+
33
+ def DbBridge.setConnectionClass( aClass )
34
+ @@connectionClass = aClass
35
+ end
36
+
37
+ def DbBridge.disconnect
38
+ @@dbh.disconnect if @@dbh
39
+ end
40
+
41
+ def initialize(dbh = nil)
42
+ if dbh == nil
43
+ if @@dbh == nil
44
+ config = LafcadioConfig.new
45
+ dbName = @@dbName || config['dbname']
46
+ dbAndHost = nil
47
+ if dbName && config['dbhost']
48
+ dbAndHost = "dbi:Mysql:#{ dbName }:#{ config['dbhost'] }"
49
+ else
50
+ dbAndHost = "dbi:#{config['dbconn']}"
51
+ end
52
+ @@dbh = @@connectionClass.connect( dbAndHost, config['dbuser'],
53
+ config['dbpassword'] )
54
+ end
55
+ else
56
+ @@dbh = dbh
57
+ end
58
+ @dbh = @@dbh
59
+ ObjectSpace.define_finalizer( self, proc { |id| DbBridge.disconnect } )
60
+ end
61
+
62
+ def maybeLog(sql)
63
+ config = LafcadioConfig.new
64
+ if config['logSql'] == 'y'
65
+ sqllog = Log4r::Logger['sql'] || Log4r::Logger.new( 'sql' )
66
+ filename = File.join( config['logdir'], config['sqlLogFile'] || 'sql' )
67
+ outputter = Log4r::FileOutputter.new( 'outputter',
68
+ { :filename => filename } )
69
+ sqllog.outputters = outputter
70
+ sqllog.info sql
71
+ end
72
+ end
73
+
74
+ def commit(dbObject)
75
+ require 'lafcadio/objectStore/DomainObjectSqlMaker'
76
+ sqlMaker = DomainObjectSqlMaker.new(dbObject)
77
+ sqlMaker.sqlStatements.each { |sql, binds| executeCommit( sql, binds ) }
78
+ if sqlMaker.sqlStatements[0].first =~ /insert/
79
+ sql = 'select last_insert_id()'
80
+ result = executeSelect( sql )
81
+ @@lastPkIdInserted = result[0]['last_insert_id()'].to_i
82
+ end
83
+ end
84
+
85
+ def executeCommit( sql, binds )
86
+ @dbh.do( sql, *binds )
87
+ end
88
+
89
+ def getCollectionByQuery(query)
90
+ require 'lafcadio/objectStore/SqlValueConverter'
91
+ objectType = query.objectType
92
+ coll = []
93
+ objects = []
94
+ result = executeSelect query.toSql
95
+ result.each { |row_hash|
96
+ converter = SqlValueConverter.new(objectType, row_hash)
97
+ obj = objectType.new converter
98
+ objects << obj
99
+ }
100
+ coll = coll.concat objects
101
+ coll
102
+ end
103
+
104
+ def executeSelect(sql)
105
+ maybeLog sql
106
+ begin
107
+ @dbh.select_all( sql )
108
+ rescue DBI::DatabaseError => e
109
+ raise $!.to_s + ": #{ e.errstr }"
110
+ end
111
+ end
112
+
113
+ def _dump(aDepth)
114
+ if @db.respond_to? '_dump'
115
+ dbDump = @db._dump
116
+ else
117
+ dbDump = @db.class.to_s
118
+ end
119
+ "dbh:#{dbDump}"
120
+ end
121
+
122
+ def lastPkIdInserted
123
+ @@lastPkIdInserted
124
+ end
125
+
126
+ def group_query( query )
127
+ row = executeSelect( query.toSql )[0]
128
+ result = []
129
+ row.each { |val|
130
+ if query.field_name != 'pkId'
131
+ a_field = query.objectType.getField( query.field_name )
132
+ result << a_field.valueFromSQL( val )
133
+ else
134
+ result << val.to_i
135
+ end
136
+ }
137
+ result
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,25 @@
1
+ module Lafcadio
2
+ module DomainComparable
3
+ include Comparable
4
+
5
+ # A DomainObject or DomainObjectProxy is compared by +objectType+ and by
6
+ # +pkId+.
7
+ def <=>(anOther)
8
+ if anOther.respond_to?( 'objectType' )
9
+ if self.objectType == anOther.objectType
10
+ self.pkId <=> anOther.pkId
11
+ else
12
+ self.objectType.name <=> anOther.objectType.name
13
+ end
14
+ else
15
+ nil
16
+ end
17
+ end
18
+
19
+ def eql?(otherObj)
20
+ self == otherObj
21
+ end
22
+
23
+ def hash; "#{ self.class.name } #{ pkId }".hash; end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ module Lafcadio
2
+ class DomainObjectInitError < RuntimeError #:nodoc:
3
+ attr_reader :messages
4
+
5
+ def initialize(messages)
6
+ @messages = messages
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ module Lafcadio
2
+ class DomainObjectNotFoundError < RuntimeError #:nodoc:
3
+ end
4
+ end
@@ -0,0 +1,62 @@
1
+ require 'lafcadio/objectStore/DomainComparable'
2
+
3
+ module Lafcadio
4
+ # The DomainObjectProxy is used when retrieving domain objects that are
5
+ # linked to other domain objects with LinkFields. In terms of +objectType+ and
6
+ # +pkId+, a DomainObjectProxy instance looks to the outside world like the
7
+ # domain object it's supposed to represent. It only retrieves its domain
8
+ # object from the database when member data is requested.
9
+ #
10
+ # In normal usage you will probably never manipulate a DomainObjectProxy
11
+ # directly, but you may discover it by accident by calling
12
+ # DomainObjectProxy#class (or DomainObject#class) instead of
13
+ # DomainObjectProxy#objectType (or DomainObjectProxy#objectType).
14
+ class DomainObjectProxy
15
+ include DomainComparable
16
+
17
+ attr_accessor :objectType, :pkId
18
+
19
+ def initialize(objectTypeOrDbObject, pkId = nil)
20
+ if pkId
21
+ @objectType = objectTypeOrDbObject
22
+ @pkId = pkId
23
+ elsif objectTypeOrDbObject.class < DomainObject
24
+ @dbObject = objectTypeOrDbObject
25
+ @d_obj_retrieve_time = Time.now
26
+ @objectType = @dbObject.class
27
+ @pkId = @dbObject.pkId
28
+ else
29
+ raise ArgumentError
30
+ end
31
+ @dbObject = nil
32
+ end
33
+
34
+ def getDbObject
35
+ object_store = ObjectStore.getObjectStore
36
+ if @dbObject.nil? || needs_refresh?
37
+ @dbObject = object_store.get(@objectType, @pkId)
38
+ @d_obj_retrieve_time = Time.now
39
+
40
+ end
41
+ @dbObject
42
+ end
43
+
44
+ def method_missing(methodId, *args)
45
+ getDbObject.send(methodId.id2name, *args)
46
+ end
47
+
48
+ def needs_refresh?
49
+ object_store = ObjectStore.getObjectStore
50
+ last_commit_time = object_store.last_commit_time( @objectType, @pkId )
51
+ !last_commit_time.nil? && last_commit_time > @d_obj_retrieve_time
52
+ end
53
+
54
+ def to_s
55
+ getDbObject.to_s
56
+ end
57
+
58
+ def hash
59
+ getDbObject.hash
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,74 @@
1
+ require 'lafcadio/objectStore/DomainObjectInitError'
2
+
3
+ module Lafcadio
4
+ class DomainObjectSqlMaker #:nodoc:
5
+ attr_reader :bindValues
6
+
7
+ def initialize(obj); @obj = obj; end
8
+
9
+ def insertSQL(objectType)
10
+ fields = objectType.classFields
11
+ nameValuePairs = getNameValuePairs(objectType)
12
+ if objectType.isBasedOn?
13
+ nameValuePairs[objectType.sqlPrimaryKeyName] = 'LAST_INSERT_ID()'
14
+ end
15
+ fieldNameStr = nameValuePairs.keys.join ", "
16
+ fieldValueStr = nameValuePairs.values.join ", "
17
+ "insert into #{ objectType.tableName}(#{fieldNameStr}) " +
18
+ "values(#{fieldValueStr})"
19
+ end
20
+
21
+ def getNameValuePairs(objectType)
22
+ require 'lafcadio/util/QueueHash'
23
+ nameValues = []
24
+ objectType.classFields.each { |field|
25
+ value = @obj.send(field.name)
26
+ unless field.dbWillAutomaticallyWrite
27
+ nameValues << field.nameForSQL
28
+ nameValues <<(field.valueForSQL(value))
29
+ end
30
+ if field.bind_write?
31
+ @bindValues << value
32
+ end
33
+ }
34
+ QueueHash.new( *nameValues )
35
+ end
36
+
37
+ def updateSQL(objectType)
38
+ nameValueStrings = []
39
+ nameValuePairs = getNameValuePairs(objectType)
40
+ nameValuePairs.each { |key, value|
41
+ nameValueStrings << "#{key}=#{ value }"
42
+ }
43
+ allNameValues = nameValueStrings.join ', '
44
+ "update #{ objectType.tableName} set #{allNameValues} " +
45
+ "where #{ objectType.sqlPrimaryKeyName}=#{@obj.pkId}"
46
+ end
47
+
48
+ def deleteSql(objectType)
49
+ "delete from #{ objectType.tableName} " +
50
+ "where #{ objectType.sqlPrimaryKeyName }=#{ @obj.pkId }"
51
+ end
52
+
53
+ def sqlStatements
54
+ statements = []
55
+ if @obj.errorMessages.size > 0
56
+ raise DomainObjectInitError, @obj.errorMessages, caller
57
+ end
58
+ @obj.class.selfAndConcreteSuperclasses.each { |objectType|
59
+ @bindValues = []
60
+ if @obj.pkId == nil
61
+ statement = insertSQL(objectType)
62
+ else
63
+ if @obj.delete
64
+ statement = deleteSql(objectType)
65
+ else
66
+ statement = updateSQL(objectType)
67
+ end
68
+ end
69
+ statements << [statement, @bindValues]
70
+ }
71
+ statements.reverse
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,207 @@
1
+ require 'lafcadio'
2
+
3
+ module Lafcadio
4
+ # The ObjectStore represents the database in a Lafcadio application.
5
+ #
6
+ # = Configuring the ObjectStore
7
+ # The ObjectStore depends on a few values being set correctly in the
8
+ # LafcadioConfig file:
9
+ # [dbuser] The database username.
10
+ # [dbpassword] The database password.
11
+ # [dbname] The database name.
12
+ # [dbhost] The database host.
13
+ #
14
+ # = Instantiating ObjectStore
15
+ # The ObjectStore is a ContextualService, meaning you can't get an instance by
16
+ # calling ObjectStore.new. Instead, you should call
17
+ # ObjectStore.getObjectStore. (Using a ContextualService makes it easier to
18
+ # make out the ObjectStore for unit tests: See ContextualService for more.)
19
+ #
20
+ # = Dynamic method calls
21
+ # ObjectStore uses reflection to provide a lot of convenience methods for
22
+ # querying domain objects in a number of ways.
23
+ # [ObjectStore#get< domain class > (pkId)]
24
+ # Retrieves one domain object by pkId. For example,
25
+ # ObjectStore#getUser( 100 )
26
+ # will return User 100.
27
+ # [ObjectStore#get< domain class >s (searchTerm, fieldName = nil)]
28
+ # Returns a collection of all instances of that domain class matching that
29
+ # search term. For example,
30
+ # ObjectStore#getProducts( aProductCategory )
31
+ # queries MySQL for all products that belong to that product category. You
32
+ # can omit +fieldName+ if +searchTerm+ is a non-nil domain object, and the
33
+ # field connecting the first domain class to the second is named after the
34
+ # domain class. (For example, the above line assumes that Product has a
35
+ # field named "productCategory".) Otherwise, it's best to include
36
+ # +fieldName+:
37
+ # ObjectStore#getUsers( "Jones", "lastName" )
38
+ #
39
+ # = Querying
40
+ # ObjectStore can also be used to generate complex, ad-hoc queries which
41
+ # emulate much of the functionality you'd get from writing the SQL yourself.
42
+ # Furthermore, these queries can be run against in-memory data stores, which
43
+ # is particularly useful for tests.
44
+ # date = Date.new( 2003, 1, 1 )
45
+ # ObjectStore#getInvoices { |invoice|
46
+ # Query.And( invoice.date.gte( date ), invoice.rate.equals( 10 ),
47
+ # invoice.hours.equals( 10 ) )
48
+ # }
49
+ # is the same as
50
+ # select * from invoices
51
+ # where (date >= '2003-01-01' and rate = 10 and hours = 10)
52
+ # See lafcadio/query.rb for more.
53
+ #
54
+ # = SQL Logging
55
+ # Lafcadio uses log4r to log all of its SQL statements. The simplest way to
56
+ # turn on logging is to set the following values in the LafcadioConfig file:
57
+ # [logSql] Should be set to "y" to turn on logging.
58
+ # [logdir] The directory where log files should be written. Required if
59
+ # +logSql+ is "y"
60
+ # [sqlLogFile] The name of the file (not including its directory) where SQL
61
+ # should be logged. Default is "sql".
62
+ #
63
+ # = Triggers
64
+ # Domain classes can be set to fire triggers either before or after commits.
65
+ # Since these triggers are executed in Ruby, they're easy to test. See
66
+ # DomainObject#preCommitTrigger and DomainObject#postCommitTrigger for more.
67
+ class ObjectStore < ContextualService
68
+ def ObjectStore.setDbName(dbName) #:nodoc:
69
+ DbBridge.setDbName dbName
70
+ end
71
+
72
+ def initialize(context, dbBridge = nil) #:nodoc:
73
+ super context
74
+ @dbBridge = dbBridge == nil ? DbBridge.new : dbBridge
75
+ @cache = ObjectStore::Cache.new( @dbBridge )
76
+ end
77
+
78
+ # Commits a domain object to the database. You can also simply call
79
+ # myDomainObject.commit
80
+ def commit(dbObject)
81
+ require 'lafcadio/objectStore/Committer'
82
+ committer = Committer.new dbObject, @dbBridge
83
+ committer.execute
84
+ updateCacheAfterCommit( committer )
85
+ end
86
+
87
+ # Flushes one domain object from its cache.
88
+ def flush(dbObject)
89
+ @cache.flush dbObject
90
+ end
91
+
92
+ # Returns the domain object corresponding to the domain class and pkId.
93
+ def get(objectType, pkId)
94
+ query = Query.new objectType, pkId
95
+ @cache.getByQuery( query )[0] ||
96
+ ( raise( DomainObjectNotFoundError,
97
+ "Can't find #{objectType} #{pkId}", caller ) )
98
+ end
99
+
100
+ # Returns all domain objects for the given domain class.
101
+ def getAll(objectType)
102
+ query = Query.new( objectType )
103
+ @cache.getByQuery( query )
104
+ end
105
+
106
+ # Returns the DbBridge; this is useful in case you need to use raw SQL for a
107
+ # specific query.
108
+ def getDbBridge; @dbBridge; end
109
+
110
+ def getFiltered(objectTypeName, searchTerm, fieldName = nil) #:nodoc:
111
+ require 'lafcadio/query/Link'
112
+ objectType = DomainObject.getObjectTypeFromString objectTypeName
113
+ unless fieldName
114
+ fieldName = searchTerm.objectType.bareName
115
+ fieldName = fieldName.decapitalize
116
+ end
117
+ if searchTerm.class <= DomainObject
118
+ condition = Query::Link.new(fieldName, searchTerm, objectType)
119
+ else
120
+ condition = Query::Equals.new(fieldName, searchTerm, objectType)
121
+ end
122
+ getSubset( condition )
123
+ end
124
+
125
+ def getMapMatch(objectType, mapped) #:nodoc:
126
+ fieldName = mapped.objectType.bareName.decapitalize
127
+ Query::Equals.new(fieldName, mapped, objectType)
128
+ end
129
+
130
+ def getMapObject(objectType, map1, map2) #:nodoc:
131
+ require 'lafcadio/query/CompoundCondition'
132
+ unless map1 && map2
133
+ raise ArgumentError,
134
+ "ObjectStore#getMapObject needs two non-nil keys", caller
135
+ end
136
+ mapMatch1 = getMapMatch objectType, map1
137
+ mapMatch2 = getMapMatch objectType, map2
138
+ condition = Query::CompoundCondition.new mapMatch1, mapMatch2
139
+ getSubset(condition)[0]
140
+ end
141
+
142
+ def getMapped(searchTerm, resultTypeName) #:nodoc:
143
+ resultType = DomainObject.getObjectTypeFromString resultTypeName
144
+ coll = []
145
+ firstTypeName = searchTerm.class.bareName
146
+ secondTypeName = resultType.bareName
147
+ mapTypeName = firstTypeName + secondTypeName
148
+ getFiltered(mapTypeName, searchTerm).each { |mapObj|
149
+ coll << mapObj.send( resultType.name.decapitalize )
150
+ }
151
+ coll
152
+ end
153
+
154
+ # Retrieves the maximum value across all instances of one domain class.
155
+ # ObjectStore#getMax( Client )
156
+ # returns the highest +pkId+ in the +clients+ table.
157
+ # ObjectStore#getMax( Invoice, "rate" )
158
+ # will return the highest rate for all invoices.
159
+ def getMax( domain_class, field_name = nil )
160
+ query = Query::Max.new( domain_class, field_name )
161
+ @dbBridge.group_query( query ).only
162
+ end
163
+
164
+ # Retrieves a collection of domain objects by +pkId+.
165
+ # ObjectStore#getObjects( Clients, [ 1, 2, 3 ] )
166
+ def getObjects(objectType, pkIds)
167
+ require 'lafcadio/query/In'
168
+ condition = Query::In.new('pkId', pkIds, objectType)
169
+ getSubset condition
170
+ end
171
+
172
+ def getSubset(conditionOrQuery) #:nodoc:
173
+ if conditionOrQuery.class <= Query::Condition
174
+ condition = conditionOrQuery
175
+ query = Query.new condition.objectType, condition
176
+ else
177
+ query = conditionOrQuery
178
+ end
179
+ @cache.getByQuery( query )
180
+ end
181
+
182
+ def last_commit_time( domain_class, pkId ) #:nodoc:
183
+ @cache.last_commit_time( domain_class, pkId )
184
+ end
185
+
186
+ def method_missing(methodId, *args) #:nodoc:
187
+ proc = block_given? ? ( proc { |obj| yield( obj ) } ) : nil
188
+ dispatch = MethodDispatch.new( methodId, proc, *args )
189
+ self.send( dispatch.symbol, *dispatch.args )
190
+ end
191
+
192
+ # Caches one domain object.
193
+ def set(dbObject)
194
+ @cache.save dbObject
195
+ end
196
+
197
+ def updateCacheAfterCommit( committer ) #:nodoc:
198
+ if committer.commitType == Committer::UPDATE ||
199
+ committer.commitType == Committer::INSERT
200
+ set( committer.dbObject )
201
+ elsif committer.commitType == Committer::DELETE
202
+ @cache.flush( committer.dbObject )
203
+ end
204
+ @cache.set_commit_time( committer.dbObject )
205
+ end
206
+ end
207
+ end