lore 0.4.8 → 0.9.2

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 (111) hide show
  1. data/Manifest.txt +16 -7
  2. data/README.rdoc +91 -0
  3. data/benchmark/benchmark.sql +11 -0
  4. data/benchmark/results.txt +28 -0
  5. data/benchmark/select.rb +352 -0
  6. data/lib/lore.rb +22 -8
  7. data/lib/lore/adapters/context.rb +64 -0
  8. data/lib/lore/adapters/postgres-pr.rb +6 -0
  9. data/lib/lore/adapters/postgres-pr/connection.rb +93 -0
  10. data/lib/lore/adapters/postgres-pr/result.rb +63 -0
  11. data/lib/lore/{types.rb → adapters/postgres-pr/types.rb} +36 -0
  12. data/lib/lore/adapters/postgres.rb +24 -0
  13. data/lib/lore/adapters/postgres/connection.rb +81 -0
  14. data/lib/lore/adapters/postgres/result.rb +82 -0
  15. data/lib/lore/adapters/postgres/types.rb +91 -0
  16. data/lib/lore/bits.rb +18 -0
  17. data/lib/lore/cache/abstract_entity_cache.rb +2 -1
  18. data/lib/lore/cache/cacheable.rb +12 -177
  19. data/lib/lore/cache/memcache_entity_cache.rb +89 -0
  20. data/lib/lore/cache/memory_entity_cache.rb +77 -0
  21. data/lib/lore/cache/mmap_entity_cache.rb +2 -2
  22. data/lib/lore/cache/mmap_entity_cache_bork.rb +86 -0
  23. data/lib/lore/clause.rb +107 -35
  24. data/lib/lore/{exception → exceptions}/ambiguous_attribute.rb +2 -2
  25. data/lib/lore/{exception → exceptions}/cache_exception.rb +1 -1
  26. data/lib/lore/exceptions/database_exception.rb +16 -0
  27. data/lib/lore/{exception/invalid_parameter.rb → exceptions/invalid_field.rb} +7 -4
  28. data/lib/lore/exceptions/unknown_type.rb +18 -0
  29. data/lib/lore/exceptions/validation_failure.rb +71 -0
  30. data/lib/lore/gui/form_generator.rb +109 -60
  31. data/lib/lore/gui/lore_model_select_field.rb +1 -0
  32. data/lib/lore/migration.rb +84 -25
  33. data/lib/lore/model.rb +3 -18
  34. data/lib/lore/{aspect.rb → model/aspect.rb} +0 -0
  35. data/lib/lore/model/associations.rb +225 -0
  36. data/lib/lore/model/attribute_settings.rb +233 -0
  37. data/lib/lore/model/filters.rb +34 -0
  38. data/lib/lore/model/mockable.rb +62 -0
  39. data/lib/lore/{model_factory.rb → model/model_factory.rb} +68 -39
  40. data/lib/lore/model/model_instance.rb +382 -0
  41. data/lib/lore/{model_shortcuts.rb → model/model_shortcuts.rb} +7 -0
  42. data/lib/lore/model/polymorphic.rb +53 -0
  43. data/lib/lore/model/prepare.rb +97 -0
  44. data/lib/lore/model/table_accessor.rb +1016 -0
  45. data/lib/lore/query.rb +71 -0
  46. data/lib/lore/query_shortcuts.rb +43 -11
  47. data/lib/lore/strategies/table_delete.rb +115 -0
  48. data/lib/lore/strategies/table_insert.rb +146 -0
  49. data/lib/lore/strategies/table_select.rb +299 -0
  50. data/lib/lore/strategies/table_update.rb +155 -0
  51. data/lib/lore/validation/parameter_validator.rb +85 -26
  52. data/lib/lore/validation/type_validator.rb +34 -78
  53. data/{custom_models.rb → lore-0.9.2.gem} +0 -0
  54. data/lore.gemspec +26 -17
  55. data/spec/clause.rb +37 -0
  56. data/spec/fixtures/blank_models.rb +37 -0
  57. data/{test/model.rb → spec/fixtures/models.rb} +64 -41
  58. data/spec/fixtures/polymorphic_models.rb +68 -0
  59. data/spec/model_associations.rb +86 -0
  60. data/spec/model_create.rb +47 -0
  61. data/spec/model_definition.rb +151 -0
  62. data/spec/model_delete.rb +31 -0
  63. data/spec/model_inheritance.rb +50 -0
  64. data/spec/model_polymorphic.rb +85 -0
  65. data/spec/model_select.rb +101 -0
  66. data/spec/model_select_eager.rb +42 -0
  67. data/spec/model_union_select.rb +33 -0
  68. data/spec/model_update.rb +45 -0
  69. data/spec/model_validation.rb +20 -0
  70. data/spec/spec_db.sql +808 -0
  71. data/spec/spec_env.rb +19 -0
  72. data/spec/spec_helpers.rb +77 -0
  73. metadata +93 -82
  74. data/lib/lore/README.txt +0 -84
  75. data/lib/lore/behaviours/lockable.rb +0 -55
  76. data/lib/lore/behaviours/movable.rb +0 -72
  77. data/lib/lore/behaviours/paginated.rb +0 -31
  78. data/lib/lore/behaviours/versioned.rb +0 -36
  79. data/lib/lore/connection.rb +0 -152
  80. data/lib/lore/exception/invalid_klass_parameters.rb +0 -63
  81. data/lib/lore/exception/unknown_typecode.rb +0 -19
  82. data/lib/lore/result.rb +0 -119
  83. data/lib/lore/symbol.rb +0 -58
  84. data/lib/lore/table_accessor.rb +0 -1790
  85. data/lib/lore/table_deleter.rb +0 -116
  86. data/lib/lore/table_inserter.rb +0 -170
  87. data/lib/lore/table_instance.rb +0 -389
  88. data/lib/lore/table_selector.rb +0 -285
  89. data/lib/lore/table_updater.rb +0 -157
  90. data/lib/lore/validation.rb +0 -65
  91. data/lib/lore/validation/message.rb +0 -60
  92. data/lib/lore/validation/reason.rb +0 -52
  93. data/lore_test.log +0 -2366
  94. data/test/README +0 -31
  95. data/test/custom_models.rb +0 -18
  96. data/test/env.rb +0 -5
  97. data/test/prepare.rb +0 -37
  98. data/test/tc_aspect.rb +0 -58
  99. data/test/tc_cache.rb +0 -83
  100. data/test/tc_clause.rb +0 -104
  101. data/test/tc_deep_inheritance.rb +0 -49
  102. data/test/tc_factory.rb +0 -57
  103. data/test/tc_filter.rb +0 -37
  104. data/test/tc_form.rb +0 -32
  105. data/test/tc_model.rb +0 -140
  106. data/test/tc_prepare.rb +0 -44
  107. data/test/tc_refined_query.rb +0 -88
  108. data/test/tc_table_accessor.rb +0 -267
  109. data/test/tc_thread.rb +0 -100
  110. data/test/test_db.sql +0 -400
  111. data/test/test_lore.rb +0 -50
@@ -0,0 +1,47 @@
1
+
2
+ require 'spec_env'
3
+ include Lore::Spec_Fixtures::Models
4
+
5
+ describe(Lore::Table_Accessor) do
6
+ before do
7
+ end
8
+
9
+ it "does not create records for aggregated models on create procedures" do
10
+ motor = Motor.create(:motor_name => 'Gaso-Suck 3000', :kw => 200)
11
+
12
+ vehicle = Motorized_Vehicle.create(:name => 'vehicle_name',
13
+ :num_doors => 3,
14
+ :num_seats => 5,
15
+ :owner_id => 0,
16
+ :maxspeed => 170,
17
+ :motor_id => motor.pkey)
18
+
19
+ vehicle.name.should == 'vehicle_name'
20
+ vehicle.motor_name.should == 'Gaso-Suck 3000'
21
+ vehicle.kw.should == 200
22
+ vehicle.maxspeed.should == "170km/h"
23
+ end
24
+
25
+ it "automatically distributes attribute values on base tables on create procedures" do
26
+
27
+ motor = Motor.create(:motor_name => 'Lawn Mower Ultra', :kw => 20)
28
+
29
+ car = Car.create(:name => 'vehicle_name',
30
+ :num_doors => 5,
31
+ :num_seats => 4,
32
+ :owner_id => 0,
33
+ :motor_id => motor.pkey,
34
+ :car_type_id => Car_Type.create(:type_name => 'Roadkill X1000').car_type_id,
35
+ :maxspeed => 180)
36
+ car.num_doors.should == 5
37
+ car.name.should == 'vehicle_name'
38
+ car.maxspeed.should == '180km/h'
39
+ end
40
+
41
+ it "provides a before_create hook" do
42
+ end
43
+
44
+ it "provides an after_create hook" do
45
+ end
46
+
47
+ end
@@ -0,0 +1,151 @@
1
+
2
+ require 'spec_env'
3
+ include Lore::Spec_Fixtures::Blank_Models
4
+
5
+ describe(Lore::Table_Accessor) do
6
+ before do
7
+ # Lore::Spec_Fixtures::Models::Vehicle.delete_all
8
+ # Lore::Spec_Fixtures::Models::Car.delete_all
9
+ # Lore::Spec_Fixtures::Models::Motorbike.delete_all
10
+ # Lore::Spec_Fixtures::Models::Owner.delete_all
11
+ # Lore::Spec_Fixtures::Models::Vehicle_Owner.delete_all
12
+ # Lore::Spec_Fixtures::Models::Car_Type.delete_all
13
+ # Lore::Spec_Fixtures::Models::Garage.delete_all
14
+ # Lore::Spec_Fixtures::Models::Motor.delete_all
15
+ # Lore::Spec_Fixtures::Models::Motorized_Vehicle.delete_all
16
+ end
17
+
18
+ it "is assigned to a base table" do
19
+ Vehicle.table :vehicle, :public
20
+ Car.table :car, :public
21
+ Motorbike.table :motorbike, :public
22
+ Owner.table :owner, :public
23
+ Vehicle_Owner.table :vehicle_owner, :public
24
+ Car_Type.table :car_type, :public
25
+ Garage.table :garage, :public
26
+ Motor.table :motor, :public
27
+ Motorized_Vehicle.table :motorized, :public
28
+
29
+ Car.table_name.should == 'public.car'
30
+ Vehicle.table_name.should == 'public.vehicle'
31
+ Motorbike.table_name.should == 'public.motorbike'
32
+ Owner.table_name.should == 'public.owner'
33
+ Vehicle_Owner.table_name.should == 'public.vehicle_owner'
34
+ Car_Type.table_name.should == 'public.car_type'
35
+ Garage.table_name.should == 'public.garage'
36
+ end
37
+
38
+ it "loads attribute fields automatically as array of symbols" do
39
+ Vehicle.get_fields.should == { 'public.vehicle' => [ :id, :manuf_id, :num_seats, :maxspeed, :name, :owner_id ] }
40
+ Vehicle.get_fields_flat.should == [ :id, :manuf_id, :num_seats, :maxspeed, :name, :owner_id ]
41
+ end
42
+
43
+ it "has one or more primary key attributes" do
44
+ Vehicle.primary_key :id, :vehicle_id_seq
45
+ Car.primary_key :id, :car_id_seq
46
+ Motorbike.primary_key :motorbike_id, :motorbike_id_seq
47
+ Owner.primary_key :owner_id, :owner_id_seq
48
+ Car_Type.primary_key :car_type_id, :car_type_id_seq
49
+ Garage.primary_key :garage_id, :garage_id_seq
50
+ Motor.primary_key :id, :motor_id_seq
51
+ Motorized_Vehicle.primary_key :id, :motorized_id_seq
52
+ end
53
+
54
+ it "may have required attributes" do
55
+ Car.expects :num_seats
56
+ # does the same
57
+ Car.validates :num_doors, :mandatory => true
58
+ end
59
+
60
+ it "allows adding other models as aggregates" do
61
+ Car.aggregates Car_Type, :car_type_id
62
+ Motorized_Vehicle.is_a Vehicle, :vehicle_id
63
+ Motorized_Vehicle.aggregates Motor, :motor_id
64
+ Motorized_Vehicle.__associations__.base_klasses.values.should == [ [ Vehicle, [ :vehicle_id ] ] ]
65
+ Motorized_Vehicle.__associations__.aggregate_klasses.values.should == [ [ Motor , [ :motor_id ] ] ]
66
+ Motorized_Vehicle.__associations__.joined_models.values.should == [ [ Vehicle, [ :vehicle_id ] ] , [ Motor, [ :motor_id ] ] ]
67
+ end
68
+
69
+ it "can be derived from one base model or more" do
70
+ Car.is_a Motorized_Vehicle, :motorized_id
71
+ Motorbike.is_a Vehicle, :vehicle_id
72
+
73
+ Car.is_a?(Motorized_Vehicle).should == true
74
+ Car.is_a?(Vehicle).should == true
75
+ end
76
+
77
+ it "inherits attribute fields from joined base models" do
78
+ expected_fields = {
79
+ 'public.vehicle' => [ :id, :manuf_id, :num_seats, :maxspeed, :name, :owner_id ],
80
+ 'public.car_type' => [ :car_type_id, :type_name ],
81
+ 'public.car' => [ :id, :motorized_id, :car_type_id, :num_doors ],
82
+ 'public.motorized' => [ :vehicle_id, :motor_id, :id ],
83
+ 'public.motor' => [ :id, :motor_name, :kw ]
84
+ }
85
+ Car.get_fields.should_be expected_fields
86
+ end
87
+
88
+ it "may have composed primary keys" do
89
+ Vehicle_Owner.primary_key :vehicle_id
90
+ Vehicle_Owner.primary_key :owner_id
91
+ end
92
+
93
+ it "may have non-sequential primary keys" do
94
+ end
95
+
96
+ it "allows arbitrary naming of keys" do
97
+ Vehicle.has_a Owner, :owner
98
+ end
99
+
100
+ it "provides input and output filters for attribute values" do
101
+ end
102
+
103
+ it "defines attributes that cannot be set manually as explicit" do
104
+ expected = {
105
+ # has_a foreign keys :manuf_id and owner are explicit:
106
+ 'public.vehicle' => [ :manuf_id, :num_seats, :maxspeed, :name, :owner_id ],
107
+ # Aggregate foreign key :motor_id is explicit:
108
+ 'public.motorized' => [ :motor_id ],
109
+ # Aggregate foreign key :car_type_id is explicit:
110
+ 'public.car' => [ :car_type_id, :num_doors ]
111
+
112
+ # Aggregated models do not extend implicit or explicit fields!
113
+ # 'public.motor' => [ :motor_name ],
114
+ # 'public.car_type' => [ :type_name ],
115
+ }
116
+ Car.__attributes__.explicit.should_be expected
117
+ end
118
+
119
+ it "defines all attributes that are not explicit as implicit" do
120
+ expected = {
121
+ 'public.vehicle' => [ :id ],
122
+ 'public.motorized' => [ :id, :vehicle_id ],
123
+ 'public.car' => [ :id, :motorized_id ]
124
+
125
+ # Aggregated models do not extend implicit or explicit fields!
126
+ # 'public.motor' => [ :id ],
127
+ # 'public.car_type' => [ :car_type_id ],
128
+ }
129
+
130
+ Car.__attributes__.implicit.should_be expected
131
+ end
132
+
133
+ it "provides a before_select hook" do
134
+ end
135
+
136
+ it "provides validating presence of attribute values" do
137
+ Vehicle.validates :name, :mandatory => true
138
+ # .expects does the same
139
+ Car.expects :num_doors
140
+ end
141
+
142
+ it "provides validating attribute values by length" do
143
+ Vehicle.validates :name, :maxlength => 20
144
+ end
145
+
146
+ it "provides validating attribute values by format" do
147
+ Vehicle.validates :name, :format => NAME_FORMAT
148
+ end
149
+
150
+
151
+ end
@@ -0,0 +1,31 @@
1
+
2
+ require 'spec_env'
3
+ include Lore::Spec_Fixtures::Models
4
+
5
+ include Spec_Model_Select_Helpers
6
+
7
+ describe(Lore::Table_Accessor) do
8
+
9
+ it "does not delete records for aggregated models on delete procedures" do
10
+ manuf = Manufacturer.create(:name => 'Major Motors')
11
+ vehicle = Car.create(car_create_values(:name => 'wombat', :manuf_id => manuf.pkey))
12
+ manuf_id = vehicle.manufacturer.manuf_id
13
+ motor_id = vehicle.motor_id
14
+ manuf = Manufacturer.get(manuf_id)
15
+ vehicle.motor_name.should == 'Mock Motor'
16
+ vehicle.delete!
17
+ manuf = Manufacturer.get(manuf_id) # Re-Select
18
+ motor = Motor.get(motor_id) # Re-Select
19
+ manuf.should_not == false
20
+ motor.should_not == false
21
+ end
22
+
23
+ it "deletes single Model instances on Model#delete" do
24
+ car = Car.create(car_create_values(:name => 'delete_me!'))
25
+ car_id = car.pkey
26
+ car.delete
27
+ Car.get(car_id).should == false
28
+ end
29
+
30
+ end
31
+
@@ -0,0 +1,50 @@
1
+
2
+ require 'spec_env'
3
+ include Lore::Spec_Fixtures::Models
4
+
5
+ describe(Lore::Table_Accessor) do
6
+
7
+ before do
8
+ flush_test_data()
9
+ end
10
+
11
+ it "provides single inheritance" do
12
+ Motorized_Vehicle.is_a?(Vehicle).should == true
13
+ Car.is_a?(Vehicle).should == true
14
+
15
+ end
16
+
17
+ it "provides multiple inheritance" do
18
+ Autobot.is_a?(Car).should == true
19
+ Autobot.is_a?(Robot).should == true
20
+
21
+ motor = Motor.create(:motor_name => 'Autobot Car Motor',
22
+ :kw => 239)
23
+ car_type = Car_Type.create(:type_name => 'Autobot Car')
24
+
25
+ t = Autobot.create(# Attributes for Vehicle
26
+ :name => 'Autobot',
27
+ :num_seats => 4,
28
+ :maxspeed => 190,
29
+ :owner_id => 23,
30
+ :manuf_id => 42,
31
+ # Attributes for Motorized
32
+ :motor_type => 'brushless',
33
+ :motor_id => motor.pkey,
34
+ # Attributes for Car
35
+ :car_type_id => car_type.pkey,
36
+ :num_doors => 5,
37
+ # Attributes for Robot
38
+ :robot_class => 'Exoskel X3000',
39
+ :locomotion_type => 'bipedal')
40
+
41
+ t.name.should == 'autobot'
42
+ t.num_seats.should == 4
43
+ t.manuf_id.should == 42
44
+ t.motor_type.should == 'brushless'
45
+ t.locomotion_type.should == 'bipedal'
46
+
47
+ t.transform.should == 'Autobot transformed!'
48
+ end
49
+
50
+ end
@@ -0,0 +1,85 @@
1
+
2
+ require 'spec_env'
3
+ include Lore::Spec_Fixtures::Polymorphic_Models
4
+
5
+ describe(Lore::Table_Accessor) do
6
+ before do
7
+ flush_test_data()
8
+ end
9
+
10
+ it "implements the Liskov substitution principle" do
11
+ end
12
+
13
+ it "implements inverse polymorphism" do
14
+
15
+ Asset.is_polymorphic?.should == true
16
+ Media_Asset.is_polymorphic?.should == false
17
+ Document_Asset.is_polymorphic?.should == false
18
+
19
+ expected = { 'public.asset' => :model }
20
+ Media_Asset.__associations__.polymorphics.should_be expected
21
+
22
+ Asset.__associations__.concrete_models.length.should == 2
23
+
24
+ 5.times {
25
+ info = Media_Asset_Info.create(:description => 'a media file')
26
+ media = Media_Asset.create(:folder => '/tmp/spec/media/',
27
+ :filename => 'music.ogg',
28
+ :hits => 123,
29
+ :info_id => info.pkey,
30
+ :media_type => 'sound')
31
+ info = Document_Asset_Info.create(:relevance => 5)
32
+ docum = Document_Asset.create(:folder => '/tmp/spec/docs/',
33
+ :filename => 'sample.txt',
34
+ :info_id => info.pkey,
35
+ :doctype => 'plaintext')
36
+
37
+ }
38
+ polymorphics = Asset.find(10).polymorphic.sort_by(Asset.asset_id, :desc).entities
39
+ polymorphics.length.should == 10
40
+ polymorphics.each_with_index { |a,idx|
41
+ expected = (idx % 2 == 1)? true : false
42
+ a.is_a?(Media_Asset).should == expected
43
+ a.is_a?(Document_Asset).should == !expected
44
+ }
45
+ end
46
+
47
+ it "Handles inherited fields like in regular selects" do
48
+
49
+ info = Media_Asset_Info.create(:description => 'a media file')
50
+ media = Media_Asset.create(:folder => '/tmp/spec/media/',
51
+ :filename => 'music.ogg',
52
+ :hits => 123,
53
+ :info_id => info.pkey,
54
+ :media_type => 'sound')
55
+ info = Document_Asset_Info.create(:relevance => 5)
56
+ docum = Document_Asset.create(:folder => '/tmp/spec/docs/',
57
+ :filename => 'sample.txt',
58
+ :info_id => info.pkey,
59
+ :doctype => 'plaintext')
60
+
61
+ media_polymorphic_id = media.asset_id
62
+ docum_polymorphic_id = docum.asset_id
63
+
64
+ # Select an Asset which is known to be a concrete
65
+ # Media_Asset:
66
+ asset = Asset.polymorphic_select { |a|
67
+ a.where(Asset.asset_id.is media_polymorphic_id)
68
+ a.limit(1)
69
+ }.first
70
+ asset.is_a?(Media_Asset).should == true
71
+ asset.is_a?(Asset).should == true
72
+ asset.media_type.should == 'sound'
73
+
74
+ # Select an Asset which is known to be a concrete
75
+ # Document_Asset:
76
+ asset = Asset.polymorphic_select { |a|
77
+ a.where(Asset.asset_id.is docum_polymorphic_id)
78
+ a.limit(1)
79
+ }.first
80
+ asset.is_a?(Document_Asset).should == true
81
+ asset.is_a?(Asset).should == true
82
+ asset.doctype.should == 'plaintext'
83
+ end
84
+
85
+ end
@@ -0,0 +1,101 @@
1
+
2
+ require 'spec_env'
3
+ include Lore::Spec_Fixtures::Models
4
+
5
+ include Spec_Model_Select_Helpers
6
+
7
+ describe(Lore::Table_Accessor) do
8
+ before do
9
+ flush_test_data()
10
+ end
11
+
12
+ it "should provide a DSL for selects" do
13
+
14
+ for index in 0...3 do
15
+ Car.create(car_create_values(:name => "Car #{index}" ))
16
+ end
17
+
18
+ expected = Car.select_value('count(*)') { |c| c.where(true) }
19
+ expected.to_i.should == 3
20
+
21
+ car = Car.select { |c|
22
+ c.where((c.name == "car1").or(c.name == "car2"))
23
+ c.limit(1)
24
+ }.first
25
+ car.name.should == "car1"
26
+
27
+ car = Car.select { |c|
28
+ c.where((c.name == "car1").or(c.name == "car2"))
29
+ c.limit(1, 1)
30
+ }.first
31
+ car.name.should == "car2"
32
+ end
33
+
34
+ it "provides convenience methods for selects" do
35
+ car_org = Car.create(car_create_values(:name => "The Car" ))
36
+ car_sel = Car.find(1).with(Car.name == "thecar").entity
37
+ car_org.name.should == "thecar"
38
+ car_sel.name.should == "thecar"
39
+ car_org.should == car_sel
40
+ end
41
+
42
+ it "allows arbitrary joins with other models" do
43
+
44
+ cf = Car_Features.create(:car_id => Car.create(car_create_values(:name => 'fordmondeo')).pkey,
45
+ :color => 'red')
46
+
47
+ res = Car.select { |c|
48
+ c.join(Car_Features).on(Car.id == Car_Features.car_id) { |cc|
49
+ cc.where(:name.ilike('ford%') & :color.is('red'))
50
+ }
51
+ }.first
52
+ res.color.should == 'red'
53
+ res.name.should == 'fordmondeo'
54
+
55
+ end
56
+
57
+ it "allows selecting skalar values, e.g. for aggregate functions" do
58
+ most_recent_car = false
59
+ 3.times {
60
+ most_recent_car = Car.create(car_create_values(:name => "The Car" ))
61
+ }
62
+ values = Car.select_values('count(*), max(car.id)') { |c|
63
+ c.where(true)
64
+ }.first
65
+
66
+ values[0].to_i.should == 3
67
+ values[1].to_i.should == most_recent_car.id
68
+ end
69
+
70
+ it "provides convenience methods for selecting skalar values" do
71
+ most_recent_car = false
72
+ id_sum = 0
73
+ 3.times {
74
+ most_recent_car = Car.create(car_create_values(:name => "The Car" ))
75
+ id_sum += most_recent_car.id
76
+ }
77
+ Car.value_of.max(Car.id).to_i.should == most_recent_car.id
78
+ Car.value_of.sum(Car.id).to_i.should == id_sum
79
+ end
80
+
81
+ it "does not trigger queries immediately, but provides proxy query objects" do
82
+ Lore::Connection.reset_query_count
83
+ query = Car.select { |c|
84
+ c.where(c.num_seats >= 100)
85
+ c.limit(10,5)
86
+ }
87
+ query.is_a?(Lore::Select_Query).should == true
88
+ query_string = query.sql
89
+ expected = "SELECT * FROM public.car
90
+ JOIN public.car_type ON (public.car_type.car_type_id = public.car.car_type_id)
91
+ JOIN public.motorized ON (public.motorized.id = public.car.motorized_id)
92
+ JOIN public.vehicle ON (public.vehicle.id = public.motorized.vehicle_id)
93
+ JOIN public.motor ON (public.motor.id = public.motorized.motor_id)
94
+ WHERE num_seats >= '100' LIMIT 10 OFFSET 5"
95
+ query.sql.gsub(/\s/,'').should == expected.gsub(/\s/,'')
96
+ Lore::Connection.query_count.should == 0
97
+ end
98
+
99
+ end
100
+
101
+