og 0.16.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/CHANGELOG +485 -0
  2. data/README +35 -12
  3. data/Rakefile +4 -7
  4. data/benchmark/bench.rb +1 -1
  5. data/doc/AUTHORS +3 -3
  6. data/doc/RELEASES +153 -2
  7. data/doc/config.txt +0 -7
  8. data/doc/tutorial.txt +7 -0
  9. data/examples/README +5 -0
  10. data/examples/mysql_to_psql.rb +25 -50
  11. data/examples/run.rb +62 -77
  12. data/install.rb +1 -1
  13. data/lib/og.rb +45 -106
  14. data/lib/og/collection.rb +156 -0
  15. data/lib/og/entity.rb +131 -0
  16. data/lib/og/errors.rb +10 -15
  17. data/lib/og/manager.rb +115 -0
  18. data/lib/og/{mixins → mixin}/hierarchical.rb +43 -37
  19. data/lib/og/{mixins → mixin}/orderable.rb +35 -35
  20. data/lib/og/{mixins → mixin}/timestamped.rb +0 -6
  21. data/lib/og/{mixins → mixin}/tree.rb +0 -4
  22. data/lib/og/relation.rb +178 -0
  23. data/lib/og/relation/belongs_to.rb +14 -0
  24. data/lib/og/relation/has_many.rb +62 -0
  25. data/lib/og/relation/has_one.rb +17 -0
  26. data/lib/og/relation/joins_many.rb +69 -0
  27. data/lib/og/relation/many_to_many.rb +17 -0
  28. data/lib/og/relation/refers_to.rb +31 -0
  29. data/lib/og/store.rb +223 -0
  30. data/lib/og/store/filesys.rb +113 -0
  31. data/lib/og/store/madeleine.rb +4 -0
  32. data/lib/og/store/memory.rb +291 -0
  33. data/lib/og/store/mysql.rb +283 -0
  34. data/lib/og/store/psql.rb +238 -0
  35. data/lib/og/store/sql.rb +599 -0
  36. data/lib/og/store/sqlite.rb +190 -0
  37. data/lib/og/store/sqlserver.rb +262 -0
  38. data/lib/og/types.rb +19 -0
  39. data/lib/og/validation.rb +0 -4
  40. data/test/og/{mixins → mixin}/tc_hierarchical.rb +21 -23
  41. data/test/og/{mixins → mixin}/tc_orderable.rb +15 -14
  42. data/test/og/mixin/tc_timestamped.rb +38 -0
  43. data/test/og/store/tc_filesys.rb +71 -0
  44. data/test/og/tc_relation.rb +36 -0
  45. data/test/og/tc_store.rb +290 -0
  46. data/test/og/tc_types.rb +21 -0
  47. metadata +54 -40
  48. data/examples/mock_example.rb +0 -50
  49. data/lib/og/adapters/base.rb +0 -706
  50. data/lib/og/adapters/filesys.rb +0 -117
  51. data/lib/og/adapters/mysql.rb +0 -350
  52. data/lib/og/adapters/oracle.rb +0 -368
  53. data/lib/og/adapters/psql.rb +0 -272
  54. data/lib/og/adapters/sqlite.rb +0 -265
  55. data/lib/og/adapters/sqlserver.rb +0 -356
  56. data/lib/og/database.rb +0 -290
  57. data/lib/og/enchant.rb +0 -149
  58. data/lib/og/meta.rb +0 -407
  59. data/lib/og/testing/mock.rb +0 -165
  60. data/lib/og/typemacros.rb +0 -24
  61. data/test/og/adapters/tc_filesys.rb +0 -83
  62. data/test/og/adapters/tc_sqlite.rb +0 -86
  63. data/test/og/adapters/tc_sqlserver.rb +0 -96
  64. data/test/og/tc_automanage.rb +0 -46
  65. data/test/og/tc_lifecycle.rb +0 -105
  66. data/test/og/tc_many_to_many.rb +0 -61
  67. data/test/og/tc_meta.rb +0 -55
  68. data/test/og/tc_validation.rb +0 -89
  69. data/test/tc_og.rb +0 -364
data/lib/og/types.rb ADDED
@@ -0,0 +1,19 @@
1
+ module Og
2
+
3
+ # Some useful type macros to help when defining properties.
4
+ # You can easily code your own type macros. Just return the
5
+ # array that should be passed to the property macro.
6
+ #
7
+ # === Example
8
+ #
9
+ # property :name, VarChar(30)
10
+
11
+ def self.VarChar(size)
12
+ return String, :sql => "VARCHAR(#{size})"
13
+ end
14
+
15
+ NotNull = { :sql => 'NOT NULL' }.freeze
16
+
17
+ Null = { :sql => 'NULL' }.freeze
18
+
19
+ end
data/lib/og/validation.rb CHANGED
@@ -1,7 +1,3 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: validation.rb 1 2005-04-11 11:04:30Z gmosx $
4
-
5
1
  require 'glue/validation'
6
2
 
7
3
  module Glue
@@ -3,19 +3,18 @@ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
3
3
  require 'test/unit'
4
4
  require 'ostruct'
5
5
 
6
- require 'og/mixins/hierarchical'
7
-
8
6
  require 'og'
7
+ require 'og/mixin/hierarchical'
9
8
 
10
- $og = Og::Database.new(
11
- :adapter => 'psql',
12
- :database => 'test',
9
+ $og = Og.setup(
10
+ :store => 'psql',
11
+ :name => 'test',
13
12
  :user => 'postgres',
14
13
  :password => 'navelrulez',
15
- :drop => true
14
+ :destroy => true
16
15
  )
17
16
 
18
- class TestCaseOgHierarchical < Test::Unit::TestCase # :nodoc: all
17
+ class TC_OgHierarchical < Test::Unit::TestCase # :nodoc: all
19
18
 
20
19
  class Comment
21
20
  property :body, String
@@ -34,41 +33,40 @@ class TestCaseOgHierarchical < Test::Unit::TestCase # :nodoc: all
34
33
  end
35
34
 
36
35
  def test_all
37
- $og.auto_manage_classes
36
+ $og.manage_classes
38
37
 
39
38
  root = Comment.create('root')
40
39
  c1 = Comment.new('1')
41
- root.add_comment(c1)
40
+ root.add_comment c1
42
41
  c2 = Comment.new('1.1')
43
- c1.add_comment(c2)
42
+ c1.add_comment c2
44
43
  c3 = Comment.new('1.2')
45
- c1.add_comment(c3)
44
+ c1.add_comment c3
46
45
  c4 = Comment.new('1.1.1')
47
- c2.add_comment(c4)
46
+ c2.add_comment c4
48
47
  c5 = Comment.new('1.2.1')
49
- c3.add_comment(c5)
48
+ c3.add_comment c5
50
49
  c6 = Comment.new('1.1.1.1')
51
- c4.add_comment(c6)
50
+ c4.add_comment c6
52
51
  c7 = Comment.new('2')
53
- root.add_comment(c7)
52
+ root.add_comment c7
54
53
  c8 = Comment.new('3')
55
- root.add_comment(c8)
54
+ root.add_comment c8
56
55
  c9 = Comment.new('2.1')
57
- c7.add_comment(c9)
56
+ c7.add_comment c9
58
57
 
59
58
  c1.reload
60
- =begin
61
- Comment.all("ORDER BY lft, rgt").each { |c|
59
+
60
+ Comment.all(:order => "lft, rgt").each { |c|
62
61
  puts sprintf("%3d %3d %s", c.lft, c.rgt, c.body)
63
62
  # p c
64
63
  }
65
64
  puts '--1'
66
- c1.comments("ORDER BY lft, rgt").each { |c| puts c.body }
65
+ c1.comments(:order => "lft, rgt").each { |c| puts c.body }
67
66
  puts '--2'
68
- c1.full_comments("ORDER BY lft, rgt").each { |c| puts c.body }
67
+ c1.full_comments(:order => "lft, rgt").each { |c| puts c.body }
69
68
  puts '--3'
70
- c1.direct_comments("ORDER BY lft, rgt").each { |c| puts c.body }
71
- =end
69
+ c1.direct_comments(:order => "lft, rgt").each { |c| puts c.body }
72
70
 
73
71
  assert_equal 6, c1.full_comments.size
74
72
  assert_equal 5, c1.comments.size
@@ -3,16 +3,16 @@ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
3
3
  require 'test/unit'
4
4
  require 'ostruct'
5
5
 
6
- require 'og/mixins/orderable'
7
-
8
6
  require 'og'
7
+ require 'og/mixin/orderable'
9
8
 
10
- $og = Og::Database.new(
11
- :adapter => 'psql',
12
- :database => 'test',
9
+ $og = Og.setup(
10
+ :store => 'psql',
11
+ # :store => :memory,
12
+ :name => 'test',
13
13
  :user => 'postgres',
14
14
  :password => 'navelrulez',
15
- :drop => true
15
+ :destroy => true
16
16
  )
17
17
 
18
18
  class TestCaseOgOrderable < Test::Unit::TestCase # :nodoc: all
@@ -32,7 +32,7 @@ class TestCaseOgOrderable < Test::Unit::TestCase # :nodoc: all
32
32
  property :body, String
33
33
  belongs_to :article, Article
34
34
 
35
- include Og::Orderable, :scope => :article
35
+ include Og::Orderable #, :scope => :article
36
36
 
37
37
  def initialize(body = nil)
38
38
  @body = body
@@ -40,17 +40,17 @@ class TestCaseOgOrderable < Test::Unit::TestCase # :nodoc: all
40
40
  end
41
41
 
42
42
  def test_all
43
- $og.auto_manage_classes
43
+ $og.manage_classes
44
44
 
45
45
  a = Article.create('article')
46
46
  a.save
47
47
 
48
- c1 = Comment.new('1')
49
- a.add_comment(c1)
50
- c2 = Comment.new('2')
51
- a.add_comment(c2)
52
- c3 = Comment.new('3')
53
- a.add_comment(c3)
48
+ c1 = Comment.create('1')
49
+ a.comments << c1
50
+ c2 = Comment.create('2')
51
+ a.comments << c2
52
+ c3 = Comment.create('3')
53
+ a.comments << c3
54
54
 
55
55
  assert_equal 1, c1.position
56
56
  assert_equal 2, c2.position
@@ -63,6 +63,7 @@ class TestCaseOgOrderable < Test::Unit::TestCase # :nodoc: all
63
63
  c3.reload
64
64
 
65
65
  assert_equal 1, c1.position
66
+
66
67
  assert_equal 2, c3.position
67
68
  assert_equal 3, c2.position
68
69
 
@@ -0,0 +1,38 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
2
+
3
+ require 'test/unit'
4
+ require 'ostruct'
5
+
6
+ require 'og'
7
+ require 'og/mixin/timestamped'
8
+
9
+ $og = Og.setup(
10
+ :store => 'psql',
11
+ :name => 'test',
12
+ :user => 'postgres',
13
+ :password => 'navelrulez',
14
+ :destroy => true
15
+ )
16
+
17
+ class TestCaseOgTimestamped < Test::Unit::TestCase # :nodoc: all
18
+
19
+ class Article
20
+ include Og::Timestamped
21
+ property :body, String
22
+
23
+ def initialize(body = nil)
24
+ @body = body
25
+ end
26
+ end
27
+
28
+ def test_all
29
+ $og.manage_classes
30
+
31
+ a = Article.create('article')
32
+ a.save
33
+
34
+ a = Article[1]
35
+ assert a.create_time
36
+ end
37
+
38
+ end
@@ -0,0 +1,71 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+
3
+ require 'test/unit'
4
+
5
+ require 'og'
6
+
7
+ class TestCaseOgFilesys < Test::Unit::TestCase # :nodoc: all
8
+ include Og
9
+
10
+ class Comment; end
11
+
12
+ class Article
13
+ property :body, String
14
+ has_many :comment, Comment
15
+
16
+ def initialize(body = nil)
17
+ @body = body
18
+ end
19
+ end
20
+
21
+ class Comment
22
+ property :body, String
23
+ belongs_to :article, Article
24
+
25
+ def initialize(body = nil)
26
+ @body = body
27
+ end
28
+ end
29
+
30
+ class User
31
+ property :name, :name_key => true
32
+ end
33
+
34
+ def setup
35
+ @og = Og.setup(:store => 'filesys', :name => 'test')
36
+ end
37
+
38
+ def teardown
39
+ @og = nil
40
+ end
41
+
42
+ def test_all
43
+ # p Comment.__meta
44
+ # p Article.__meta
45
+
46
+ a1 = Article.new('Article 1')
47
+ @og.store.save(a1)
48
+
49
+ a2 = @og.store.load(1, Article)
50
+
51
+ assert_equal a1.body, a2.body
52
+
53
+ a3 = Article.new('Article 3')
54
+ a3.save
55
+
56
+ @og.store.delete(a3)
57
+
58
+ assert @og.store.load(1, Article)
59
+ assert !@og.store.load(2, Article)
60
+
61
+ a2.delete
62
+
63
+ # a.comments << Comment.new('Comment 1')
64
+ # a.save
65
+ # a = Article[1]
66
+
67
+ @og.store.close
68
+ @og.store.class.destroy(@og.options)
69
+ end
70
+
71
+ end
@@ -0,0 +1,36 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+
3
+ require 'test/unit'
4
+
5
+ require 'og'
6
+ require 'og/relation'
7
+
8
+ class TestCaseOgRelation < Test::Unit::TestCase # :nodoc: all
9
+ include Og
10
+
11
+ class User
12
+ property :name
13
+ has_many Dummer
14
+ has_many Article
15
+ end
16
+
17
+ class Article
18
+ property :body, String
19
+ end
20
+
21
+ def test_all
22
+ # no-namespace case.
23
+ rel = User.relation(:dummers)
24
+ rel.resolve_target
25
+ assert_equal Dummer, rel.target_class
26
+
27
+ # namespace case.
28
+ rel = User.relation(:articles)
29
+ rel.resolve_target
30
+ assert_equal TestCaseOgRelation::Article, rel.target_class
31
+ end
32
+ end
33
+
34
+ class Dummer
35
+ property :dum, String
36
+ end
@@ -0,0 +1,290 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+
3
+ #$DBG = true
4
+
5
+ require 'test/unit'
6
+
7
+ require 'og'
8
+
9
+ class TCOgStore < Test::Unit::TestCase # :nodoc: all
10
+ include Og
11
+
12
+ # Not needed thanks to Og's two-pass algorithm.
13
+ # class Comment; end
14
+
15
+ class User
16
+ property :name, Og::VarChar(32), :unique => true
17
+
18
+ def initialize(name = nil)
19
+ @name = name
20
+ end
21
+ end
22
+
23
+ class Category
24
+ property :title, Og::VarChar(32), :unique => true
25
+ joins_many Article
26
+
27
+ def initialize(title = nil)
28
+ @title = title
29
+ end
30
+ end
31
+
32
+ class Article
33
+ property :title, :body, String
34
+ has_many Comment
35
+ has_one :author, User
36
+ refers_to :owner, User
37
+ many_to_many Category
38
+
39
+ def initialize(body = nil)
40
+ @body = body
41
+ end
42
+ end
43
+
44
+ class Comment
45
+ property :body, String
46
+ property :hits, Fixnum
47
+ # lets define the relation name just for fun.
48
+ belongs_to :article, Article
49
+ belongs_to User
50
+
51
+ def initialize(body = nil, user = nil)
52
+ @body = body
53
+ @user = user
54
+ @hits = 0
55
+ end
56
+ end
57
+
58
+ def setup
59
+ @og = nil
60
+ end
61
+
62
+ def teardown
63
+ @og.store.close
64
+ @og.store.class.destroy(@og.options)
65
+ @og = nil
66
+ end
67
+
68
+ =begin
69
+ def test_psql
70
+ @og = Og.setup(
71
+ :destroy => true,
72
+ :store => :psql,
73
+ :name => 'test',
74
+ :user => 'postgres',
75
+ :password => 'navelrulez'
76
+ )
77
+ features_test
78
+ conversions_test
79
+ end
80
+ =end
81
+ =begin
82
+ def test_mysql
83
+ @og = Og.setup(
84
+ :destroy => true,
85
+ :store => :mysql,
86
+ :name => 'test',
87
+ :user => 'root',
88
+ :password => 'navelrulez'
89
+ )
90
+ features_test
91
+ # conversions_test
92
+ end
93
+ =end
94
+ #=begin
95
+ def test_sqlite
96
+ @og = Og.setup(
97
+ :destroy => true,
98
+ :store => :sqlite,
99
+ :name => 'test'
100
+ )
101
+ features_test
102
+ conversions_test
103
+ end
104
+ #=end
105
+ =begin
106
+ def test_memory
107
+ @og = Og.setup(
108
+ :store => :memory,
109
+ :name => :test,
110
+ :destroy => true
111
+ )
112
+ features_test
113
+ end
114
+ =end
115
+
116
+ def features_test
117
+ u = User.create('gmosx')
118
+
119
+ a1 = Article.new('Article 1')
120
+ @og.store.save(a1)
121
+
122
+ a2 = @og.store.load(1, Article)
123
+
124
+ assert_equal a1.body, a2.body
125
+
126
+ a3 = Article.create do |a|
127
+ a.title = 'Title 3'
128
+ a.body = 'Article 3'
129
+ end
130
+
131
+ a0 = Article.one(:condition => "body='Article 3'")
132
+ assert_equal 'Article 3', a0.body
133
+
134
+ @og.store.delete(a3)
135
+
136
+ assert @og.store.load(1, Article)
137
+ # assert !Article[2]
138
+ assert Article.load(1)
139
+
140
+ a2.delete
141
+
142
+ a4 = Article.new('Article 4')
143
+ a4.author = u
144
+ a4.owner = u
145
+ a4.save
146
+
147
+ # add some children.
148
+
149
+ a4.comments << Comment.new('Comment 1', u)
150
+ a4.comments.push(Comment.new('Comment 2', u))
151
+ a4.comments.add(Comment.new('Comment 3', u))
152
+
153
+ assert_equal 3, a4.comments.size
154
+
155
+ assert_not_equal a4.comments[1].body, a4.comments[0].body
156
+
157
+
158
+ assert_not_equal a4.comments[0].body, a4.comments[1].body
159
+
160
+ c1 = Comment.new('Comment 4')
161
+ c1.article = a4
162
+ c1.user = u
163
+ c1.save
164
+
165
+ c1.reload
166
+ assert_equal 'Comment 4', c1.body
167
+
168
+ # count
169
+
170
+ assert_equal 4, @og.store.count(:class => Comment)
171
+ assert_equal 1, @og.store.count(:class => Comment, :condition => "body = 'Comment 4'")
172
+ assert_equal 4, Comment.count
173
+ assert_equal 1, Comment.count(:condition => "body = 'Comment 2'")
174
+
175
+ # update_properties
176
+
177
+ Comment.update_properties('@hits = @hits + 1')
178
+ cc = Comment[1]
179
+ assert_equal 1, cc.hits
180
+ Comment.update_properties('@hits = @hits + 1', :condition => 'oid = 1')
181
+ cc.reload
182
+ assert_equal 2, cc.hits
183
+ cc.update_properties('@hits = @hits + 1')
184
+ cc.reload
185
+ assert_equal 3, cc.hits
186
+
187
+ # update selected properties.
188
+
189
+ cc.hits = 5
190
+ cc.update(:hits)
191
+ assert_equal 5, cc.hits
192
+ cc.reload
193
+ assert_equal 5, cc.hits
194
+
195
+ cc.hits += 1
196
+ cc.body = 'Wow!'
197
+ cc.update(:hits, :body)
198
+ cc.reload
199
+ assert_equal 'Wow!', cc.body
200
+
201
+ # join
202
+
203
+ c3 = Comment.one(:condition => "body = 'Comment 4'", :include => :user)
204
+ assert_equal 'Comment 4', c3.body
205
+ # is eagerly loaded.
206
+ assert_equal 'gmosx', c3.user.name
207
+ assert_equal 'Article 4', c3.article.body
208
+
209
+ comments = a4.comments(:reload => true, :include => [:user, :article])
210
+ assert_equal 'gmosx', comments[0].user.name
211
+ assert_equal 'Article 4', comments.first.article.body
212
+
213
+ # thanks to reloading detects the manually added
214
+ # comment.
215
+
216
+ assert_equal 4, a4.comments(:reload => true).size
217
+
218
+ a4.comments.delete(c1)
219
+ assert_equal 3, a4.comments.size
220
+
221
+ assert_equal 3, @og.store.count(:class => Comment)
222
+
223
+ a4.comments.clear
224
+ assert_equal 0, a4.comments.size
225
+
226
+ # has_one
227
+
228
+ assert_equal 'gmosx', a4.author.name
229
+
230
+ # refers_to
231
+
232
+ assert_equal 'gmosx', a4.owner.name
233
+
234
+ # generated finders
235
+
236
+ assert User.respond_to?(:find_by_name)
237
+ assert Comment.respond_to?(:find_by_body)
238
+
239
+ u = User.find_by_name('gmosx')
240
+ assert_equal 'gmosx', u.name
241
+
242
+ # inspection.
243
+
244
+ assert_equal 2, Comment.relations.size
245
+
246
+ rel = Comment.relation(:article)
247
+ assert_equal Og::BelongsTo, rel.class
248
+
249
+ # joins_many / many_to_many relations.
250
+
251
+ c1 = Category.create('News')
252
+ c2 = Category.create('Sports')
253
+ a = Article.create('Hello')
254
+ a.categories << c1
255
+ a.save
256
+ a.categories << c2
257
+ a.save
258
+
259
+ assert_equal 2, a.categories.size
260
+
261
+ a = Article.find_by_body('Hello').first
262
+ assert_equal 2, a.categories.size
263
+ assert_equal 'News', a.categories[0].title
264
+
265
+ c = Category.find_by_title('News')
266
+ assert_equal 1, c.articles.size
267
+ end
268
+
269
+ def conversions_test
270
+ store = @og.store
271
+
272
+ assert_equal '13', store.quote(13)
273
+ assert_equal '13.23', store.quote(13.23)
274
+ assert_equal "'can''t quote'", store.quote("can't quote")
275
+
276
+ t = Time.now
277
+
278
+ assert_equal t.day, store.parse_timestamp(store.timestamp(t)).day
279
+ assert_equal t.year, store.parse_timestamp(store.timestamp(t)).year
280
+ assert_equal t.month, store.parse_timestamp(store.timestamp(t)).month
281
+ assert_equal t.hour, store.parse_timestamp(store.timestamp(t)).hour
282
+ assert_equal t.min, store.parse_timestamp(store.timestamp(t)).min
283
+ assert_equal t.sec, store.parse_timestamp(store.timestamp(t)).sec
284
+
285
+ d = Date.new
286
+
287
+ assert_equal d, store.parse_date(store.date(d))
288
+ end
289
+
290
+ end