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.
- data/lib/lafcadio.rb +32 -0
- data/lib/lafcadio.rb~ +32 -0
- data/lib/lafcadio/TestSuite.rb +16 -0
- data/lib/lafcadio/dateTime.rb +2 -0
- data/lib/lafcadio/dateTime/Month.rb +93 -0
- data/lib/lafcadio/domain.rb +119 -0
- data/lib/lafcadio/domain.rb~ +119 -0
- data/lib/lafcadio/domain/DomainObject.rb +375 -0
- data/lib/lafcadio/domain/DomainObject.rb~ +371 -0
- data/lib/lafcadio/domain/MapObject.rb +22 -0
- data/lib/lafcadio/domain/ObjectType.rb +80 -0
- data/lib/lafcadio/includer.rb +18 -0
- data/lib/lafcadio/mock.rb +2 -0
- data/lib/lafcadio/mock/MockDbBridge.rb +78 -0
- data/lib/lafcadio/mock/MockDbBridge.rb~ +74 -0
- data/lib/lafcadio/mock/MockObjectStore.rb +20 -0
- data/lib/lafcadio/objectField.rb +14 -0
- data/lib/lafcadio/objectField/AutoIncrementField.rb +25 -0
- data/lib/lafcadio/objectField/BooleanField.rb +83 -0
- data/lib/lafcadio/objectField/DateField.rb +33 -0
- data/lib/lafcadio/objectField/DateTimeField.rb +25 -0
- data/lib/lafcadio/objectField/DecimalField.rb +41 -0
- data/lib/lafcadio/objectField/EmailField.rb +28 -0
- data/lib/lafcadio/objectField/EnumField.rb +62 -0
- data/lib/lafcadio/objectField/FieldValueError.rb +4 -0
- data/lib/lafcadio/objectField/IntegerField.rb +15 -0
- data/lib/lafcadio/objectField/LinkField.rb +92 -0
- data/lib/lafcadio/objectField/LinkField.rb~ +86 -0
- data/lib/lafcadio/objectField/MoneyField.rb +13 -0
- data/lib/lafcadio/objectField/MonthField.rb +16 -0
- data/lib/lafcadio/objectField/ObjectField.rb +142 -0
- data/lib/lafcadio/objectField/PasswordField.rb +29 -0
- data/lib/lafcadio/objectField/StateField.rb +13 -0
- data/lib/lafcadio/objectField/SubsetLinkField.rb +25 -0
- data/lib/lafcadio/objectField/TextField.rb +23 -0
- data/lib/lafcadio/objectField/TextListField.rb +21 -0
- data/lib/lafcadio/objectField/TimeStampField.rb +15 -0
- data/lib/lafcadio/objectStore.rb +100 -0
- data/lib/lafcadio/objectStore/Cache.rb +81 -0
- data/lib/lafcadio/objectStore/Committer.rb +65 -0
- data/lib/lafcadio/objectStore/CouldntMatchObjectTypeError.rb +4 -0
- data/lib/lafcadio/objectStore/DbBridge.rb +140 -0
- data/lib/lafcadio/objectStore/DbBridge.rb~ +140 -0
- data/lib/lafcadio/objectStore/DomainComparable.rb +25 -0
- data/lib/lafcadio/objectStore/DomainObjectInitError.rb +9 -0
- data/lib/lafcadio/objectStore/DomainObjectNotFoundError.rb +4 -0
- data/lib/lafcadio/objectStore/DomainObjectProxy.rb +62 -0
- data/lib/lafcadio/objectStore/DomainObjectSqlMaker.rb +74 -0
- data/lib/lafcadio/objectStore/ObjectStore.rb +207 -0
- data/lib/lafcadio/objectStore/ObjectStore.rb~ +207 -0
- data/lib/lafcadio/objectStore/SqlValueConverter.rb +30 -0
- data/lib/lafcadio/objectStore/SqlValueConverter.rb~ +30 -0
- data/lib/lafcadio/query.rb +203 -0
- data/lib/lafcadio/query/Compare.rb +55 -0
- data/lib/lafcadio/query/CompoundCondition.rb +39 -0
- data/lib/lafcadio/query/Condition.rb +66 -0
- data/lib/lafcadio/query/Condition.rb~ +66 -0
- data/lib/lafcadio/query/Equals.rb +45 -0
- data/lib/lafcadio/query/In.rb +20 -0
- data/lib/lafcadio/query/Like.rb +48 -0
- data/lib/lafcadio/query/Link.rb +20 -0
- data/lib/lafcadio/query/Max.rb +32 -0
- data/lib/lafcadio/query/Max.rb~ +25 -0
- data/lib/lafcadio/query/Not.rb +21 -0
- data/lib/lafcadio/query/Query.rb +92 -0
- data/lib/lafcadio/schema.rb +2 -0
- data/lib/lafcadio/schema/CreateTableStatement.rb +61 -0
- data/lib/lafcadio/schema/CreateTableStatement.rb~ +59 -0
- data/lib/lafcadio/test.rb +2 -0
- data/lib/lafcadio/test/LafcadioTestCase.rb +17 -0
- data/lib/lafcadio/test/testconfig.dat +13 -0
- data/lib/lafcadio/util.rb +180 -0
- data/lib/lafcadio/util/Context.rb +61 -0
- data/lib/lafcadio/util/ContextualService.rb +33 -0
- data/lib/lafcadio/util/English.rb +117 -0
- data/lib/lafcadio/util/HashOfArrays.rb +48 -0
- data/lib/lafcadio/util/LafcadioConfig.rb +25 -0
- data/lib/lafcadio/util/QueueHash.rb +67 -0
- data/lib/lafcadio/util/UsStates.rb +29 -0
- data/lib/lafcadio/xml.rb +2 -0
- 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,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
|