og 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
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