og 0.31.0 → 0.40.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/doc/{AUTHORS → CONTRIBUTORS} +26 -10
- data/doc/LICENSE +2 -3
- data/doc/RELEASES +56 -7
- data/doc/tutorial.txt +15 -15
- data/lib/glue/cacheable.rb +2 -5
- data/lib/glue/hierarchical.rb +1 -4
- data/lib/glue/optimistic_locking.rb +0 -2
- data/lib/glue/orderable.rb +79 -75
- data/lib/glue/revisable.rb +19 -24
- data/lib/glue/searchable.rb +0 -2
- data/lib/glue/taggable.rb +31 -29
- data/lib/glue/timestamped.rb +4 -2
- data/lib/og.rb +50 -29
- data/lib/og/adapter.rb +19 -0
- data/lib/og/adapter/mysql.rb +212 -0
- data/lib/og/adapter/mysql/override.rb +34 -0
- data/lib/og/adapter/mysql/script.rb +15 -0
- data/lib/og/adapter/mysql/utils.rb +40 -0
- data/lib/og/adapter/postgresql.rb +231 -0
- data/lib/og/adapter/postgresql/override.rb +117 -0
- data/lib/og/adapter/postgresql/script.rb +15 -0
- data/lib/og/adapter/postgresql/utils.rb +35 -0
- data/lib/og/adapter/sqlite.rb +132 -0
- data/lib/og/adapter/sqlite/override.rb +33 -0
- data/lib/og/adapter/sqlite/script.rb +15 -0
- data/lib/og/collection.rb +35 -7
- data/lib/og/{evolution.rb → dump.rb} +4 -5
- data/lib/og/entity.rb +102 -173
- data/lib/og/entity/clone.rb +119 -0
- data/lib/og/errors.rb +0 -2
- data/lib/og/manager.rb +85 -37
- data/lib/og/relation.rb +52 -34
- data/lib/og/relation/belongs_to.rb +0 -2
- data/lib/og/relation/has_many.rb +27 -4
- data/lib/og/relation/joins_many.rb +41 -14
- data/lib/og/relation/many_to_many.rb +10 -0
- data/lib/og/relation/refers_to.rb +22 -5
- data/lib/og/store.rb +80 -86
- data/lib/og/store/sql.rb +710 -713
- data/lib/og/store/sql/evolution.rb +119 -0
- data/lib/og/store/sql/join.rb +155 -0
- data/lib/og/store/sql/utils.rb +149 -0
- data/lib/og/test/assertions.rb +1 -3
- data/lib/og/test/testcase.rb +0 -2
- data/lib/og/types.rb +2 -5
- data/lib/og/validation.rb +6 -9
- data/test/{og/mixin → glue}/tc_hierarchical.rb +3 -13
- data/test/glue/tc_og_paginate.rb +47 -0
- data/test/{og/mixin → glue}/tc_optimistic_locking.rb +2 -12
- data/test/{og/mixin → glue}/tc_orderable.rb +15 -23
- data/test/glue/tc_orderable2.rb +47 -0
- data/test/glue/tc_revisable.rb +3 -3
- data/test/{og/mixin → glue}/tc_taggable.rb +20 -10
- data/test/{og/mixin → glue}/tc_timestamped.rb +2 -12
- data/test/glue/tc_webfile.rb +36 -0
- data/test/og/CONFIG.rb +8 -11
- data/test/og/multi_validations_model.rb +14 -0
- data/test/og/store/tc_filesys.rb +3 -1
- data/test/og/store/tc_kirby.rb +16 -13
- data/test/og/store/tc_sti.rb +11 -11
- data/test/og/store/tc_sti2.rb +79 -0
- data/test/og/tc_build.rb +41 -0
- data/test/og/tc_cacheable.rb +3 -2
- data/test/og/tc_has_many.rb +96 -0
- data/test/og/tc_inheritance.rb +6 -4
- data/test/og/tc_joins_many.rb +93 -0
- data/test/og/tc_multi_validations.rb +5 -7
- data/test/og/tc_multiple.rb +7 -6
- data/test/og/tc_override.rb +13 -7
- data/test/og/tc_primary_key.rb +30 -0
- data/test/og/tc_relation.rb +8 -14
- data/test/og/tc_reldelete.rb +163 -0
- data/test/og/tc_reverse.rb +17 -14
- data/test/og/tc_scoped.rb +3 -11
- data/test/og/tc_setup.rb +13 -11
- data/test/og/tc_store.rb +21 -28
- data/test/og/tc_validation2.rb +2 -2
- data/test/og/tc_validation_loop.rb +17 -15
- metadata +109 -103
- data/INSTALL +0 -91
- data/ProjectInfo +0 -51
- data/README +0 -177
- data/doc/config.txt +0 -28
- data/examples/README +0 -23
- data/examples/mysql_to_psql.rb +0 -71
- data/examples/run.rb +0 -271
- data/lib/glue/tree.rb +0 -218
- data/lib/og/store/alpha/filesys.rb +0 -110
- data/lib/og/store/alpha/memory.rb +0 -295
- data/lib/og/store/alpha/sqlserver.rb +0 -256
- data/lib/og/store/kirby.rb +0 -490
- data/lib/og/store/mysql.rb +0 -415
- data/lib/og/store/psql.rb +0 -875
- data/lib/og/store/sqlite.rb +0 -348
- data/lib/og/store/sqlite2.rb +0 -241
- data/setup.rb +0 -1585
- data/test/og/tc_sti_find.rb +0 -35
data/lib/glue/tree.rb
DELETED
@@ -1,218 +0,0 @@
|
|
1
|
-
# NOT WORKING YET !!!
|
2
|
-
|
3
|
-
raise 'This is not working yet, do not require this file.'
|
4
|
-
|
5
|
-
# A useful encapsulation of the nested intervals pattern for
|
6
|
-
# hierarchical SQL queries. Slightly adapted from the original
|
7
|
-
# article (http://www.dbazine.com/tropashko4.shtml)
|
8
|
-
|
9
|
-
module TreeTraversal
|
10
|
-
|
11
|
-
# The default prefix for the tree traversal helpers.
|
12
|
-
|
13
|
-
cattr_accessor :prefix, 'tree'
|
14
|
-
|
15
|
-
def self.child(sum, n)
|
16
|
-
power = 2 ** n
|
17
|
-
return sum * power
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
__END__
|
23
|
-
|
24
|
-
def xcoord(numer, denom)
|
25
|
-
num = numer + 1
|
26
|
-
den = denom * 2
|
27
|
-
|
28
|
-
while (num / 2).floor == (num / 2)
|
29
|
-
num /= 2
|
30
|
-
den /= 2
|
31
|
-
end
|
32
|
-
|
33
|
-
return num, den
|
34
|
-
end
|
35
|
-
|
36
|
-
#--
|
37
|
-
# TODO: optimize this
|
38
|
-
#++
|
39
|
-
|
40
|
-
def ycoord(numer, denom)
|
41
|
-
num, den = xcoord(numer, denom)
|
42
|
-
|
43
|
-
while den < denom
|
44
|
-
num *= 2
|
45
|
-
den *= 2
|
46
|
-
end
|
47
|
-
|
48
|
-
num = numer - num
|
49
|
-
|
50
|
-
while (num / 2).floor == (num / 2)
|
51
|
-
num /= 2
|
52
|
-
den /= 2
|
53
|
-
end
|
54
|
-
|
55
|
-
return num, den
|
56
|
-
end
|
57
|
-
|
58
|
-
def parent(numer, denom)
|
59
|
-
return nil if numer == 3
|
60
|
-
|
61
|
-
num = (numer - 1) / 2
|
62
|
-
den = denom / 2
|
63
|
-
|
64
|
-
while ((num-1)/4).floor == ((num-1)/4)
|
65
|
-
num = (num + 1) / 2
|
66
|
-
den = den / 2
|
67
|
-
end
|
68
|
-
|
69
|
-
return num, den
|
70
|
-
end
|
71
|
-
|
72
|
-
def sibling(numer, denom)
|
73
|
-
return nil if numer == 3
|
74
|
-
|
75
|
-
num = (numer - 1) / 2
|
76
|
-
den = denom / 2
|
77
|
-
sib = 1
|
78
|
-
|
79
|
-
while ((num-1)/4).floor == ((num-1)/4)
|
80
|
-
return sib if num == 1 and den == 1
|
81
|
-
num = (num + 1) / 2
|
82
|
-
den /= 2
|
83
|
-
sib += 1
|
84
|
-
end
|
85
|
-
|
86
|
-
return sib
|
87
|
-
end
|
88
|
-
|
89
|
-
def child(numer, denom, n)
|
90
|
-
power = 2 ** n
|
91
|
-
|
92
|
-
num = (numer * power) + 3 - power
|
93
|
-
den = denom * power
|
94
|
-
|
95
|
-
return num, den
|
96
|
-
end
|
97
|
-
|
98
|
-
def path(numer, denom)
|
99
|
-
return '' if numer == nil
|
100
|
-
n, d = parent(numer, denom)
|
101
|
-
return "#{path(n, d)}.#{sibling(numer, denom)}"
|
102
|
-
end
|
103
|
-
|
104
|
-
def encode(path)
|
105
|
-
num = den = 1
|
106
|
-
postfix = ".#{path}."
|
107
|
-
|
108
|
-
while postfix.length > 1
|
109
|
-
sibling, postfix = postfix.split('.', 2)
|
110
|
-
num, den = child(num, den, sibling.to_i)
|
111
|
-
end
|
112
|
-
|
113
|
-
return num, den
|
114
|
-
end
|
115
|
-
|
116
|
-
|
117
|
-
require 'og'
|
118
|
-
|
119
|
-
class Comment
|
120
|
-
property :path, String
|
121
|
-
property :x, :y, Float
|
122
|
-
|
123
|
-
def initialize(path = nil, x = nil, y = nil)
|
124
|
-
@path, @x, @y = path, x, y
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
Og::Database.new(
|
129
|
-
:database => 'test',
|
130
|
-
:adapter => 'psql',
|
131
|
-
:user => 'postgres',
|
132
|
-
:password => 'navelrulez',
|
133
|
-
:connection_count => 1,
|
134
|
-
:drop => true
|
135
|
-
)
|
136
|
-
|
137
|
-
def dp(path)
|
138
|
-
n, d = encode(path)
|
139
|
-
n, d = Float(n), Float(d)
|
140
|
-
# puts "#{path} -> n: #{n} d: #{d} c: #{n/d}"
|
141
|
-
p = path(n, d)
|
142
|
-
# puts "=== #{p}"
|
143
|
-
xn, xd = xcoord(n, d)
|
144
|
-
yn, yd = ycoord(n, d)
|
145
|
-
Comment.create(path, xn/xd, yn/yd)
|
146
|
-
end
|
147
|
-
|
148
|
-
dp '1.1'
|
149
|
-
dp '1.2'
|
150
|
-
dp '1.3'
|
151
|
-
dp '1.1.2.1'
|
152
|
-
dp '1.5.2.1'
|
153
|
-
dp '1.2.1.1.1'
|
154
|
-
dp '1.4.1.1'
|
155
|
-
dp '1.4.3'
|
156
|
-
dp '1.4.1'
|
157
|
-
dp '1.2.1'
|
158
|
-
dp '1.2.1.2'
|
159
|
-
dp '1.5'
|
160
|
-
dp '1.5.1'
|
161
|
-
|
162
|
-
for c in Comment.all('ORDER BY x DESC, y ASC')
|
163
|
-
puts "#{c.path.ljust(16)}#{c.inspect}"
|
164
|
-
end
|
165
|
-
|
166
|
-
class Article
|
167
|
-
property :title, :body, String
|
168
|
-
has_many: :comments, Comment, :tree => true
|
169
|
-
end
|
170
|
-
|
171
|
-
class Comment
|
172
|
-
property :body, String
|
173
|
-
belongs_to :article, Article
|
174
|
-
belongs_to :parent, Comment
|
175
|
-
has_many :children, Comment, :tree => true
|
176
|
-
has_many :roles, Role, :list => true
|
177
|
-
end
|
178
|
-
|
179
|
-
|
180
|
-
article.comments_tree
|
181
|
-
comment.add_child(Comment.new('hello'))
|
182
|
-
comment.children_tree
|
183
|
-
comment.children
|
184
|
-
|
185
|
-
if options[:tree]
|
186
|
-
code << %{
|
187
|
-
property :#{prefix}_x, Fixnum
|
188
|
-
property :#{prefix}_y, Fixnum
|
189
|
-
sql_index '#{prefix}_x, #{prefix}_y'
|
190
|
-
}
|
191
|
-
end
|
192
|
-
|
193
|
-
if options[:tree]
|
194
|
-
|
195
|
-
code << %{
|
196
|
-
def #{name}_tree(extrasql = nil)
|
197
|
-
Og.db.select("SELECT * FROM #{Og::Adapter.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\} ORDER BY #{prefix}_x DESC, #{prefix}_y ASC", #{klass})
|
198
|
-
end
|
199
|
-
}
|
200
|
-
|
201
|
-
elsif options[:list]
|
202
|
-
|
203
|
-
else
|
204
|
-
|
205
|
-
end
|
206
|
-
|
207
|
-
}
|
208
|
-
|
209
|
-
if options[:tree]
|
210
|
-
code << %{
|
211
|
-
n = Og.db.count("#{linkback}=\#\@oid", #{klass})
|
212
|
-
ptx = @#{prefix}_x || 0
|
213
|
-
pty = @#{prefix}_y || 0
|
214
|
-
obj.#{prefix}_x, obj.#{prefix}_y = TreeTraversal.child(ptx + pty, n)
|
215
|
-
}
|
216
|
-
end
|
217
|
-
|
218
|
-
code << %{
|
@@ -1,110 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
require 'og/store'
|
5
|
-
|
6
|
-
module Og
|
7
|
-
|
8
|
-
# A Store that saves the object on the Filesystem.
|
9
|
-
# An extension of the Memory store.
|
10
|
-
|
11
|
-
class FilesysStore < Store
|
12
|
-
|
13
|
-
# :section: Store methods.
|
14
|
-
|
15
|
-
def self.dir(name)
|
16
|
-
"#{name}_db"
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.create(options)
|
20
|
-
name = dir(options[:name])
|
21
|
-
FileUtils.mkdir_p(name)
|
22
|
-
rescue
|
23
|
-
Logger.error "Cannot create '#{name}'"
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.destroy(options)
|
27
|
-
name = dir(options[:name])
|
28
|
-
FileUtils.rm_rf(name)
|
29
|
-
rescue
|
30
|
-
Logger.error "Cannot destroy '#{name}'"
|
31
|
-
end
|
32
|
-
|
33
|
-
# Initialize a connection to this store.
|
34
|
-
|
35
|
-
def initialize(options)
|
36
|
-
super
|
37
|
-
|
38
|
-
@base_dir = self.class.dir(options[:name])
|
39
|
-
|
40
|
-
unless File.directory?(@base_dir)
|
41
|
-
Logger.info "Database '#{options[:name]}' not found!"
|
42
|
-
self.class.create(options)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def enchant(klass, manager)
|
47
|
-
super
|
48
|
-
|
49
|
-
klass.const_set 'OGNAME', klass.to_s.gsub(/::/, "/").downcase
|
50
|
-
klass.property :oid, Fixnum
|
51
|
-
|
52
|
-
FileUtils.mkdir_p(path(klass))
|
53
|
-
File.open(spath(klass), 'w') { |f| f << '1' }
|
54
|
-
rescue => ex
|
55
|
-
Logger.error "Cannot create directory to store '#{klass}' classes!"
|
56
|
-
end
|
57
|
-
|
58
|
-
# :section: Lifecycle methods.
|
59
|
-
|
60
|
-
def load(oid, klass)
|
61
|
-
obj = nil
|
62
|
-
File.open(path(klass, oid), 'r') { |f| obj = YAML::load(f.read) }
|
63
|
-
return obj
|
64
|
-
rescue
|
65
|
-
return nil
|
66
|
-
end
|
67
|
-
|
68
|
-
def reload(obj)
|
69
|
-
end
|
70
|
-
|
71
|
-
def save(obj)
|
72
|
-
seq = nil
|
73
|
-
File.open(spath(obj.class), 'r') { |f| seq = f.read.to_i }
|
74
|
-
obj.oid = seq
|
75
|
-
File.open(path(obj.class, obj.oid), 'w') { |f| f << obj.to_yaml }
|
76
|
-
seq += 1
|
77
|
-
File.open(spath(obj.class), 'w') { |f| f << seq }
|
78
|
-
end
|
79
|
-
|
80
|
-
def delete(obj_or_pk, klass = nil, cascade = true)
|
81
|
-
pk = obj_or_pk.is_a?(Fixnum) ? obj_or_pk : obj_or_pk.oid
|
82
|
-
klass ||= obj_or_pk.class
|
83
|
-
FileUtils.rm(path(klass, pk))
|
84
|
-
end
|
85
|
-
|
86
|
-
def find
|
87
|
-
end
|
88
|
-
|
89
|
-
def count
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
# Path helper.
|
95
|
-
|
96
|
-
def path(klass, pk = nil)
|
97
|
-
class_dir = File.join(@base_dir, klass::OGNAME)
|
98
|
-
pk ? File.join(class_dir, "#{pk}.yml") : class_dir
|
99
|
-
end
|
100
|
-
|
101
|
-
# Path to sequence helper.
|
102
|
-
|
103
|
-
def spath(klass)
|
104
|
-
File.join(path(klass), 'seq')
|
105
|
-
end
|
106
|
-
|
107
|
-
end
|
108
|
-
|
109
|
-
end
|
110
|
-
|
@@ -1,295 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
module Og
|
5
|
-
|
6
|
-
# A collection of utilities. Mainly to stay compatible with the
|
7
|
-
# SQL based backends.
|
8
|
-
#
|
9
|
-
# WARNING: This store does not yet support all Og features.
|
10
|
-
|
11
|
-
module MemoryUtils
|
12
|
-
|
13
|
-
# FIXME: find a neutral name.
|
14
|
-
|
15
|
-
def table(klass)
|
16
|
-
klass.to_s
|
17
|
-
end
|
18
|
-
|
19
|
-
# FIXME: find a neutral name.
|
20
|
-
|
21
|
-
def join_table(class1, class2, postfix = nil)
|
22
|
-
"#{class1}#{class2}"
|
23
|
-
end
|
24
|
-
|
25
|
-
def quote(val)
|
26
|
-
val.inspect
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
# A Store that 'persists' objects into (RAM) memory.
|
32
|
-
#--
|
33
|
-
# TODO: fully working query.
|
34
|
-
# TODO: arbitrary pk.
|
35
|
-
#++
|
36
|
-
|
37
|
-
class MemoryStore < Store
|
38
|
-
extend MemoryUtils; include MemoryUtils
|
39
|
-
|
40
|
-
class ObjectHash < Hash
|
41
|
-
def [](key)
|
42
|
-
super(key.to_s)
|
43
|
-
end
|
44
|
-
|
45
|
-
def []=(key, value)
|
46
|
-
super(key.to_s, value)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# This hash implements an in-memory database.
|
51
|
-
|
52
|
-
@objects = ObjectHash.new
|
53
|
-
|
54
|
-
def self.objects
|
55
|
-
@objects
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.objects=(val)
|
59
|
-
@objects = val
|
60
|
-
end
|
61
|
-
|
62
|
-
# A pseudo-connection to the actual object store.
|
63
|
-
|
64
|
-
attr_accessor :conn
|
65
|
-
|
66
|
-
def self.destroy(options)
|
67
|
-
FileUtils.rm_rf("#{options[:name]}.db")
|
68
|
-
rescue
|
69
|
-
Logger.info "Cannot destroy '#{name}'"
|
70
|
-
end
|
71
|
-
|
72
|
-
def initialize(options)
|
73
|
-
super
|
74
|
-
begin
|
75
|
-
@conn = self.class.objects = YAML.load_file("#{@options[:name]}.db")
|
76
|
-
rescue
|
77
|
-
@conn = self.class.objects = ObjectHash.new
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def close
|
82
|
-
File.open("#{@options[:name]}.db", 'w') { |f| f << @conn.to_yaml }
|
83
|
-
end
|
84
|
-
|
85
|
-
# Enchants a class.
|
86
|
-
|
87
|
-
def enchant(klass, manager)
|
88
|
-
klass.property :oid, Fixnum
|
89
|
-
|
90
|
-
super
|
91
|
-
|
92
|
-
@conn[klass] ||= {}
|
93
|
-
|
94
|
-
eval_og_insert(klass)
|
95
|
-
eval_og_update(klass)
|
96
|
-
eval_og_read(klass)
|
97
|
-
eval_og_delete(klass)
|
98
|
-
end
|
99
|
-
|
100
|
-
# :section: Lifecycle methods.
|
101
|
-
|
102
|
-
# Loads an object from the store using the primary key.
|
103
|
-
|
104
|
-
def load(pk, klass)
|
105
|
-
@conn[klass][pk]
|
106
|
-
end
|
107
|
-
|
108
|
-
# Update selected properties of an object or class of
|
109
|
-
# objects.
|
110
|
-
|
111
|
-
def update_properties(target, set, options = nil)
|
112
|
-
set = set.gsub(/,/, ';')
|
113
|
-
if target.is_a?(Class)
|
114
|
-
if options
|
115
|
-
condition = options[:condition] || options[:where]
|
116
|
-
else
|
117
|
-
condition = 'true'
|
118
|
-
end
|
119
|
-
for obj in @conn[target].values
|
120
|
-
obj.instance_eval %{
|
121
|
-
if #{condition.gsub(/=/, '==')}
|
122
|
-
#{set}
|
123
|
-
end
|
124
|
-
}
|
125
|
-
end
|
126
|
-
else
|
127
|
-
target.instance_eval(set)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
alias_method :pupdate, :update_properties
|
131
|
-
alias_method :update_property, :update_properties
|
132
|
-
|
133
|
-
# Find a collection of objects.
|
134
|
-
#
|
135
|
-
# === Examples
|
136
|
-
#
|
137
|
-
# User.find(:condition => 'age > 15', :order => 'score ASC', :offet => 10, :limit =>10)
|
138
|
-
# Comment.find(:include => :entry)
|
139
|
-
# store.find(:class => User, :where => 'age > 15')
|
140
|
-
|
141
|
-
def find(options)
|
142
|
-
query(options)
|
143
|
-
end
|
144
|
-
|
145
|
-
# Find one object.
|
146
|
-
|
147
|
-
def find_one(options)
|
148
|
-
query(options).first
|
149
|
-
end
|
150
|
-
|
151
|
-
# Reloads an object from the store.
|
152
|
-
|
153
|
-
def reload(obj, pk)
|
154
|
-
# Nop, the memory store is always synchronized.
|
155
|
-
end
|
156
|
-
|
157
|
-
# Count results.
|
158
|
-
|
159
|
-
def count(options)
|
160
|
-
objects = 0
|
161
|
-
|
162
|
-
if condition = options[:condition] || options[:where]
|
163
|
-
condition = "obj." + condition.gsub(/=/, '==')
|
164
|
-
else
|
165
|
-
condition = true
|
166
|
-
end
|
167
|
-
|
168
|
-
eval %{
|
169
|
-
for obj in @conn[options[:class]].values
|
170
|
-
objects += 1 if #{condition}
|
171
|
-
end
|
172
|
-
}
|
173
|
-
|
174
|
-
return objects
|
175
|
-
end
|
176
|
-
|
177
|
-
# Relate two objects through an intermediate join table.
|
178
|
-
# Typically used in joins_many and many_to_many relations.
|
179
|
-
|
180
|
-
def join(obj1, obj2, table)
|
181
|
-
# nop
|
182
|
-
end
|
183
|
-
|
184
|
-
# Query.
|
185
|
-
|
186
|
-
def query(options)
|
187
|
-
objects = []
|
188
|
-
|
189
|
-
if condition = options[:condition] || options[:where]
|
190
|
-
condition = "obj." + condition.gsub(/=/, '==')
|
191
|
-
else
|
192
|
-
condition = true
|
193
|
-
end
|
194
|
-
|
195
|
-
eval %{
|
196
|
-
for obj in @conn[options[:class]].values
|
197
|
-
objects << obj if #{condition}
|
198
|
-
end
|
199
|
-
}
|
200
|
-
|
201
|
-
if order = options[:order]
|
202
|
-
desc = (order =~ /DESC/)
|
203
|
-
order = order.gsub(/DESC/, '').gsub(/ASC/, '')
|
204
|
-
eval "objects.sort { |x, y| x.#{order} <=> y.#{order} }"
|
205
|
-
objects.reverse! if desc
|
206
|
-
end
|
207
|
-
|
208
|
-
return objects
|
209
|
-
end
|
210
|
-
|
211
|
-
# :section: Transaction methods.
|
212
|
-
|
213
|
-
# Start a new transaction.
|
214
|
-
|
215
|
-
def start
|
216
|
-
end
|
217
|
-
|
218
|
-
# Commit a transaction.
|
219
|
-
|
220
|
-
def commit
|
221
|
-
end
|
222
|
-
|
223
|
-
# Rollback a transaction.
|
224
|
-
|
225
|
-
def rollback
|
226
|
-
end
|
227
|
-
|
228
|
-
private
|
229
|
-
|
230
|
-
# :section: Lifecycle method compilers.
|
231
|
-
|
232
|
-
# Compile the og_update method for the class.
|
233
|
-
|
234
|
-
def eval_og_insert(klass)
|
235
|
-
pk = klass.primary_key.first
|
236
|
-
|
237
|
-
klass.class_eval %{
|
238
|
-
def og_insert(store)
|
239
|
-
#{::Aspects.gen_advice_code(:og_insert, klass.advices, :pre) if klass.respond_to?(:advices)}
|
240
|
-
@#{pk} = store.conn[#{klass}].size + 1
|
241
|
-
store.conn[#{klass}][@#{pk}] = self
|
242
|
-
#{::Aspects.gen_advice_code(:og_insert, klass.advices, :post) if klass.respond_to?(:advices)}
|
243
|
-
end
|
244
|
-
}
|
245
|
-
end
|
246
|
-
|
247
|
-
# Compile the og_update method for the class.
|
248
|
-
|
249
|
-
def eval_og_update(klass)
|
250
|
-
pk = klass.primary_key.first
|
251
|
-
|
252
|
-
klass.class_eval %{
|
253
|
-
def og_update(store, options)
|
254
|
-
#{::Aspects.gen_advice_code(:og_update, klass.advices, :pre) if klass.respond_to?(:advices)}
|
255
|
-
store.conn[#{klass}][@#{pk}] = self
|
256
|
-
#{::Aspects.gen_advice_code(:og_update, klass.advices, :post) if klass.respond_to?(:advices)}
|
257
|
-
end
|
258
|
-
}
|
259
|
-
end
|
260
|
-
|
261
|
-
# Not really useful in this store, kept for compatibility,
|
262
|
-
# just to call the aspects.
|
263
|
-
|
264
|
-
def eval_og_read(klass)
|
265
|
-
klass.class_eval %{
|
266
|
-
def og_read
|
267
|
-
#{::Aspects.gen_advice_code(:og_read, klass.advices, :pre) if klass.respond_to?(:advices)}
|
268
|
-
#{::Aspects.gen_advice_code(:og_read, klass.advices, :post) if klass.respond_to?(:advices)}
|
269
|
-
end
|
270
|
-
}
|
271
|
-
end
|
272
|
-
|
273
|
-
def eval_og_delete(klass)
|
274
|
-
klass.module_eval %{
|
275
|
-
def og_delete(store, pk, cascade = true)
|
276
|
-
#{::Aspects.gen_advice_code(:og_delete, klass.advices, :pre) if klass.respond_to?(:advices)}
|
277
|
-
pk ||= @#{klass.primary_key.first}
|
278
|
-
transaction do |tx|
|
279
|
-
tx.conn[#{klass}].delete(pk)
|
280
|
-
if cascade and #{klass}.__meta[:descendants]
|
281
|
-
#{klass}.__meta[:descendants].each do |dclass, foreign_key|
|
282
|
-
eval "tx.conn[dclass].delete_if { |dobj| dobj.\#{foreign_key} == \#{pk} }"
|
283
|
-
end
|
284
|
-
end
|
285
|
-
end
|
286
|
-
#{::Aspects.gen_advice_code(:og_delete, klass.advices, :post) if klass.respond_to?(:advices)}
|
287
|
-
end
|
288
|
-
}
|
289
|
-
end
|
290
|
-
|
291
|
-
end
|
292
|
-
|
293
|
-
end
|
294
|
-
|
295
|
-
# * George Moschovitis <gm@navel.gr>
|