og 0.20.0 → 0.21.0

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 (53) hide show
  1. data/CHANGELOG +796 -664
  2. data/INSTALL +24 -24
  3. data/README +39 -32
  4. data/Rakefile +41 -42
  5. data/benchmark/bench.rb +36 -36
  6. data/doc/AUTHORS +15 -12
  7. data/doc/LICENSE +3 -3
  8. data/doc/RELEASES +311 -243
  9. data/doc/config.txt +1 -1
  10. data/examples/mysql_to_psql.rb +15 -15
  11. data/examples/run.rb +92 -92
  12. data/install.rb +7 -17
  13. data/lib/og.rb +76 -75
  14. data/lib/og/collection.rb +203 -160
  15. data/lib/og/entity.rb +168 -169
  16. data/lib/og/errors.rb +5 -5
  17. data/lib/og/manager.rb +179 -178
  18. data/lib/og/mixin/hierarchical.rb +107 -107
  19. data/lib/og/mixin/optimistic_locking.rb +36 -36
  20. data/lib/og/mixin/orderable.rb +148 -148
  21. data/lib/og/mixin/timestamped.rb +8 -8
  22. data/lib/og/mixin/tree.rb +124 -124
  23. data/lib/og/relation.rb +237 -213
  24. data/lib/og/relation/belongs_to.rb +5 -5
  25. data/lib/og/relation/has_many.rb +60 -58
  26. data/lib/og/relation/joins_many.rb +93 -47
  27. data/lib/og/relation/refers_to.rb +25 -21
  28. data/lib/og/store.rb +210 -207
  29. data/lib/og/store/filesys.rb +79 -79
  30. data/lib/og/store/kirby.rb +263 -258
  31. data/lib/og/store/memory.rb +261 -261
  32. data/lib/og/store/mysql.rb +288 -284
  33. data/lib/og/store/psql.rb +261 -244
  34. data/lib/og/store/sql.rb +873 -720
  35. data/lib/og/store/sqlite.rb +177 -175
  36. data/lib/og/store/sqlserver.rb +204 -214
  37. data/lib/og/types.rb +1 -1
  38. data/lib/og/validation.rb +57 -57
  39. data/lib/vendor/mysql.rb +376 -376
  40. data/lib/vendor/mysql411.rb +10 -10
  41. data/test/og/mixin/tc_hierarchical.rb +59 -59
  42. data/test/og/mixin/tc_optimistic_locking.rb +40 -40
  43. data/test/og/mixin/tc_orderable.rb +67 -67
  44. data/test/og/mixin/tc_timestamped.rb +19 -19
  45. data/test/og/store/tc_filesys.rb +46 -46
  46. data/test/og/tc_inheritance.rb +81 -81
  47. data/test/og/tc_join.rb +67 -0
  48. data/test/og/tc_polymorphic.rb +49 -49
  49. data/test/og/tc_relation.rb +57 -30
  50. data/test/og/tc_select.rb +49 -0
  51. data/test/og/tc_store.rb +345 -337
  52. data/test/og/tc_types.rb +11 -11
  53. metadata +11 -18
@@ -6,171 +6,214 @@ module Og
6
6
 
7
7
  class Collection
8
8
 
9
- # The owner of this collection.
10
-
11
- attr_accessor :owner
12
-
13
- # The members of this collection. Keeps the objects
14
- # that belong to this collection.
15
-
16
- attr_accessor :members
17
-
18
- # A method used to add insert objects in the collection.
19
-
20
- attr_accessor :insert_proc
21
-
22
- # A method used to remove objects from the collection.
23
-
24
- attr_accessor :remove_proc
25
-
26
- # A method used to find the objects that belong to the
27
- # collection.
28
-
29
- attr_accessor :find_proc
30
-
31
- # The default find options.
32
-
33
- attr_accessor :find_options
34
-
35
- # Is the collection in build mode?
36
-
37
- attr_accessor :building
38
-
39
- # Is the collection loaded?
40
-
41
- attr_accessor :loaded
42
-
43
- # Initialize the collection.
44
-
45
- def initialize(owner = nil, insert_proc = nil, remove_proc = nil, find_proc = nil, find_options = {})
46
- @owner = owner
47
- @insert_proc = insert_proc
48
- @remove_proc = remove_proc
49
- @find_proc = find_proc
50
- @find_options = find_options
51
- @members = []
52
- @loaded = false
53
- @building = false
54
- end
55
-
56
- # Load the members of the collection.
57
-
58
- def load_members
59
- unless @loaded
60
- @members = @owner.send(@find_proc, @find_options)
61
- @loaded = true
62
- end
63
- @members
64
- end
65
-
66
- # Reload the collection.
67
-
68
- def reload(options)
69
- # gmosx, NOOO: this was a bug! it corrupts the default options.
70
- # @find_options = options
71
- @members = @owner.send(@find_proc, options)
72
- end
73
-
74
- # Convert the collection to an array.
75
-
76
- def to_ary
77
- load_members
78
- @members
79
- end
80
-
81
- # Defined to avoid the method missing overhead.
82
-
83
- def each(&block)
84
- load_members
85
- @members.each(&block)
86
- end
87
-
88
- # Defined to avoid the method missing overhead.
89
-
90
- def [](idx)
91
- load_members
92
- @members[idx]
93
- end
94
-
95
- # Add a new member to the collection.
96
-
97
- def push(obj)
98
- @members.push(obj)
99
- unless @building or owner.unsaved?
100
- @owner.send(@insert_proc, obj)
101
- end
102
- end
103
- alias_method :<<, :push
104
- alias_method :add, :push
105
-
106
- # Remove a member from the collection, the actual object
107
- # is not deleted.
108
-
109
- def remove(*objects)
110
- objects = objects.flatten
111
-
112
- objects.reject! { |obj| @members.delete(obj) if obj.unsaved? }
113
- return if objects.empty?
114
-
115
- @owner.transaction do
116
- objects.each do |obj|
117
- @owner.send(@remove_proc, obj)
118
- @members.delete(obj)
119
- end
120
- end
121
- end
122
-
123
- # Delete a member from the collection AND the store.
124
-
125
- def delete(*objects)
126
- objects = objects.flatten
127
-
128
- objects.reject! { |obj| @members.delete(obj) if obj.unsaved? }
129
- return if objects.empty?
130
-
131
- @owner.transaction do
132
- objects.each do |obj|
133
- obj.delete
134
- @members.delete(obj)
135
- end
136
- end
137
- end
138
-
139
- # Remove all members from the collection.
140
-
141
- def remove_all
142
- @owner.transaction do
143
- @members.each { |obj| @owner.send(@remove_proc, obj) }
144
- end
145
- @members.clear
146
- end
147
- alias_method :clear, :remove_all
148
-
149
- # Delete all members of the collection. Also delete from the
150
- # store.
151
-
152
- def delete_all
153
- @owner.transaction do
154
- @members.each { |obj| obj.delete }
155
- end
156
- @members.clear
157
- end
158
-
159
- # Redirect all other methods to the members array.
160
-
161
- def method_missing(symbol, *args, &block)
162
- load_members
163
- @members.send(symbol, *args, &block)
164
- end
9
+ # The owner of this collection.
10
+
11
+ attr_accessor :owner
12
+
13
+ # The members of this collection. Keeps the objects
14
+ # that belong to this collection.
15
+
16
+ attr_accessor :members
17
+
18
+ # A method used to add insert objects in the collection.
19
+
20
+ attr_accessor :insert_proc
21
+
22
+ # A method used to remove objects from the collection.
23
+
24
+ attr_accessor :remove_proc
25
+
26
+ # A method used to find the objects that belong to the
27
+ # collection.
28
+
29
+ attr_accessor :find_proc
30
+
31
+ # A method used to count the objects that belong to the
32
+ # collection.
33
+
34
+ attr_accessor :count_proc
35
+
36
+ # The default find options.
37
+
38
+ attr_accessor :find_options
39
+
40
+ # Is the collection in build mode?
41
+
42
+ attr_accessor :building
43
+
44
+ # Is the collection loaded?
45
+
46
+ attr_accessor :loaded
47
+
48
+ # Initialize the collection.
49
+
50
+ def initialize(owner = nil, insert_proc = nil,
51
+ remove_proc = nil, find_proc = nil,
52
+ count_proc = nil, find_options = {})
53
+ @owner = owner
54
+ @insert_proc = insert_proc
55
+ @remove_proc = remove_proc
56
+ @find_proc = find_proc
57
+ @count_proc = count_proc
58
+ @find_options = find_options
59
+ @members = []
60
+ @loaded = false
61
+ @building = false
62
+ end
63
+
64
+ # Load the members of the collection.
65
+
66
+ def load_members
67
+ unless @loaded
68
+ @members = @owner.send(@find_proc, @find_options)
69
+ @loaded = true
70
+ end
71
+ @members
72
+ end
73
+
74
+ # Reload the collection.
75
+
76
+ def reload(options)
77
+ # gmosx, NOOO: this was a bug! it corrupts the default options.
78
+ # @find_options = options
79
+ @members = @owner.send(@find_proc, options)
80
+ end
81
+
82
+ # Unload the members (clear the cache).
83
+
84
+ def unload
85
+ @members.clear
86
+ @loaded = false
87
+ end
88
+
89
+ # Convert the collection to an array.
90
+
91
+ def to_ary
92
+ load_members
93
+ @members
94
+ end
95
+
96
+ # Defined to avoid the method missing overhead.
97
+
98
+ def each(&block)
99
+ load_members
100
+ @members.each(&block)
101
+ end
102
+
103
+ # Defined to avoid the method missing overhead.
104
+
105
+ def [](idx)
106
+ load_members
107
+ @members[idx]
108
+ end
109
+
110
+ # Add a new member to the collection.
111
+
112
+ def push(obj, options = nil)
113
+ @members.push(obj)
114
+ unless @building or owner.unsaved?
115
+ @owner.send(@insert_proc, obj, options)
116
+ end
117
+ end
118
+ alias_method :<<, :push
119
+ alias_method :add, :push
120
+
121
+ # Remove a member from the collection, the actual object
122
+ # is not deleted.
123
+
124
+ def remove(*objects)
125
+ objects = objects.flatten
126
+
127
+ objects.reject! { |obj| @members.delete(obj) if obj.unsaved? }
128
+ return if objects.empty?
129
+
130
+ @owner.transaction do
131
+ objects.each do |obj|
132
+ @owner.send(@remove_proc, obj)
133
+ @members.delete(obj)
134
+ end
135
+ end
136
+ end
137
+
138
+ # Delete a member from the collection AND the store.
139
+
140
+ def delete(*objects)
141
+ objects = objects.flatten
142
+
143
+ objects.reject! { |obj| @members.delete(obj) if obj.unsaved? }
144
+ return if objects.empty?
145
+
146
+ @owner.transaction do
147
+ objects.each do |obj|
148
+ obj.delete
149
+ @members.delete(obj)
150
+ end
151
+ end
152
+ end
153
+
154
+ # Delete a member from the collection AND the store, if the
155
+ # condition block evaluates to true.
156
+
157
+ def delete_if(&block)
158
+ objects = @members.select(&block)
159
+
160
+ objects.reject! { |obj| @members.delete(obj) if obj.unsaved? }
161
+ return if objects.empty?
162
+
163
+ @owner.transaction do
164
+ objects.each do |obj|
165
+ obj.delete
166
+ @members.delete(obj)
167
+ end
168
+ end
169
+ end
170
+
171
+ # Remove all members from the collection.
172
+
173
+ def remove_all
174
+ @owner.transaction do
175
+ @members.each { |obj| @owner.send(@remove_proc, obj) }
176
+ end
177
+ @members.clear
178
+ end
179
+ alias_method :clear, :remove_all
180
+
181
+ # Delete all members of the collection. Also delete from the
182
+ # store.
183
+
184
+ def delete_all
185
+ @owner.transaction do
186
+ @members.each { |obj| obj.delete }
187
+ end
188
+ @members.clear
189
+ end
190
+
191
+ # Return the size of a collection.
192
+
193
+ def size(reload = false)
194
+ if @loaded and !reload
195
+ return @members.size
196
+ else
197
+ return @owner.send(@count_proc)
198
+ end
199
+ end
200
+ alias_method :count, :size
201
+
202
+ # Redirect all other methods to the members array.
203
+
204
+ def method_missing(symbol, *args, &block)
205
+ load_members
206
+ @members.send(symbol, *args, &block)
207
+ end
165
208
 
166
209
  private
167
210
 
168
- def check_type(obj)
169
- end
170
-
211
+ def check_type(obj)
212
+ end
213
+
171
214
  end
172
215
 
173
216
  end
174
217
 
175
218
  # * George Moschovitis <gm@navel.gr>
176
- # * Julien Perrot <jperrot@exosec.fr>
219
+ # * Julien Perrot <jperrot@exosec.fr>
@@ -6,180 +6,179 @@ module Og
6
6
 
7
7
  module EntityMixin
8
8
 
9
- def self.append_features(base)
10
- super
11
-
12
- base.extend(ClassMethods)
13
-
14
- base.module_eval <<-end_eval, __FILE__, __LINE__
15
- def save(options = nil)
16
- self.class.ogmanager.store.save(self, options)
17
- # return self
18
- end
19
- alias_method :save!, :save
20
-
21
- def insert
22
- self.class.ogmanager.store.insert(self)
23
- return self
24
- end
25
-
26
- def update(options = nil)
27
- self.class.ogmanager.store.update(self, options)
28
- end
29
-
30
- def update_properties(set)
31
- self.class.ogmanager.store.update_properties(self, set)
32
- end
33
-
34
- # Reload this entity instance from the store.
35
-
36
- def reload
37
- self.class.ogmanager.store.reload(self, self.pk)
38
- end
39
- alias_method :reload!, :reload
40
-
41
- # Delete this entity instance from the store.
42
-
43
- def delete
44
- self.class.ogmanager.store.delete(self)
45
- end
46
- alias_method :delete!, :delete
47
-
48
- def transaction(&block)
49
- self.class.ogmanager.store.transaction(&block)
50
- end
51
- end_eval
52
-
53
- base.send(:include, RelationMacros)
54
- end
55
-
56
- module ClassMethods
57
- def create(*args)
58
- obj = self.new(*args)
59
- yield(obj) if block_given?
60
- ogmanager.store.save(obj)
61
- return obj
62
- end
63
-
64
- # Load an instance of this Entity class using the primary
65
- # key.
66
-
67
- def load(pk)
68
- ogmanager.store.load(pk, self)
69
- end
70
- alias_method :[], :load
71
- alias_method :exist?, :load
72
-
73
- def update_properties(set, options = nil)
74
- ogmanager.store.update_properties(self, set, options)
75
- end
76
- alias_method :pupdate, :update_properties
77
- alias_method :update_property, :update_properties
78
- alias_method :batch_update, :update_properties
79
-
80
- def find(options = {})
81
- # gmosx, FIXME: this code seems too complex,
82
- # improve this!
83
-
84
- if find_options = self.__meta[:find_options]
85
- options = find_options.first.dup.update(options)
86
- end
87
- options[:class] = self
88
- if self.metadata.superclass
89
- options[:type] = self
90
- end
91
- ogmanager.store.find(options)
92
- end
93
- alias_method :all, :find
94
-
95
- def find_one(options = {})
96
- options[:class] = self
97
- ogmanager.store.find_one(options)
98
- end
99
- alias_method :one, :find_one
100
- alias_method :first, :find_one
101
-
102
- def select(sql)
103
- ogmanager.store.select(sql, self)
104
- end
105
-
106
- def select_one(sql)
107
- ogmanager.store.select_one(sql, self)
108
- end
109
-
110
- def count(options = {})
111
- options[:class] = self
112
- ogmanager.store.count(options)
113
- end
114
-
115
- # Delete an instance of this Entity class using the actual
116
- # instance or the primary key.
117
-
118
- def delete(obj_or_pk)
119
- ogmanager.store.delete(obj_or_pk, self)
120
- end
121
- alias_method :delete!, :delete
122
-
123
- def transaction(&block)
124
- ogmanager.store.transaction(&block)
125
- end
126
-
127
- def primary_key
128
- unless @__meta and @__meta[:primary_key]
129
- self.meta :primary_key, Entity.resolve_primary_key(self)
130
- end
131
- @__meta[:primary_key].flatten
132
- end
133
-
134
- # Set the default find options for this entity.
135
-
136
- def find_options(options)
137
- meta :find_options, options
138
- end
139
-
140
- # Set the default order option for this entity.
141
-
142
- def order(order_str)
143
- meta :find_options, :order => order_str
144
- end
145
-
146
- # Enable schema inheritance for this Entity class.
147
- # The Single Table Inheritance pattern is used.
148
-
149
- def schema_inheritance
150
- meta :schema_inheritance
151
- end
152
-
153
- # Is this entity a polymorphic parent?
154
-
155
- def polymorphic_parent?
156
- self.to_s == self.metadata.polymorphic.to_s
157
- end
158
-
159
- # :nodoc:
160
- # Used internally to fix the forward reference problem.
161
-
162
- def const_missing(sym)
163
- return sym
164
- end
165
- end
9
+ def self.append_features(base)
10
+ super
11
+
12
+ base.extend(ClassMethods)
13
+
14
+ base.module_eval <<-end_eval, __FILE__, __LINE__
15
+ def save(options = nil)
16
+ self.class.ogmanager.store.save(self, options)
17
+ # return self
18
+ end
19
+ alias_method :save!, :save
20
+
21
+ def insert
22
+ self.class.ogmanager.store.insert(self)
23
+ return self
24
+ end
25
+
26
+ def update(options = nil)
27
+ self.class.ogmanager.store.update(self, options)
28
+ end
29
+
30
+ def update_properties(set)
31
+ self.class.ogmanager.store.update_properties(self, set)
32
+ end
33
+
34
+ # Reload this entity instance from the store.
35
+
36
+ def reload
37
+ self.class.ogmanager.store.reload(self, self.pk)
38
+ end
39
+ alias_method :reload!, :reload
40
+
41
+ # Delete this entity instance from the store.
42
+
43
+ def delete
44
+ self.class.ogmanager.store.delete(self)
45
+ end
46
+ alias_method :delete!, :delete
47
+
48
+ def transaction(&block)
49
+ self.class.ogmanager.store.transaction(&block)
50
+ end
51
+ end_eval
52
+
53
+ base.send(:include, RelationMacros)
54
+ end
55
+
56
+ module ClassMethods
57
+ def create(*args)
58
+ obj = self.new(*args)
59
+ yield(obj) if block_given?
60
+ ogmanager.store.save(obj)
61
+ return obj
62
+ end
63
+
64
+ # Load an instance of this Entity class using the primary
65
+ # key.
66
+
67
+ def load(pk)
68
+ ogmanager.store.load(pk, self)
69
+ end
70
+ alias_method :[], :load
71
+ alias_method :exist?, :load
72
+
73
+ def update_properties(set, options = nil)
74
+ ogmanager.store.update_properties(self, set, options)
75
+ end
76
+ alias_method :pupdate, :update_properties
77
+ alias_method :update_property, :update_properties
78
+ alias_method :batch_update, :update_properties
79
+
80
+ def find(options = {})
81
+ # gmosx, FIXME: this code seems too complex,
82
+ # improve this!
83
+
84
+ if find_options = self.__meta[:find_options]
85
+ options = find_options.first.dup.update(options)
86
+ end
87
+ options[:class] = self
88
+ if self.metadata.superclass
89
+ options[:type] = self
90
+ end
91
+ ogmanager.store.find(options)
92
+ end
93
+ alias_method :all, :find
94
+
95
+ def find_one(options = {})
96
+ options[:class] = self
97
+ ogmanager.store.find_one(options)
98
+ end
99
+ alias_method :one, :find_one
100
+ alias_method :first, :find_one
101
+
102
+ def select(sql)
103
+ ogmanager.store.select(sql, self)
104
+ end
105
+
106
+ def select_one(sql)
107
+ ogmanager.store.select_one(sql, self)
108
+ end
109
+
110
+ def count(options = {})
111
+ options[:class] = self
112
+ ogmanager.store.count(options)
113
+ end
114
+
115
+ # Delete an instance of this Entity class using the actual
116
+ # instance or the primary key.
117
+
118
+ def delete(obj_or_pk)
119
+ ogmanager.store.delete(obj_or_pk, self)
120
+ end
121
+ alias_method :delete!, :delete
122
+
123
+ def transaction(&block)
124
+ ogmanager.store.transaction(&block)
125
+ end
126
+
127
+ def primary_key
128
+ unless @__meta and @__meta[:primary_key]
129
+ self.meta :primary_key, Entity.resolve_primary_key(self)
130
+ end
131
+ @__meta[:primary_key].flatten
132
+ end
133
+
134
+ # Set the default find options for this entity.
135
+
136
+ def find_options(options)
137
+ meta :find_options, options
138
+ end
139
+
140
+ # Set the default order option for this entity.
141
+
142
+ def order(order_str)
143
+ meta :find_options, :order => order_str
144
+ end
145
+
146
+ # Enable schema inheritance for this Entity class.
147
+ # The Single Table Inheritance pattern is used.
148
+
149
+ def schema_inheritance
150
+ meta :schema_inheritance
151
+ end
152
+
153
+ # Is this entity a polymorphic parent?
154
+
155
+ def polymorphic_parent?
156
+ self.to_s == self.metadata.polymorphic.to_s
157
+ end
158
+
159
+ # Used internally to fix the forward reference problem.
160
+
161
+ def const_missing(sym) # :nodoc: all
162
+ return sym
163
+ end
164
+ end
166
165
  end
167
166
 
168
167
  # A helper class.
169
168
 
170
169
  class Entity
171
- class << self
172
- def resolve_primary_key(klass)
173
- for p in klass.properties
174
- if p.meta[:primary_key]
175
- return p.symbol, p.klass
176
- end
177
- end
178
- return :oid, Fixnum
179
- end
180
- end
181
-
182
- include EntityMixin
170
+ class << self
171
+ def resolve_primary_key(klass)
172
+ for p in klass.properties
173
+ if p.meta[:primary_key]
174
+ return p.symbol, p.klass
175
+ end
176
+ end
177
+ return :oid, Fixnum
178
+ end
179
+ end
180
+
181
+ include EntityMixin
183
182
  end
184
183
 
185
184
  end