lore 0.4.8 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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
File without changes
@@ -9,37 +9,46 @@ spec = Gem::Specification.new { |s|
9
9
  s.description = <<-EOF
10
10
  Lore is an object-relational mapping (ORM) implementation
11
11
  providing many features like prepared statements,
12
- (multiple) inheritance, a comfortable query syntax,
13
- highly customizable automated form generation,
14
- and result caching using memory mapping (MMap).
12
+ (multiple) inheritance, true polymorphism, a comfortable
13
+ query syntax, highly customizable automated form generation,
14
+ and result caching.
15
15
  It aims at performance, usability and - unlike most ORMs -
16
- high coverage of native SQL functions and features.
16
+ high coverage of object oriented paradigms.
17
17
  Lore is currently using PostgreSQL as database backend.
18
18
  EOF
19
- s.version = '0.4.8'
20
- s.author = 'Tobias Fuchs'
21
- s.email = 'fuchs@atomnode.net'
22
- s.date = Time.now
23
- s.files = '*.rb'
24
- s.add_dependency('postgres', '>= 0.1')
25
- s.add_dependency('aurita-gui', '>= 0.1')
19
+ s.version = '0.9.2'
20
+ s.author = 'Tobias Fuchs'
21
+ s.email = 'twh.fuchs@gmail.com'
22
+ s.date = Time.now
23
+ s.files = '*.rb'
24
+
25
+ s.requirements = "A ruby binding for PostgreSQL, such as postgres or postgres-pr. "
26
+ # Remove dependency as postgres-pr would be ok, too
27
+ # s.add_dependency('postgres', '>= 0.1')
28
+ s.add_dependency('aurita-gui', '>= 0.2')
26
29
  s.files = FileList['*',
30
+ 'benchmark/*',
31
+ 'spec/*',
32
+ 'spec/fixtures/*',
27
33
  'lib/*',
28
34
  'lib/lore/*',
29
- 'lib/lore/behaviours/*',
35
+ 'lib/lore/adapters/*',
36
+ 'lib/lore/adapters/postgres/*',
37
+ 'lib/lore/adapters/postgres-pr/*',
30
38
  'lib/lore/cache/*',
31
- 'lib/lore/validation/*',
39
+ 'lib/lore/exceptions/*',
32
40
  'lib/lore/gui/*',
33
41
  'lib/lore/gui/templates/*',
34
- 'lib/lore/exception/*',
35
- 'bin/*',
36
- 'test/*'].to_a
42
+ 'lib/lore/model/*',
43
+ 'lib/lore/strategies/*',
44
+ 'lib/lore/validation/*',
45
+ 'bin/*'].to_a
37
46
 
38
47
  s.has_rdoc = true
39
48
  s.rdoc_options << '--title' << 'Lore ORM' <<
40
49
  '--main' << 'Lore::Model' <<
41
50
  '--line-numbers'
42
51
 
43
- s.homepage = 'http://lore.rubyforge.org'
52
+ s.homepage = 'http://github.com/fuchsto/lore/'
44
53
 
45
54
  }
@@ -0,0 +1,37 @@
1
+
2
+ require 'spec_env'
3
+
4
+ include Lore::Spec_Fixtures::Models
5
+
6
+ describe(Lore::Clause) do
7
+
8
+ it "is assigned to a concrete table field" do
9
+ Car.maxspeed.to_s.should == 'public.vehicle.maxspeed'
10
+ Car.num_seats.to_s.should == 'public.vehicle.num_seats'
11
+ Car.num_doors.to_s.should == 'public.car.num_doors'
12
+ Car.name.to_s.should == 'public.vehicle.name'
13
+ # should agggregates be included?
14
+ # Car.type_name.to_s.should == 'public.car_type.type_name
15
+ end
16
+
17
+ it "has comparison operators like >, <, <=>, <=, >= and some aliases" do
18
+ (Car.maxspeed > 100).to_s.should == "public.vehicle.maxspeed > '100'"
19
+ (Car.num_doors == 4).to_s.should == "public.car.num_doors = '4'"
20
+ (Car.num_seats <= 5).to_s.should == "public.vehicle.num_seats <= '5'"
21
+ end
22
+
23
+ it "has special SQL comparison operators such as between, like, ilike" do
24
+ Car.name.like('%wombat').to_s.should == "public.vehicle.name LIKE '%wombat'"
25
+ end
26
+
27
+ it "has logical operators like & and |" do
28
+ clause = Car.name.ilike('%knurt%').and(Car.num_doors.is(3))
29
+ clause.to_sql.should == "(public.vehicle.name ILIKE '%knurt%' AND public.car.num_doors = '3')"
30
+
31
+ or_clause = (Vehicle.num_seats.in(1..5))
32
+ or_clause.to_sql.should == "public.vehicle.num_seats BETWEEN 1 AND 5 "
33
+
34
+ (clause | or_clause).to_sql.should == "((public.vehicle.name ILIKE '%knurt%' AND public.car.num_doors = '3') OR public.vehicle.num_seats BETWEEN 1 AND 5 )"
35
+ end
36
+
37
+ end
@@ -0,0 +1,37 @@
1
+
2
+ module Lore
3
+ module Spec_Fixtures
4
+ module Blank_Models
5
+
6
+ NAME_FORMAT = { :format => /^([a-zA-Z_0-9 ])+$/, :length => 3..100, :mandatory => true }
7
+
8
+ class Vehicle < Lore::Model
9
+ end
10
+
11
+ class Motor < Lore::Model
12
+ end
13
+
14
+ class Motorized_Vehicle < Lore::Model
15
+ end
16
+
17
+ class Car < Vehicle
18
+ end
19
+
20
+ class Motorbike < Vehicle
21
+ end
22
+
23
+ class Owner < Lore::Model
24
+ end
25
+
26
+ class Vehicle_Owner < Lore::Model
27
+ end
28
+
29
+ class Car_Type < Lore::Model
30
+ end
31
+
32
+ class Garage < Lore::Model
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -1,33 +1,28 @@
1
1
 
2
2
  require 'rubygems'
3
- require('./test/env')
3
+ require('lore')
4
4
  require('lore/model')
5
5
 
6
- Lore::Context.enter :test
7
-
8
6
  module Lore
9
- module Unit
7
+ module Spec_Fixtures
8
+ module Models
10
9
 
11
- NAME_FORMAT = { :format => /^([a-zA-Z_0-9])+$/, :length => 3..100, :mandatory => true }
10
+ NAME_FORMAT = { :format => /^([a-zA-Z_0-9 ])+$/, :length => 3..100, :mandatory => true }
12
11
 
13
12
  class Manufacturer < Lore::Model
14
13
  table :manufacturer, :public
15
14
  primary_key :manuf_id, :manuf_id_seq
16
15
 
17
- validates :name, NAME_FORMAT
16
+ # validates :name, NAME_FORMAT
18
17
 
19
18
  use_label :name
20
-
21
- cache_entities
22
19
  end
23
20
 
24
21
  class Owner < Lore::Model
25
22
  table :owner, :public
26
23
  primary_key :owner_id, :owner_id_seq
27
24
 
28
- validates :name, NAME_FORMAT
29
-
30
- cache_entities
25
+ # validates :name, NAME_FORMAT
31
26
  end
32
27
 
33
28
  class Vehicle < Lore::Model
@@ -37,21 +32,17 @@ module Unit
37
32
  has_a Manufacturer, :manuf_id
38
33
  has_n Owner, :vehicle_id
39
34
 
40
- validates :name, NAME_FORMAT
35
+ # validates :name, NAME_FORMAT
41
36
  validates :maxspeed, :mandatory => true
42
37
  validates :num_seats, :mandatory => true
43
38
 
44
39
  add_input_filter(:name) { |name|
45
40
  name.gsub(/[^a-zA-Z_0-9]/,'').downcase
46
41
  }
47
- add_input_filter(:maxspeed) { |m| m.to_s.gsub('km/h','') }
42
+ add_input_filter(:maxspeed) { |m| m.to_s.sub('km/h','') }
48
43
  add_output_filter(:maxspeed) { |m| m << 'km/h' }
49
44
 
50
- explicit :optional, :owner_id
51
-
52
45
  # add_select_filter { |clause| clause & (Vehicle.deleted == 't') }
53
-
54
- cache_entities
55
46
  end
56
47
 
57
48
  class Vehicle_Owner < Lore::Model
@@ -71,27 +62,55 @@ module Unit
71
62
  table :car_type, :public
72
63
  primary_key :car_type_id, :car_type_id_seq
73
64
 
74
- validates :name, NAME_FORMAT
65
+ # validates :type_name, NAME_FORMAT
75
66
 
76
- use_label :name
67
+ use_label :type_name
68
+ end
77
69
 
78
- cache_entities
70
+ class Motor < Lore::Model
71
+ table :motor, :public
72
+ primary_key :id, :motor_id_seq
73
+
74
+ expects :kw
75
+ end
76
+
77
+ class Motorized_Vehicle < Vehicle
78
+ table :motorized, :public
79
+ primary_key :id, :motorized_id_seq
80
+
81
+ is_a Vehicle, :vehicle_id
82
+ aggregates Motor, :motor_id
79
83
  end
80
84
 
81
- class Car < Vehicle
85
+ class Car < Motorized_Vehicle
82
86
  table :car, :public
83
87
  primary_key :id, :car_id_seq
84
88
 
85
- is_a Vehicle, :vehicle_id
89
+ # This is not a typo: As vehicle_id is a unique,
90
+ # inherited primary key in Motorized_Vehicle, it
91
+ # must be allowed for referencing a Motorized_Vehicle.
92
+ # is_a Motorized_Vehicle, :vehicle_id
93
+ is_a Motorized_Vehicle, :motorized_id
86
94
  aggregates Car_Type, :car_type_id
87
95
 
88
- validates :num_seats, :mandatory => true
96
+ # validates :num_seats, :mandatory => true
89
97
  validates :num_doors, :mandatory => true
90
98
 
91
99
  add_input_filter(:maxspeed) { |m| m.to_s.gsub('km/h','') }
92
100
  add_output_filter(:maxspeed) { |m| m << 'km/h' }
93
101
 
94
- cache_entities
102
+ def drive
103
+ "driving with #{maxspeed}!"
104
+ end
105
+ end
106
+
107
+ class Car_Features < Lore::Model
108
+ table :car_features, :public
109
+ primary_key :id, :car_features_id_seq
110
+
111
+ has_a Car, :car_id
112
+
113
+ expects :color
95
114
  end
96
115
 
97
116
  class Convertible < Car
@@ -107,36 +126,40 @@ module Unit
107
126
  aggregates Car, :car_id
108
127
  end
109
128
 
110
- class Bike < Vehicle
111
- table :bike, :public
112
- primary_key :bike_id, :bike_id_seq
129
+ class Motorbike < Motorized_Vehicle
130
+ table :motorbike, :public
131
+ primary_key :id, :bike_id_seq
113
132
 
114
- is_a Vehicle, :vehicle_id
115
-
116
- cache_entities
133
+ is_a Motorized_Vehicle, :vehicle_id
117
134
  end
118
- =begin
119
- class Trike < Vehicle
120
- table :trike, :public
121
- primary_key :trike_id, :trike_id_seq
122
-
123
- is_a Car, :car_id
124
- is_a Bike, :bike_id
125
135
 
126
- cache_entities
127
- end
128
- =end
129
136
  class Garage < Lore::Model
130
137
  table :garage, :public
131
138
  primary_key :garage_id, :garage_id_seq
132
139
  primary_key :vehicle_id
133
140
 
134
141
  has_n Vehicle, :vehicle_id
142
+ end
143
+
144
+ class Robot < Lore::Model
145
+ table :robot, :public
146
+ primary_key :id, :robot_id_seq
147
+
148
+ def transform
149
+ 'Autobot transformed!'
150
+ end
151
+ end
152
+
153
+ class Autobot < Robot
154
+ table :autobot, :public
155
+ primary_key :id, :autobot_id_seq
135
156
 
136
- cache_entities
157
+ is_a Robot, :robot_id
158
+ is_a Car, :car_id
137
159
  end
138
160
 
139
161
  end
140
162
  end
163
+ end
141
164
 
142
165
 
@@ -0,0 +1,68 @@
1
+
2
+ require 'lore/model'
3
+
4
+ module Lore
5
+ module Spec_Fixtures
6
+ module Polymorphic_Models
7
+
8
+ class Asset < Lore::Model
9
+
10
+ table :asset, :public
11
+ primary_key :asset_id, :asset_id_seq
12
+
13
+ expects :folder, :filename
14
+
15
+ is_polymorphic :model
16
+
17
+ def path
18
+ folder + '/' + filename
19
+ end
20
+ end
21
+
22
+ class Media_Asset_Info < Lore::Model
23
+ table :media_asset_info, :public
24
+ primary_key :id, :media_asset_id_seq
25
+ expects :media_asset_id
26
+ end
27
+
28
+ class Document_Asset_Info < Lore::Model
29
+ table :document_asset_info, :public
30
+ primary_key :id, :document_asset_id_seq
31
+ expects :document_asset_id
32
+ end
33
+
34
+ class Media_Asset < Asset
35
+ table :media_asset, :public
36
+ primary_key :id, :media_asset_id_seq
37
+
38
+ is_a Asset, :asset_id
39
+
40
+ expects :media_type
41
+ aggregates Media_Asset_Info, :info_id
42
+ end
43
+
44
+ # class Movie_Asset < Media_Asset
45
+ # table :movie_asset, :public
46
+ # primary_key :id, :movie_asset_id_seq
47
+ #
48
+ # is_a Media_Asset, :media_asset_id
49
+ #
50
+ # def self.before_create(args)
51
+ # args[:media_type] = 'movie'
52
+ # end
53
+ # end
54
+
55
+ class Document_Asset < Asset
56
+ table :document_asset, :public
57
+ primary_key :id, :document_asset_id_seq
58
+
59
+ is_a Asset, :asset_id
60
+
61
+ expects :doctype
62
+ aggregates Document_Asset_Info, :info_id
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,86 @@
1
+
2
+ require 'spec_env'
3
+ include Lore::Spec_Fixtures::Models
4
+
5
+ describe(Lore::Table_Accessor) do
6
+ before do
7
+ flush_test_data()
8
+ end
9
+
10
+ it "is assigned to a base table" do
11
+ Car.table_name.should == 'public.car'
12
+ Vehicle.table_name.should == 'public.vehicle'
13
+ end
14
+
15
+ it "loads attribute fields automatically as array of symbols" do
16
+ owner = Owner.create(:name => 'Filou')
17
+ manuf_org = Manufacturer.create(:name => 'Ford')
18
+ manuf_new = Manufacturer.create(:name => 'Ford')
19
+ v = Vehicle.create(:name => 'Ford Mondeo',
20
+ :num_seats => 100,
21
+ :maxspeed => 180,
22
+ :manuf_id => manuf_org.pkey,
23
+ :owner_id => owner.pkey)
24
+ v.manufacturer.should == manuf_org
25
+ end
26
+
27
+ it "allows setting entities for 1:1 relations" do
28
+ owner = Owner.create(:name => 'Filou')
29
+ manuf_org = Manufacturer.create(:name => 'Ford')
30
+ manuf_new = Manufacturer.create(:name => 'Ford')
31
+ motor = Motor.create(:motor_name => 'Ford V8', :kw => 120)
32
+ type = Car_Type.create(:type_name => 'Limousine')
33
+ v = Car.create(:name => 'Ford Mondeo',
34
+ :motor_id => motor.pkey,
35
+ :num_doors => 3,
36
+ :num_seats => 100,
37
+ :maxspeed => 180,
38
+ :car_type_id => type.pkey,
39
+ :manuf_id => manuf_org.pkey,
40
+ :owner_id => owner.pkey)
41
+ v.manufacturer.should == manuf_org
42
+ v.manufacturer = manuf_new
43
+
44
+ expected = { 'public.vehicle' => { :id => v.vehicle_id },
45
+ 'public.car' => { :id => v.id },
46
+ 'public.motorized' => { :id => v.motorized_id } }
47
+
48
+ v.get_primary_key_value_map.should_be expected
49
+ v.commit
50
+ v.manufacturer.should == manuf_new
51
+
52
+ v.set_manufacturer!(manuf_org)
53
+ v.manufacturer.should == manuf_org
54
+ end
55
+
56
+ it "provides 1:n associations" do
57
+ # TODO: Implement this
58
+ #
59
+ # garage = Garage.create()
60
+ # vehicle_1 = Vehicle.create()
61
+ # vehicle_2 = Vehicle.create()
62
+ # car_1 = Car.create()
63
+ # car_2 = Car.create()
64
+ #
65
+ # garage.add_vehicle(vehicle_1)
66
+ # garage.add_vehicle(car_1)
67
+ # garage.save
68
+ # expected = [ vehicle_1, car_1 ]
69
+ # garage.vehicle_set.should_be expected
70
+ #
71
+ # garage.vehicle_set = [ vehicle_2, car_2 ]
72
+ # garage.save
73
+ # expected = [ vehicle_2, car_2 ]
74
+ # garage.vehicle_set.should_be expected
75
+ #
76
+ # garage.vehicle_set.delete(car2)
77
+ # garage.save
78
+ # expected = [ vehicle_2 ]
79
+ # garage.vehicle_set.should_be expected
80
+ end
81
+
82
+ it "provides n:n associations" do
83
+
84
+ end
85
+
86
+ end