lafcadio 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/lafcadio_schema +28 -26
- data/lib/lafcadio.rb +3 -3
- data/lib/lafcadio.rb~ +1 -1
- data/lib/lafcadio/domain.rb +29 -35
- data/lib/lafcadio/domain.rb~ +35 -42
- data/lib/lafcadio/mock.rb +37 -15
- data/lib/lafcadio/mock.rb~ +59 -36
- data/lib/lafcadio/objectField.rb +31 -20
- data/lib/lafcadio/objectField.rb~ +163 -142
- data/lib/lafcadio/objectStore.rb +125 -58
- data/lib/lafcadio/objectStore.rb~ +242 -177
- data/lib/lafcadio/query.rb +98 -95
- data/lib/lafcadio/query.rb~ +96 -95
- data/lib/lafcadio/schema.rb +4 -4
- data/lib/lafcadio/schema.rb~ +13 -17
- data/lib/lafcadio/test.rb +33 -7
- data/lib/lafcadio/test.rb~ +146 -20
- data/lib/lafcadio/util.rb +27 -11
- data/lib/lafcadio/util.rb~ +27 -43
- metadata +3 -7
- data/lib/lafcadio/dateTime.rb~ +0 -93
- data/lib/lafcadio/depend.rb~ +0 -8
- data/lib/lafcadio/objectStore.rb.~1.64.~ +0 -766
- data/lib/lafcadio/test/testconfig.dat~ +0 -13
data/lib/lafcadio/objectStore.rb
CHANGED
@@ -3,6 +3,7 @@ require 'lafcadio/depend'
|
|
3
3
|
require 'lafcadio/domain'
|
4
4
|
require 'lafcadio/query'
|
5
5
|
require 'lafcadio/util'
|
6
|
+
require 'monitor'
|
6
7
|
|
7
8
|
module Lafcadio
|
8
9
|
class DomainObjectInitError < RuntimeError #:nodoc:
|
@@ -42,11 +43,16 @@ module Lafcadio
|
|
42
43
|
|
43
44
|
def db_object #:nodoc:
|
44
45
|
if @db_object.nil? || needs_refresh?
|
45
|
-
|
46
|
-
|
46
|
+
dbo = ObjectStore.get_object_store.get( @domain_class, @pk_id )
|
47
|
+
self.db_object = dbo
|
47
48
|
end
|
48
49
|
@db_object
|
49
50
|
end
|
51
|
+
|
52
|
+
def db_object=( dbo )
|
53
|
+
@db_object = dbo
|
54
|
+
@d_obj_retrieve_time = Time.now
|
55
|
+
end
|
50
56
|
|
51
57
|
def hash #:nodoc:
|
52
58
|
db_object.hash
|
@@ -141,10 +147,8 @@ module Lafcadio
|
|
141
147
|
# DomainObject#pre_commit_trigger and DomainObject#post_commit_trigger for
|
142
148
|
# more.
|
143
149
|
class ObjectStore < ContextualService::Service
|
144
|
-
# Returns true if the current stored instance is a MockObjectStore.
|
145
|
-
def self.mock?; get_object_store.mock?; end
|
146
|
-
|
147
150
|
@@db_bridge = nil
|
151
|
+
@@db_type = 'Mysql'
|
148
152
|
|
149
153
|
# Returns the DbBridge; this is useful in case you need to use raw SQL for
|
150
154
|
# a specific query.
|
@@ -154,13 +158,20 @@ module Lafcadio
|
|
154
158
|
DbConnection.db_name= dbName
|
155
159
|
end
|
156
160
|
|
161
|
+
def self.db_type; @@db_type; end
|
162
|
+
|
163
|
+
def self.db_type=( dbt ); @@db_type = dbt; end
|
164
|
+
|
165
|
+
# Returns true if the current stored instance is a MockObjectStore.
|
166
|
+
def self.mock?; get_object_store.mock?; end
|
167
|
+
|
157
168
|
def initialize #:nodoc:
|
158
169
|
@cache = ObjectStore::Cache.new self.class.db_bridge
|
159
170
|
end
|
160
171
|
|
161
172
|
# Returns all domain objects for the given domain class.
|
162
|
-
def all(domain_class)
|
163
|
-
@cache.get_by_query( Query.new( domain_class ) )
|
173
|
+
def all( domain_class, opts = {} )
|
174
|
+
@cache.get_by_query( Query.new( domain_class, opts ) )
|
164
175
|
end
|
165
176
|
|
166
177
|
# Returns the DbBridge; this is useful in case you need to use raw SQL for
|
@@ -169,7 +180,8 @@ module Lafcadio
|
|
169
180
|
|
170
181
|
# Returns the domain object corresponding to the domain class and pk_id.
|
171
182
|
def get( domain_class, pk_id )
|
172
|
-
|
183
|
+
qry = Query.new( domain_class, :pk_id => pk_id )
|
184
|
+
@cache.get_by_query( qry ).first or (
|
173
185
|
raise(
|
174
186
|
DomainObjectNotFoundError, "Can't find #{domain_class} #{pk_id}",
|
175
187
|
caller
|
@@ -231,7 +243,7 @@ module Lafcadio
|
|
231
243
|
def query(conditionOrQuery)
|
232
244
|
if conditionOrQuery.class <= Query::Condition
|
233
245
|
condition = conditionOrQuery
|
234
|
-
query = Query.new condition.domain_class, condition
|
246
|
+
query = Query.new( condition.domain_class, :condition => condition )
|
235
247
|
else
|
236
248
|
query = conditionOrQuery
|
237
249
|
end
|
@@ -256,9 +268,12 @@ module Lafcadio
|
|
256
268
|
def transaction( &action ); @cache.transaction( action ); end
|
257
269
|
|
258
270
|
class Cache #:nodoc:
|
271
|
+
include MonitorMixin
|
272
|
+
|
259
273
|
attr_reader :db_bridge
|
260
274
|
|
261
275
|
def initialize( db_bridge = DbBridge.new )
|
276
|
+
super()
|
262
277
|
@db_bridge = db_bridge
|
263
278
|
@domain_class_caches = {}
|
264
279
|
end
|
@@ -268,8 +283,12 @@ module Lafcadio
|
|
268
283
|
db_object.last_commit_type = get_last_commit db_object
|
269
284
|
db_object.pre_commit_trigger
|
270
285
|
update_dependent_domain_objects( db_object ) if db_object.delete
|
271
|
-
|
272
|
-
|
286
|
+
synchronize do
|
287
|
+
@db_bridge.commit db_object
|
288
|
+
unless db_object.pk_id
|
289
|
+
db_object.pk_id = @db_bridge.last_pk_id_inserted
|
290
|
+
end
|
291
|
+
end
|
273
292
|
update_after_commit db_object
|
274
293
|
db_object.post_commit_trigger
|
275
294
|
db_object.reset_original_values_hash
|
@@ -285,20 +304,36 @@ module Lafcadio
|
|
285
304
|
@domain_class_caches[domain_class]
|
286
305
|
end
|
287
306
|
|
307
|
+
def get_by_query( query )
|
308
|
+
main_cache = cache query.domain_class
|
309
|
+
unless main_cache.queries[query]
|
310
|
+
if query.one_pk_id?
|
311
|
+
collected = false
|
312
|
+
else
|
313
|
+
collected = main_cache.collect_from_superset query
|
314
|
+
end
|
315
|
+
if !collected and main_cache.queries.values
|
316
|
+
newObjects = @db_bridge.select_dobjs query
|
317
|
+
newObjects.each { |dbObj| main_cache.save dbObj }
|
318
|
+
main_cache.queries[query] = newObjects.collect { |dobj| dobj.pk_id }
|
319
|
+
end
|
320
|
+
end
|
321
|
+
main_cache.queries[query].map { |pk_id| main_cache[pk_id] }.compact
|
322
|
+
end
|
323
|
+
|
288
324
|
def get_last_commit( db_object )
|
289
325
|
if db_object.delete
|
290
|
-
|
326
|
+
:delete
|
291
327
|
elsif db_object.pk_id
|
292
|
-
|
328
|
+
:update
|
293
329
|
else
|
294
|
-
|
330
|
+
:insert
|
295
331
|
end
|
296
332
|
end
|
297
333
|
|
298
334
|
def method_missing( meth, *args )
|
299
335
|
simple_dispatch = [
|
300
|
-
:
|
301
|
-
:update_after_commit
|
336
|
+
:queries, :save, :set_commit_time, :update_after_commit
|
302
337
|
]
|
303
338
|
if simple_dispatch.include?( meth )
|
304
339
|
cache( args.first.domain_class ).send( meth, *args )
|
@@ -379,29 +414,8 @@ module Lafcadio
|
|
379
414
|
end
|
380
415
|
end
|
381
416
|
|
382
|
-
def get_by_query( query )
|
383
|
-
unless queries[query]
|
384
|
-
collected = collect_from_superset query
|
385
|
-
if !collected and queries.values
|
386
|
-
query_db query
|
387
|
-
end
|
388
|
-
end
|
389
|
-
collection = []
|
390
|
-
queries[query].each { |pk_id|
|
391
|
-
dobj = self[ pk_id ]
|
392
|
-
collection << dobj if dobj
|
393
|
-
}
|
394
|
-
collection
|
395
|
-
end
|
396
|
-
|
397
417
|
def last_commit_time( pk_id ); commit_times[pk_id]; end
|
398
418
|
|
399
|
-
def query_db( query )
|
400
|
-
newObjects = @db_bridge.select_dobjs query
|
401
|
-
newObjects.each { |dbObj| save dbObj }
|
402
|
-
queries[query] = newObjects.collect { |dobj| dobj.pk_id }
|
403
|
-
end
|
404
|
-
|
405
419
|
# Saves a domain object.
|
406
420
|
def save(db_object)
|
407
421
|
self[db_object.pk_id] = db_object
|
@@ -411,11 +425,11 @@ module Lafcadio
|
|
411
425
|
def set_commit_time( d_obj ); commit_times[d_obj.pk_id] = Time.now; end
|
412
426
|
|
413
427
|
def update_after_commit( db_object ) #:nodoc:
|
414
|
-
if [
|
428
|
+
if [ :update, :insert ].include?(
|
415
429
|
db_object.last_commit_type
|
416
430
|
)
|
417
431
|
save db_object
|
418
|
-
elsif db_object.last_commit_type ==
|
432
|
+
elsif db_object.last_commit_type == :delete
|
419
433
|
flush db_object
|
420
434
|
end
|
421
435
|
set_commit_time db_object
|
@@ -430,7 +444,9 @@ module Lafcadio
|
|
430
444
|
@obj = obj
|
431
445
|
reversed = []
|
432
446
|
@obj.class.self_and_concrete_superclasses.each { |domain_class|
|
433
|
-
|
447
|
+
statement_bind_value_pairs( domain_class ).reverse.each do |pair|
|
448
|
+
reversed << pair
|
449
|
+
end
|
434
450
|
}
|
435
451
|
reversed.reverse.each do |statement, binds|
|
436
452
|
self << [ statement, binds ]
|
@@ -463,7 +479,8 @@ module Lafcadio
|
|
463
479
|
fields = domain_class.class_fields
|
464
480
|
nameValuePairs = get_name_value_pairs( domain_class )
|
465
481
|
if domain_class.is_child_domain_class?
|
466
|
-
|
482
|
+
pair = DbBridge.last_inserted_pk_id_pair domain_class.superclass
|
483
|
+
nameValuePairs[domain_class.sql_primary_key_name] = pair.first
|
467
484
|
end
|
468
485
|
fieldNameStr = nameValuePairs.keys.join ", "
|
469
486
|
fieldValueStr = nameValuePairs.values.join ", "
|
@@ -471,18 +488,24 @@ module Lafcadio
|
|
471
488
|
"values(#{fieldValueStr})"
|
472
489
|
end
|
473
490
|
|
474
|
-
def
|
491
|
+
def statement_bind_value_pairs( domain_class )
|
475
492
|
@bind_values = []
|
476
493
|
if @obj.pk_id == nil
|
477
494
|
statement = insert_sql( domain_class )
|
495
|
+
pairs = [ [statement, @bind_values] ]
|
496
|
+
if domain_class.is_child_domain_class? and ObjectStore.db_type == 'Pg'
|
497
|
+
setval_sql = "select setval( '#{ domain_class.postgres_pk_id_seq }', currval('#{ domain_class.superclass.postgres_pk_id_seq }') )"
|
498
|
+
pairs << [ setval_sql, @bind_values ]
|
499
|
+
end
|
500
|
+
pairs
|
478
501
|
else
|
479
502
|
if @obj.delete
|
480
503
|
statement = delete_sql( domain_class )
|
481
504
|
else
|
482
505
|
statement = update_sql( domain_class)
|
483
506
|
end
|
507
|
+
[ [statement, @bind_values] ]
|
484
508
|
end
|
485
|
-
[statement, @bind_values]
|
486
509
|
end
|
487
510
|
|
488
511
|
def update_sql( domain_class )
|
@@ -512,8 +535,18 @@ module Lafcadio
|
|
512
535
|
new
|
513
536
|
end
|
514
537
|
|
538
|
+
def self.last_inserted_pk_id_pair( domain_class )
|
539
|
+
case ObjectStore.db_type
|
540
|
+
when 'Mysql'
|
541
|
+
[ 'last_insert_id()', 'last_insert_id()' ]
|
542
|
+
when 'Pg'
|
543
|
+
[ "currval('#{ domain_class.postgres_pk_id_seq }')", 'currval' ]
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
515
547
|
def initialize
|
516
548
|
@db_conn = DbConnection.get_db_connection
|
549
|
+
@transaction = nil
|
517
550
|
ObjectSpace.define_finalizer( self, proc { |id|
|
518
551
|
DbConnection.get_db_connection.disconnect
|
519
552
|
} )
|
@@ -532,9 +565,24 @@ module Lafcadio
|
|
532
565
|
@db_conn.do( sql, *binds )
|
533
566
|
end
|
534
567
|
if statements_and_binds[0].first =~ /insert/
|
535
|
-
|
536
|
-
|
537
|
-
|
568
|
+
@@last_pk_id_inserted = get_last_pk_id_inserted(
|
569
|
+
db_object.domain_class
|
570
|
+
)
|
571
|
+
end
|
572
|
+
@db_conn.do( 'commit' ) unless @transaction
|
573
|
+
end
|
574
|
+
|
575
|
+
def get_last_pk_id_inserted( domain_class )
|
576
|
+
pair = self.class.last_inserted_pk_id_pair( domain_class )
|
577
|
+
sql = 'select ' + pair.first
|
578
|
+
begin
|
579
|
+
select_all( sql ).first[pair.last].to_i
|
580
|
+
rescue RuntimeError
|
581
|
+
error_msg =
|
582
|
+
"The field \"" + domain_class.sql_primary_key_name +
|
583
|
+
"\" can\'t be found in the table \"" +
|
584
|
+
domain_class.table_name + "\"."
|
585
|
+
raise FieldMatchError, error_msg, caller
|
538
586
|
end
|
539
587
|
end
|
540
588
|
|
@@ -570,24 +618,39 @@ module Lafcadio
|
|
570
618
|
|
571
619
|
def select_dobjs(query)
|
572
620
|
domain_class = query.domain_class
|
573
|
-
select_all( query.to_sql ).collect { |row_hash|
|
574
|
-
domain_class.new(
|
621
|
+
select_all( query.to_sql( ObjectStore.db_type ) ).collect { |row_hash|
|
622
|
+
dobj = domain_class.new(
|
623
|
+
SqlToRubyValues.new( domain_class, row_hash )
|
624
|
+
)
|
625
|
+
if query.include
|
626
|
+
query.include.each do |include_sym|
|
627
|
+
field = domain_class.field include_sym
|
628
|
+
included_dclass = field.linked_type
|
629
|
+
if dobj.send( field.name )
|
630
|
+
dobj.send( field.name ).db_object = included_dclass.new(
|
631
|
+
SqlToRubyValues.new( included_dclass, row_hash )
|
632
|
+
)
|
633
|
+
end
|
634
|
+
end
|
635
|
+
end
|
636
|
+
dobj
|
575
637
|
}
|
576
638
|
end
|
577
639
|
|
578
640
|
def transaction( action )
|
579
|
-
|
580
|
-
|
641
|
+
@transaction = Transaction.new @db_conn
|
642
|
+
@transaction.commit
|
581
643
|
begin
|
582
|
-
action.call
|
583
|
-
|
644
|
+
action.call @transaction
|
645
|
+
@transaction.commit
|
584
646
|
rescue RollbackError
|
585
647
|
# rollback handled by Transaction
|
586
648
|
rescue
|
587
649
|
err_to_raise = $!
|
588
|
-
|
650
|
+
@transaction.rollback false
|
589
651
|
raise err_to_raise
|
590
652
|
end
|
653
|
+
@transaction = nil
|
591
654
|
end
|
592
655
|
|
593
656
|
class Transaction #:nodoc:
|
@@ -617,17 +680,21 @@ module Lafcadio
|
|
617
680
|
|
618
681
|
def disconnect; @dbh.disconnect; end
|
619
682
|
|
620
|
-
def
|
683
|
+
def driver_url
|
621
684
|
config = LafcadioConfig.new
|
622
685
|
dbName = @@db_name || config['dbname']
|
623
|
-
|
686
|
+
driver_name = config['dbtype'] || 'Mysql'
|
624
687
|
if dbName && config['dbhost']
|
625
|
-
|
688
|
+
"dbi:#{ driver_name }:#{ dbName }:#{ config['dbhost'] }"
|
626
689
|
else
|
627
|
-
|
690
|
+
"dbi:#{config['dbconn']}"
|
628
691
|
end
|
692
|
+
end
|
693
|
+
|
694
|
+
def load_new_dbh
|
695
|
+
config = LafcadioConfig.new
|
629
696
|
dbh = @@conn_class.connect(
|
630
|
-
|
697
|
+
driver_url, config['dbuser'], config['dbpassword']
|
631
698
|
)
|
632
699
|
dbh['AutoCommit'] = false
|
633
700
|
dbh
|
@@ -3,6 +3,7 @@ require 'lafcadio/depend'
|
|
3
3
|
require 'lafcadio/domain'
|
4
4
|
require 'lafcadio/query'
|
5
5
|
require 'lafcadio/util'
|
6
|
+
require 'monitor'
|
6
7
|
|
7
8
|
module Lafcadio
|
8
9
|
class DomainObjectInitError < RuntimeError #:nodoc:
|
@@ -12,11 +13,11 @@ module Lafcadio
|
|
12
13
|
end
|
13
14
|
|
14
15
|
# The DomainObjectProxy is used when retrieving domain objects that are
|
15
|
-
# linked to other domain objects with DomainObjectFields. In terms of
|
16
|
-
# and
|
17
|
-
#
|
18
|
-
# domain object
|
19
|
-
#
|
16
|
+
# linked to other domain objects with DomainObjectFields. In terms of
|
17
|
+
# +domain_class+ and +pk_id+, a DomainObjectProxy instance looks to the
|
18
|
+
# outside world like the domain object it's supposed to represent. It only
|
19
|
+
# retrieves its domain object from the database when member data is
|
20
|
+
# requested.
|
20
21
|
#
|
21
22
|
# In normal usage you will probably never manipulate a DomainObjectProxy
|
22
23
|
# directly, but you may discover it by accident by calling
|
@@ -27,7 +28,7 @@ module Lafcadio
|
|
27
28
|
|
28
29
|
attr_accessor :domain_class, :pk_id
|
29
30
|
|
30
|
-
def initialize( *args )
|
31
|
+
def initialize( *args ) #:nodoc:
|
31
32
|
if args.size == 2
|
32
33
|
@domain_class = args.first
|
33
34
|
@pk_id = args.last
|
@@ -40,29 +41,34 @@ module Lafcadio
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
43
|
-
def db_object
|
44
|
+
def db_object #:nodoc:
|
44
45
|
if @db_object.nil? || needs_refresh?
|
45
|
-
|
46
|
-
|
46
|
+
dbo = ObjectStore.get_object_store.get( @domain_class, @pk_id )
|
47
|
+
self.db_object = dbo
|
47
48
|
end
|
48
49
|
@db_object
|
49
50
|
end
|
51
|
+
|
52
|
+
def db_object=( dbo )
|
53
|
+
@db_object = dbo
|
54
|
+
@d_obj_retrieve_time = Time.now
|
55
|
+
end
|
50
56
|
|
51
|
-
def hash
|
57
|
+
def hash #:nodoc:
|
52
58
|
db_object.hash
|
53
59
|
end
|
54
60
|
|
55
|
-
def method_missing( methodId, *args )
|
61
|
+
def method_missing( methodId, *args ) #:nodoc:
|
56
62
|
db_object.send( methodId, *args )
|
57
63
|
end
|
58
64
|
|
59
|
-
def needs_refresh?
|
65
|
+
def needs_refresh? #:nodoc:
|
60
66
|
object_store = ObjectStore.get_object_store
|
61
67
|
last_commit_time = object_store.last_commit_time( @domain_class, @pk_id )
|
62
68
|
last_commit_time && last_commit_time > @d_obj_retrieve_time
|
63
69
|
end
|
64
70
|
|
65
|
-
def to_s
|
71
|
+
def to_s #:nodoc:
|
66
72
|
db_object.to_s
|
67
73
|
end
|
68
74
|
end
|
@@ -80,29 +86,31 @@ module Lafcadio
|
|
80
86
|
# [dbhost] The database host.
|
81
87
|
#
|
82
88
|
# = Instantiating ObjectStore
|
83
|
-
#
|
84
|
-
#
|
85
|
-
# ObjectStore.get_object_store. (Using a ContextualService makes it easier to
|
86
|
-
# make out the ObjectStore for unit tests: See ContextualService for more.)
|
89
|
+
# You can't get an instance of ObjectStore by calling ObjectStore.new.
|
90
|
+
# Instead, you should call ObjectStore.get_object_store.
|
87
91
|
#
|
88
92
|
# = Dynamic method calls
|
89
93
|
# ObjectStore uses reflection to provide a lot of convenience methods for
|
90
94
|
# querying domain objects in a number of ways.
|
91
|
-
# [ObjectStore
|
95
|
+
# [ObjectStore#< domain class >( pk_id )]
|
92
96
|
# Retrieves one domain object by pk_id. For example,
|
93
|
-
# ObjectStore#
|
94
|
-
# will return User 100.
|
95
|
-
#
|
97
|
+
# ObjectStore#user( 100 )
|
98
|
+
# will return User 100. Note that you can also just user DomainObject.[]:
|
99
|
+
# User[100]
|
100
|
+
# [ObjectStore#< plural of domain class >( searchTerm, fieldName = nil )]
|
96
101
|
# Returns a collection of all instances of that domain class matching that
|
97
102
|
# search term. For example,
|
98
|
-
# ObjectStore#
|
103
|
+
# ObjectStore#products( a_product_category )
|
99
104
|
# queries MySQL for all products that belong to that product category. You
|
100
105
|
# can omit +fieldName+ if +searchTerm+ is a non-nil domain object, and the
|
101
106
|
# field connecting the first domain class to the second is named after the
|
102
107
|
# domain class. (For example, the above line assumes that Product has a
|
103
|
-
# field named "
|
108
|
+
# field named "product_category".) Otherwise, it's best to include
|
104
109
|
# +fieldName+:
|
105
|
-
# ObjectStore#
|
110
|
+
# ObjectStore#users( "Jones", "lastName" )
|
111
|
+
# Note that these can also be accessed through DomainObject.get:
|
112
|
+
# Product.get( a_product_category )
|
113
|
+
# User.get( "Jones", "lastName" )
|
106
114
|
#
|
107
115
|
# = Querying
|
108
116
|
# ObjectStore can also be used to generate complex, ad-hoc queries which
|
@@ -110,14 +118,19 @@ module Lafcadio
|
|
110
118
|
# Furthermore, these queries can be run against in-memory data stores, which
|
111
119
|
# is particularly useful for tests.
|
112
120
|
# date = Date.new( 2003, 1, 1 )
|
113
|
-
# ObjectStore#
|
114
|
-
#
|
115
|
-
# invoice.hours.equals( 10 )
|
121
|
+
# ObjectStore#invoices { |invoice|
|
122
|
+
# invoice.date.gte( date ) & invoice.rate.equals( 10 ) &
|
123
|
+
# invoice.hours.equals( 10 )
|
116
124
|
# }
|
117
125
|
# is the same as
|
118
126
|
# select * from invoices
|
119
127
|
# where (date >= '2003-01-01' and rate = 10 and hours = 10)
|
120
|
-
#
|
128
|
+
# Note that you can also use DomainObject.get:
|
129
|
+
# Invoice.get { |invoice|
|
130
|
+
# invoice.date.gte( date ) & invoice.rate.equals( 10 ) &
|
131
|
+
# invoice.hours.equals( 10 )
|
132
|
+
# }
|
133
|
+
# See lafcadio/query.rb for more on the query inference syntax.
|
121
134
|
#
|
122
135
|
# = SQL Logging
|
123
136
|
# Lafcadio uses log4r to log all of its SQL statements. The simplest way to
|
@@ -131,25 +144,44 @@ module Lafcadio
|
|
131
144
|
# = Triggers
|
132
145
|
# Domain classes can be set to fire triggers either before or after commits.
|
133
146
|
# Since these triggers are executed in Ruby, they're easy to test. See
|
134
|
-
# DomainObject#pre_commit_trigger and DomainObject#post_commit_trigger for
|
147
|
+
# DomainObject#pre_commit_trigger and DomainObject#post_commit_trigger for
|
148
|
+
# more.
|
135
149
|
class ObjectStore < ContextualService::Service
|
136
|
-
def self.mock?; get_object_store.mock?; end
|
137
|
-
|
138
150
|
@@db_bridge = nil
|
139
|
-
|
151
|
+
@@db_type = 'Mysql'
|
152
|
+
|
153
|
+
# Returns the DbBridge; this is useful in case you need to use raw SQL for
|
154
|
+
# a specific query.
|
140
155
|
def self.db_bridge; @@db_bridge ||= DbBridge.new; end
|
141
156
|
|
142
|
-
def self.db_name= (dbName)
|
157
|
+
def self.db_name= (dbName)
|
143
158
|
DbConnection.db_name= dbName
|
144
159
|
end
|
145
160
|
|
161
|
+
def self.db_type; @@db_type; end
|
162
|
+
|
163
|
+
def self.db_type=( dbt ); @@db_type = dbt; end
|
164
|
+
|
165
|
+
# Returns true if the current stored instance is a MockObjectStore.
|
166
|
+
def self.mock?; get_object_store.mock?; end
|
167
|
+
|
146
168
|
def initialize #:nodoc:
|
147
169
|
@cache = ObjectStore::Cache.new self.class.db_bridge
|
148
170
|
end
|
149
171
|
|
172
|
+
# Returns all domain objects for the given domain class.
|
173
|
+
def all( domain_class, opts = {} )
|
174
|
+
@cache.get_by_query( Query.new( domain_class, opts ) )
|
175
|
+
end
|
176
|
+
|
177
|
+
# Returns the DbBridge; this is useful in case you need to use raw SQL for
|
178
|
+
# a specific query.
|
179
|
+
def db_bridge; @cache.db_bridge; end
|
180
|
+
|
150
181
|
# Returns the domain object corresponding to the domain class and pk_id.
|
151
182
|
def get( domain_class, pk_id )
|
152
|
-
|
183
|
+
qry = Query.new( domain_class, :pk_id => pk_id )
|
184
|
+
@cache.get_by_query( qry ).first or (
|
153
185
|
raise(
|
154
186
|
DomainObjectNotFoundError, "Can't find #{domain_class} #{pk_id}",
|
155
187
|
caller
|
@@ -157,23 +189,6 @@ module Lafcadio
|
|
157
189
|
)
|
158
190
|
end
|
159
191
|
|
160
|
-
# Returns all domain objects for the given domain class.
|
161
|
-
def get_all(domain_class)
|
162
|
-
@cache.get_by_query( Query.new( domain_class ) )
|
163
|
-
end
|
164
|
-
|
165
|
-
# Returns the DbBridge; this is useful in case you need to use raw SQL for a
|
166
|
-
# specific query.
|
167
|
-
def get_db_bridge; @cache.db_bridge; end
|
168
|
-
|
169
|
-
def get_filtered(domain_class_name, searchTerm, fieldName = nil) #:nodoc:
|
170
|
-
domain_class = Class.by_name domain_class_name
|
171
|
-
unless fieldName
|
172
|
-
fieldName = domain_class.link_field( searchTerm.domain_class ).name
|
173
|
-
end
|
174
|
-
get_subset( Query::Equals.new( fieldName, searchTerm, domain_class ) )
|
175
|
-
end
|
176
|
-
|
177
192
|
def get_map_object( domain_class, map1, map2 ) #:nodoc:
|
178
193
|
unless map1 && map2
|
179
194
|
raise ArgumentError,
|
@@ -187,44 +202,23 @@ module Lafcadio
|
|
187
202
|
map2.domain_class.basename.camel_case_to_underscore
|
188
203
|
).equals( map2 )
|
189
204
|
}
|
190
|
-
|
205
|
+
query( query ).first
|
206
|
+
end
|
207
|
+
|
208
|
+
def group_query( query ) #:nodoc:
|
209
|
+
@cache.group_query( query )
|
191
210
|
end
|
192
211
|
|
193
212
|
# Retrieves the maximum value across all instances of one domain class.
|
194
|
-
# ObjectStore#
|
213
|
+
# ObjectStore#max( Client )
|
195
214
|
# returns the highest +pk_id+ in the +clients+ table.
|
196
|
-
# ObjectStore#
|
215
|
+
# ObjectStore#max( Invoice, "rate" )
|
197
216
|
# will return the highest rate for all invoices.
|
198
|
-
def
|
217
|
+
def max( domain_class, field_name = 'pk_id' )
|
199
218
|
qry = Query::Max.new( domain_class, field_name )
|
200
219
|
@cache.group_query( qry ).only[:max]
|
201
220
|
end
|
202
221
|
|
203
|
-
# Retrieves a collection of domain objects by +pk_id+.
|
204
|
-
# ObjectStore#get_objects( Clients, [ 1, 2, 3 ] )
|
205
|
-
def get_objects( domain_class, pk_ids )
|
206
|
-
if pk_ids.is_a?( Array ) && pk_ids.all? { |elt| elt.is_a?( Integer ) }
|
207
|
-
get_subset Query::In.new( 'pk_id', pk_ids, domain_class )
|
208
|
-
else
|
209
|
-
raise(
|
210
|
-
ArgumentError,
|
211
|
-
"ObjectStore#get_objects( domain_class, pk_ids ): pk_ids needs to " +
|
212
|
-
"be an array of integers",
|
213
|
-
caller
|
214
|
-
)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
def get_subset(conditionOrQuery) #:nodoc:
|
219
|
-
if conditionOrQuery.class <= Query::Condition
|
220
|
-
condition = conditionOrQuery
|
221
|
-
query = Query.new condition.domain_class, condition
|
222
|
-
else
|
223
|
-
query = conditionOrQuery
|
224
|
-
end
|
225
|
-
@cache.get_by_query( query )
|
226
|
-
end
|
227
|
-
|
228
222
|
def method_missing(methodId, *args) #:nodoc:
|
229
223
|
if [ :commit, :flush, :last_commit_time ].include?( methodId )
|
230
224
|
@cache.send( methodId, *args )
|
@@ -232,7 +226,7 @@ module Lafcadio
|
|
232
226
|
proc = block_given? ? ( proc { |obj| yield( obj ) } ) : nil
|
233
227
|
dispatch = MethodDispatch.new( methodId, proc, *args )
|
234
228
|
if dispatch.symbol
|
235
|
-
|
229
|
+
dispatch.dispatch self
|
236
230
|
else
|
237
231
|
super
|
238
232
|
end
|
@@ -243,9 +237,20 @@ module Lafcadio
|
|
243
237
|
false
|
244
238
|
end
|
245
239
|
|
246
|
-
|
247
|
-
|
248
|
-
|
240
|
+
# Passes a query and selects with it.
|
241
|
+
# qry = Query.infer( User ) { |user| user.fname.equals( 'Francis' ) }
|
242
|
+
# francises = ObjectStore.get_object_store.query( qry )
|
243
|
+
def query(conditionOrQuery)
|
244
|
+
if conditionOrQuery.class <= Query::Condition
|
245
|
+
condition = conditionOrQuery
|
246
|
+
query = Query.new( condition.domain_class, :condition => condition )
|
247
|
+
else
|
248
|
+
query = conditionOrQuery
|
249
|
+
end
|
250
|
+
@cache.get_by_query( query )
|
251
|
+
end
|
252
|
+
|
253
|
+
def respond_to?( symbol, include_private = false ) #:nodoc:
|
249
254
|
if MethodDispatch.new( symbol ).symbol
|
250
255
|
true
|
251
256
|
else
|
@@ -253,12 +258,22 @@ module Lafcadio
|
|
253
258
|
end
|
254
259
|
end
|
255
260
|
|
261
|
+
# As long as the underlying database table sorts transactions, you can use
|
262
|
+
# this to run transactional logic. These transactions will auto commit at
|
263
|
+
# the end of the block, and can be rolled back.
|
264
|
+
# ObjectStore.get_object_store.transaction do |tr|
|
265
|
+
# Client.new( 'name' => 'Big Co.' ).commit
|
266
|
+
# tr.rollback
|
267
|
+
# end # the client will not be saved to the DB
|
256
268
|
def transaction( &action ); @cache.transaction( action ); end
|
257
269
|
|
258
270
|
class Cache #:nodoc:
|
271
|
+
include MonitorMixin
|
272
|
+
|
259
273
|
attr_reader :db_bridge
|
260
274
|
|
261
275
|
def initialize( db_bridge = DbBridge.new )
|
276
|
+
super()
|
262
277
|
@db_bridge = db_bridge
|
263
278
|
@domain_class_caches = {}
|
264
279
|
end
|
@@ -268,10 +283,15 @@ module Lafcadio
|
|
268
283
|
db_object.last_commit_type = get_last_commit db_object
|
269
284
|
db_object.pre_commit_trigger
|
270
285
|
update_dependent_domain_objects( db_object ) if db_object.delete
|
271
|
-
|
272
|
-
|
286
|
+
synchronize do
|
287
|
+
@db_bridge.commit db_object
|
288
|
+
unless db_object.pk_id
|
289
|
+
db_object.pk_id = @db_bridge.last_pk_id_inserted
|
290
|
+
end
|
291
|
+
end
|
273
292
|
update_after_commit db_object
|
274
293
|
db_object.post_commit_trigger
|
294
|
+
db_object.reset_original_values_hash
|
275
295
|
db_object
|
276
296
|
end
|
277
297
|
|
@@ -284,20 +304,36 @@ module Lafcadio
|
|
284
304
|
@domain_class_caches[domain_class]
|
285
305
|
end
|
286
306
|
|
307
|
+
def get_by_query( query )
|
308
|
+
main_cache = cache query.domain_class
|
309
|
+
unless main_cache.queries[query]
|
310
|
+
if query.one_pk_id?
|
311
|
+
collected = false
|
312
|
+
else
|
313
|
+
collected = main_cache.collect_from_superset query
|
314
|
+
end
|
315
|
+
if !collected and main_cache.queries.values
|
316
|
+
newObjects = @db_bridge.select_dobjs query
|
317
|
+
newObjects.each { |dbObj| main_cache.save dbObj }
|
318
|
+
main_cache.queries[query] = newObjects.collect { |dobj| dobj.pk_id }
|
319
|
+
end
|
320
|
+
end
|
321
|
+
main_cache.queries[query].map { |pk_id| main_cache[pk_id] }.compact
|
322
|
+
end
|
323
|
+
|
287
324
|
def get_last_commit( db_object )
|
288
325
|
if db_object.delete
|
289
|
-
|
326
|
+
:delete
|
290
327
|
elsif db_object.pk_id
|
291
|
-
|
328
|
+
:update
|
292
329
|
else
|
293
|
-
|
330
|
+
:insert
|
294
331
|
end
|
295
332
|
end
|
296
333
|
|
297
334
|
def method_missing( meth, *args )
|
298
335
|
simple_dispatch = [
|
299
|
-
:
|
300
|
-
:update_after_commit
|
336
|
+
:queries, :save, :set_commit_time, :update_after_commit
|
301
337
|
]
|
302
338
|
if simple_dispatch.include?( meth )
|
303
339
|
cache( args.first.domain_class ).send( meth, *args )
|
@@ -310,9 +346,7 @@ module Lafcadio
|
|
310
346
|
|
311
347
|
def update_dependent_domain_class( db_object, aClass, field )
|
312
348
|
object_store = ObjectStore.get_object_store
|
313
|
-
collection =
|
314
|
-
aClass.name, db_object, field.name
|
315
|
-
)
|
349
|
+
collection = aClass.get( db_object, field.name )
|
316
350
|
collection.each { |dependentObject|
|
317
351
|
if field.delete_cascade
|
318
352
|
dependentObject.delete = true
|
@@ -332,7 +366,7 @@ module Lafcadio
|
|
332
366
|
}
|
333
367
|
end
|
334
368
|
|
335
|
-
class DomainClassCache < Hash
|
369
|
+
class DomainClassCache < Hash #:nodoc:
|
336
370
|
attr_reader :commit_times, :domain_class, :queries
|
337
371
|
|
338
372
|
def initialize( domain_class, db_bridge )
|
@@ -349,11 +383,11 @@ module Lafcadio
|
|
349
383
|
|
350
384
|
def collect_from_superset( query )
|
351
385
|
if ( pk_ids = find_superset_pk_ids( query ) )
|
352
|
-
|
386
|
+
db_objects = ( pk_ids.collect { |pk_id|
|
353
387
|
self[ pk_id ]
|
354
|
-
} ).select { |dobj| query.
|
355
|
-
|
356
|
-
}
|
388
|
+
} ).select { |dobj| query.dobj_satisfies?( dobj ) }
|
389
|
+
db_objects = query.order_and_limit_collection db_objects
|
390
|
+
queries[query] = db_objects.collect { |dobj| dobj.pk_id }
|
357
391
|
true
|
358
392
|
else
|
359
393
|
false
|
@@ -380,29 +414,8 @@ module Lafcadio
|
|
380
414
|
end
|
381
415
|
end
|
382
416
|
|
383
|
-
def get_by_query( query )
|
384
|
-
unless queries[query]
|
385
|
-
collected = collect_from_superset query
|
386
|
-
if !collected and queries.values
|
387
|
-
query_db query
|
388
|
-
end
|
389
|
-
end
|
390
|
-
collection = []
|
391
|
-
queries[query].each { |pk_id|
|
392
|
-
dobj = self[ pk_id ]
|
393
|
-
collection << dobj if dobj
|
394
|
-
}
|
395
|
-
collection
|
396
|
-
end
|
397
|
-
|
398
417
|
def last_commit_time( pk_id ); commit_times[pk_id]; end
|
399
418
|
|
400
|
-
def query_db( query )
|
401
|
-
newObjects = @db_bridge.select_dobjs query
|
402
|
-
newObjects.each { |dbObj| save dbObj }
|
403
|
-
queries[query] = newObjects.collect { |dobj| dobj.pk_id }
|
404
|
-
end
|
405
|
-
|
406
419
|
# Saves a domain object.
|
407
420
|
def save(db_object)
|
408
421
|
self[db_object.pk_id] = db_object
|
@@ -412,11 +425,11 @@ module Lafcadio
|
|
412
425
|
def set_commit_time( d_obj ); commit_times[d_obj.pk_id] = Time.now; end
|
413
426
|
|
414
427
|
def update_after_commit( db_object ) #:nodoc:
|
415
|
-
if [
|
428
|
+
if [ :update, :insert ].include?(
|
416
429
|
db_object.last_commit_type
|
417
430
|
)
|
418
431
|
save db_object
|
419
|
-
elsif db_object.last_commit_type ==
|
432
|
+
elsif db_object.last_commit_type == :delete
|
420
433
|
flush db_object
|
421
434
|
end
|
422
435
|
set_commit_time db_object
|
@@ -431,7 +444,9 @@ module Lafcadio
|
|
431
444
|
@obj = obj
|
432
445
|
reversed = []
|
433
446
|
@obj.class.self_and_concrete_superclasses.each { |domain_class|
|
434
|
-
|
447
|
+
statement_bind_value_pairs( domain_class ).reverse.each do |pair|
|
448
|
+
reversed << pair
|
449
|
+
end
|
435
450
|
}
|
436
451
|
reversed.reverse.each do |statement, binds|
|
437
452
|
self << [ statement, binds ]
|
@@ -464,7 +479,8 @@ module Lafcadio
|
|
464
479
|
fields = domain_class.class_fields
|
465
480
|
nameValuePairs = get_name_value_pairs( domain_class )
|
466
481
|
if domain_class.is_child_domain_class?
|
467
|
-
|
482
|
+
pair = DbBridge.last_inserted_pk_id_pair domain_class.superclass
|
483
|
+
nameValuePairs[domain_class.sql_primary_key_name] = pair.first
|
468
484
|
end
|
469
485
|
fieldNameStr = nameValuePairs.keys.join ", "
|
470
486
|
fieldValueStr = nameValuePairs.values.join ", "
|
@@ -472,18 +488,24 @@ module Lafcadio
|
|
472
488
|
"values(#{fieldValueStr})"
|
473
489
|
end
|
474
490
|
|
475
|
-
def
|
491
|
+
def statement_bind_value_pairs( domain_class )
|
476
492
|
@bind_values = []
|
477
493
|
if @obj.pk_id == nil
|
478
494
|
statement = insert_sql( domain_class )
|
495
|
+
pairs = [ [statement, @bind_values] ]
|
496
|
+
if domain_class.is_child_domain_class? and ObjectStore.db_type == 'Pg'
|
497
|
+
setval_sql = "select setval( '#{ domain_class.postgres_pk_id_seq }', currval('#{ domain_class.superclass.postgres_pk_id_seq }') )"
|
498
|
+
pairs << [ setval_sql, @bind_values ]
|
499
|
+
end
|
500
|
+
pairs
|
479
501
|
else
|
480
502
|
if @obj.delete
|
481
503
|
statement = delete_sql( domain_class )
|
482
504
|
else
|
483
505
|
statement = update_sql( domain_class)
|
484
506
|
end
|
507
|
+
[ [statement, @bind_values] ]
|
485
508
|
end
|
486
|
-
[statement, @bind_values]
|
487
509
|
end
|
488
510
|
|
489
511
|
def update_sql( domain_class )
|
@@ -513,8 +535,18 @@ module Lafcadio
|
|
513
535
|
new
|
514
536
|
end
|
515
537
|
|
538
|
+
def self.last_inserted_pk_id_pair( domain_class )
|
539
|
+
case ObjectStore.db_type
|
540
|
+
when 'Mysql'
|
541
|
+
[ 'last_insert_id()', 'last_insert_id()' ]
|
542
|
+
when 'Pg'
|
543
|
+
[ "currval('#{ domain_class.postgres_pk_id_seq }')", 'currval' ]
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
516
547
|
def initialize
|
517
548
|
@db_conn = DbConnection.get_db_connection
|
549
|
+
@transaction = nil
|
518
550
|
ObjectSpace.define_finalizer( self, proc { |id|
|
519
551
|
DbConnection.get_db_connection.disconnect
|
520
552
|
} )
|
@@ -533,10 +565,17 @@ module Lafcadio
|
|
533
565
|
@db_conn.do( sql, *binds )
|
534
566
|
end
|
535
567
|
if statements_and_binds[0].first =~ /insert/
|
536
|
-
|
537
|
-
|
538
|
-
|
568
|
+
@@last_pk_id_inserted = get_last_pk_id_inserted(
|
569
|
+
db_object.domain_class
|
570
|
+
)
|
539
571
|
end
|
572
|
+
@db_conn.do( 'commit' ) unless @transaction
|
573
|
+
end
|
574
|
+
|
575
|
+
def get_last_pk_id_inserted( domain_class )
|
576
|
+
pair = self.class.last_inserted_pk_id_pair( domain_class )
|
577
|
+
sql = 'select ' + pair.first
|
578
|
+
select_all( sql ).first[pair.last].to_i
|
540
579
|
end
|
541
580
|
|
542
581
|
def group_query( query )
|
@@ -572,26 +611,41 @@ module Lafcadio
|
|
572
611
|
def select_dobjs(query)
|
573
612
|
domain_class = query.domain_class
|
574
613
|
select_all( query.to_sql ).collect { |row_hash|
|
575
|
-
domain_class.new(
|
614
|
+
dobj = domain_class.new(
|
615
|
+
SqlToRubyValues.new( domain_class, row_hash )
|
616
|
+
)
|
617
|
+
if query.include
|
618
|
+
query.include.each do |include_sym|
|
619
|
+
field = domain_class.field include_sym
|
620
|
+
included_dclass = field.linked_type
|
621
|
+
if dobj.send( field.name )
|
622
|
+
dobj.send( field.name ).db_object = included_dclass.new(
|
623
|
+
SqlToRubyValues.new( included_dclass, row_hash )
|
624
|
+
)
|
625
|
+
end
|
626
|
+
end
|
627
|
+
end
|
628
|
+
dobj
|
576
629
|
}
|
577
630
|
end
|
578
631
|
|
579
632
|
def transaction( action )
|
580
|
-
|
581
|
-
|
633
|
+
@transaction = Transaction.new @db_conn
|
634
|
+
@transaction.commit
|
582
635
|
begin
|
583
|
-
action.call
|
584
|
-
|
636
|
+
action.call @transaction
|
637
|
+
@transaction.commit
|
585
638
|
rescue RollbackError
|
586
639
|
# rollback handled by Transaction
|
587
640
|
rescue
|
588
641
|
err_to_raise = $!
|
589
|
-
|
642
|
+
@transaction.rollback false
|
590
643
|
raise err_to_raise
|
591
644
|
end
|
645
|
+
@transaction = nil
|
592
646
|
end
|
593
647
|
|
594
|
-
class Transaction
|
648
|
+
class Transaction #:nodoc:
|
595
649
|
def initialize( db_conn ); @db_conn = db_conn; end
|
596
650
|
|
597
651
|
def commit; @db_conn.commit; end
|
@@ -602,10 +656,11 @@ module Lafcadio
|
|
602
656
|
end
|
603
657
|
end
|
604
658
|
|
605
|
-
class RollbackError < StandardError
|
659
|
+
class RollbackError < StandardError #:nodoc:
|
660
|
+
end
|
606
661
|
end
|
607
662
|
|
608
|
-
class DbConnection < ContextualService::Service
|
663
|
+
class DbConnection < ContextualService::Service #:nodoc:
|
609
664
|
@@conn_class = DBI
|
610
665
|
@@db_name = nil
|
611
666
|
|
@@ -617,17 +672,21 @@ module Lafcadio
|
|
617
672
|
|
618
673
|
def disconnect; @dbh.disconnect; end
|
619
674
|
|
620
|
-
def
|
675
|
+
def driver_url
|
621
676
|
config = LafcadioConfig.new
|
622
677
|
dbName = @@db_name || config['dbname']
|
623
|
-
|
678
|
+
driver_name = config['dbtype'] || 'Mysql'
|
624
679
|
if dbName && config['dbhost']
|
625
|
-
|
680
|
+
"dbi:#{ driver_name }:#{ dbName }:#{ config['dbhost'] }"
|
626
681
|
else
|
627
|
-
|
682
|
+
"dbi:#{config['dbconn']}"
|
628
683
|
end
|
684
|
+
end
|
685
|
+
|
686
|
+
def load_new_dbh
|
687
|
+
config = LafcadioConfig.new
|
629
688
|
dbh = @@conn_class.connect(
|
630
|
-
|
689
|
+
driver_url, config['dbuser'], config['dbpassword']
|
631
690
|
)
|
632
691
|
dbh['AutoCommit'] = false
|
633
692
|
dbh
|
@@ -646,69 +705,75 @@ module Lafcadio
|
|
646
705
|
@orig_args = other_args
|
647
706
|
@maybe_proc = @orig_args.shift if @orig_args.size > 0
|
648
707
|
@methodName = orig_method.id2name
|
649
|
-
|
708
|
+
dispatch_method
|
709
|
+
end
|
710
|
+
|
711
|
+
def camel_case_method_name
|
712
|
+
@orig_method.id2name.underscore_to_camel_case
|
650
713
|
end
|
651
714
|
|
652
|
-
def
|
653
|
-
@
|
654
|
-
|
715
|
+
def dispatch( object_store )
|
716
|
+
target = ( @target or object_store )
|
717
|
+
target.send( @symbol, *@args )
|
655
718
|
end
|
656
719
|
|
657
|
-
def
|
658
|
-
@symbol = :
|
720
|
+
def dispatch_all
|
721
|
+
@symbol = :all
|
659
722
|
@args = [ @domain_class ]
|
660
723
|
end
|
661
724
|
|
662
|
-
def
|
663
|
-
@symbol = :
|
664
|
-
@args = [
|
725
|
+
def dispatch_domain_class_get( searchTerm, fieldName )
|
726
|
+
@symbol = :get
|
727
|
+
@args = [ searchTerm, fieldName ]
|
728
|
+
@target = @domain_class
|
665
729
|
end
|
666
|
-
|
730
|
+
|
667
731
|
def dispatch_get_map_object( domain_class )
|
668
732
|
@symbol = :get_map_object
|
669
733
|
@args = [ domain_class, @orig_args[0], @orig_args[1] ]
|
670
734
|
end
|
671
735
|
|
672
|
-
def
|
673
|
-
unless ( dispatch_get_singular )
|
674
|
-
domain_class_name = camel_case_method_name_after_get.singular
|
675
|
-
begin
|
676
|
-
@domain_class = Module.by_name domain_class_name
|
677
|
-
dispatch_get_plural
|
678
|
-
rescue NameError
|
679
|
-
# skip it
|
680
|
-
end
|
681
|
-
end
|
682
|
-
end
|
683
|
-
|
684
|
-
def dispatch_get_plural
|
736
|
+
def dispatch_plural
|
685
737
|
if @orig_args.size == 0 && @maybe_proc.nil?
|
686
|
-
|
738
|
+
dispatch_all
|
687
739
|
else
|
688
740
|
searchTerm, fieldName = @orig_args[0..1]
|
689
741
|
if searchTerm.nil? && @maybe_proc.nil? && fieldName.nil?
|
690
|
-
|
742
|
+
raise_plural_needs_field_arg_if_first_arg_nil
|
691
743
|
elsif !@maybe_proc.nil? && searchTerm.nil?
|
692
|
-
|
744
|
+
dispatch_plural_by_query_block
|
693
745
|
elsif @maybe_proc.nil? && ( !( searchTerm.nil? && fieldName.nil? ) )
|
694
|
-
|
746
|
+
dispatch_domain_class_get( searchTerm, fieldName )
|
695
747
|
else
|
696
|
-
|
748
|
+
raise_plural_cant_have_both_query_block_and_search_term
|
697
749
|
end
|
698
750
|
end
|
699
751
|
end
|
700
752
|
|
701
|
-
def
|
753
|
+
def dispatch_plural_by_query_block
|
702
754
|
inferrer = Query::Inferrer.new( @domain_class ) { |obj|
|
703
755
|
@maybe_proc.call( obj )
|
704
756
|
}
|
705
|
-
@symbol = :
|
757
|
+
@symbol = :query
|
706
758
|
@args = [ inferrer.execute ]
|
707
759
|
end
|
708
760
|
|
709
|
-
def
|
761
|
+
def dispatch_method
|
762
|
+
unless ( dispatch_singular )
|
763
|
+
domain_class_name = camel_case_method_name.singular
|
764
|
+
begin
|
765
|
+
@domain_class = Module.by_name domain_class_name
|
766
|
+
dispatch_plural
|
767
|
+
rescue NameError
|
768
|
+
# skip it
|
769
|
+
end
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
773
|
+
def dispatch_singular
|
710
774
|
begin
|
711
|
-
|
775
|
+
d_class_name = @orig_method.id2name.underscore_to_camel_case
|
776
|
+
domain_class = Module.by_name d_class_name
|
712
777
|
if @orig_args[0].class <= Integer
|
713
778
|
@symbol = :get
|
714
779
|
@args = [ domain_class, @orig_args[0] ]
|
@@ -723,13 +788,13 @@ module Lafcadio
|
|
723
788
|
end
|
724
789
|
end
|
725
790
|
|
726
|
-
def
|
791
|
+
def raise_plural_needs_field_arg_if_first_arg_nil
|
727
792
|
msg = "ObjectStore\##{ @orig_method } needs a field name as its " +
|
728
793
|
"second argument if its first argument is nil"
|
729
794
|
raise( ArgumentError, msg, caller )
|
730
795
|
end
|
731
796
|
|
732
|
-
def
|
797
|
+
def raise_plural_cant_have_both_query_block_and_search_term
|
733
798
|
raise(
|
734
799
|
ArgumentError, "Shouldn't send both a query block and a search term",
|
735
800
|
caller
|