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.
- data/CHANGELOG +796 -664
- data/INSTALL +24 -24
- data/README +39 -32
- data/Rakefile +41 -42
- data/benchmark/bench.rb +36 -36
- data/doc/AUTHORS +15 -12
- data/doc/LICENSE +3 -3
- data/doc/RELEASES +311 -243
- data/doc/config.txt +1 -1
- data/examples/mysql_to_psql.rb +15 -15
- data/examples/run.rb +92 -92
- data/install.rb +7 -17
- data/lib/og.rb +76 -75
- data/lib/og/collection.rb +203 -160
- data/lib/og/entity.rb +168 -169
- data/lib/og/errors.rb +5 -5
- data/lib/og/manager.rb +179 -178
- data/lib/og/mixin/hierarchical.rb +107 -107
- data/lib/og/mixin/optimistic_locking.rb +36 -36
- data/lib/og/mixin/orderable.rb +148 -148
- data/lib/og/mixin/timestamped.rb +8 -8
- data/lib/og/mixin/tree.rb +124 -124
- data/lib/og/relation.rb +237 -213
- data/lib/og/relation/belongs_to.rb +5 -5
- data/lib/og/relation/has_many.rb +60 -58
- data/lib/og/relation/joins_many.rb +93 -47
- data/lib/og/relation/refers_to.rb +25 -21
- data/lib/og/store.rb +210 -207
- data/lib/og/store/filesys.rb +79 -79
- data/lib/og/store/kirby.rb +263 -258
- data/lib/og/store/memory.rb +261 -261
- data/lib/og/store/mysql.rb +288 -284
- data/lib/og/store/psql.rb +261 -244
- data/lib/og/store/sql.rb +873 -720
- data/lib/og/store/sqlite.rb +177 -175
- data/lib/og/store/sqlserver.rb +204 -214
- data/lib/og/types.rb +1 -1
- data/lib/og/validation.rb +57 -57
- data/lib/vendor/mysql.rb +376 -376
- data/lib/vendor/mysql411.rb +10 -10
- data/test/og/mixin/tc_hierarchical.rb +59 -59
- data/test/og/mixin/tc_optimistic_locking.rb +40 -40
- data/test/og/mixin/tc_orderable.rb +67 -67
- data/test/og/mixin/tc_timestamped.rb +19 -19
- data/test/og/store/tc_filesys.rb +46 -46
- data/test/og/tc_inheritance.rb +81 -81
- data/test/og/tc_join.rb +67 -0
- data/test/og/tc_polymorphic.rb +49 -49
- data/test/og/tc_relation.rb +57 -30
- data/test/og/tc_select.rb +49 -0
- data/test/og/tc_store.rb +345 -337
- data/test/og/tc_types.rb +11 -11
- metadata +11 -18
data/lib/og/collection.rb
CHANGED
@@ -6,171 +6,214 @@ module Og
|
|
6
6
|
|
7
7
|
class Collection
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
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
|
-
|
169
|
-
|
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
|
-
# *
|
219
|
+
# * Julien Perrot <jperrot@exosec.fr>
|
data/lib/og/entity.rb
CHANGED
@@ -6,180 +6,179 @@ module Og
|
|
6
6
|
|
7
7
|
module EntityMixin
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
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
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
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
|