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,37 +6,64 @@ require 'og'
6
6
  require 'og/relation'
7
7
 
8
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
-
32
- # bug: test the no belongs_to case in Article
33
-
34
- og = Og.setup(:store => :memory, :name => 'test')
35
- og.manage_classes
36
-
37
- end
9
+ include Og
10
+
11
+ class User
12
+ property :name
13
+ has_many Dummer
14
+ has_many Article
15
+ def initialize(name)
16
+ @name = name
17
+ end
18
+ end
19
+
20
+ class Article
21
+ property :body, String
22
+ refers_to :active_user, User
23
+ def initialize(body)
24
+ @body = body
25
+ end
26
+ end
27
+
28
+ def test_all
29
+ # no-namespace case.
30
+ rel = User.relation(:dummers)
31
+ rel.resolve_target
32
+ assert_equal Dummer, rel.target_class
33
+
34
+ # namespace case.
35
+ rel = User.relation(:articles)
36
+ rel.resolve_target
37
+ assert_equal TestCaseOgRelation::Article, rel.target_class
38
+
39
+ # bug: test the no belongs_to case in Article
40
+
41
+ og = Og.setup(:store => :memory, :name => 'test')
42
+ og.manage_classes
43
+ end
44
+
45
+ def test_refers_to
46
+ og = Og.setup(:store => :memory, :name => 'test')
47
+ og.manage_classes
48
+
49
+ # test refers_to accessor is correctly updated even without reload
50
+ u = User.create("George")
51
+ a = Article.create("Og is a good thing!")
52
+ assert_equal(nil, a.active_user)
53
+
54
+ a.active_user = u
55
+ a.save!
56
+ assert_equal(u.oid, a.active_user_oid)
57
+ assert_equal(u.object_id, a.active_user.object_id)
58
+
59
+ u2 = User.create("Another user")
60
+ a.active_user = u2
61
+ a.save!
62
+ assert_equal(u2.oid, a.active_user_oid)
63
+ assert_equal(u2.object_id, a.active_user.object_id)
64
+ end
38
65
  end
39
66
 
40
67
  class Dummer
41
- property :dum, String
68
+ property :dum, String
42
69
  end
@@ -0,0 +1,49 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+
3
+ $DBG = true
4
+
5
+ require 'test/unit'
6
+
7
+ require 'og'
8
+
9
+ class TC_Query < Test::Unit::TestCase # :nodoc: all
10
+ include Og
11
+
12
+ class Item
13
+ property :quantity, Fixnum
14
+ property :unit_price, Float
15
+
16
+ def initialize(quantity, unit_price)
17
+ @quantity = quantity
18
+ @unit_price = unit_price
19
+ end
20
+
21
+ def total_price
22
+ @total_price.to_f
23
+ end
24
+ end
25
+
26
+ def setup
27
+ @og = Og.setup(
28
+ :destroy => true,
29
+ :store => :mysql,
30
+ # :store => :sqlite,
31
+ # :store => :psql,
32
+ # :user => 'postgres',
33
+ :user => 'root',
34
+ :password => 'navelrulez',
35
+ :name => 'test'
36
+ )
37
+ end
38
+
39
+ def test_all
40
+ Item.create(2, 34.5)
41
+ Item.create(5, 12.6)
42
+
43
+ item = Item.one :select => 'quantity, quantity*unit_price as total_price', :condition => 'oid = 1'
44
+
45
+ assert_equal 2*34.5, item.total_price
46
+ assert_equal 2, item.quantity.to_i
47
+ end
48
+
49
+ end
@@ -7,352 +7,360 @@ require 'test/unit'
7
7
  require 'og'
8
8
 
9
9
  class TCOgStore < Test::Unit::TestCase # :nodoc: all
10
- include Og
10
+ include Og
11
11
 
12
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
- order 'hits ASC'
52
-
53
- def initialize(body = nil, user = nil)
54
- @body = body
55
- @user = user
56
- @hits = 0
57
- end
58
- end
59
-
60
- class Bugger
61
- property :name, String
62
- many_to_many Bugger
63
- end
64
-
65
- def setup
66
- @og = nil
67
- end
68
-
69
- def teardown
70
- @og.store.close
71
- @og.store.class.destroy(@og.options)
72
- @og = nil
73
- end
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
+ after "$schema_after=1", :on => :og_create_schema
51
+
52
+ order 'hits ASC'
53
+
54
+ def initialize(body = nil, user = nil)
55
+ @body = body
56
+ @user = user
57
+ @hits = 0
58
+ end
59
+ end
60
+
61
+ class Bugger
62
+ property :name, String
63
+ many_to_many Bugger
64
+ end
65
+
66
+ def setup
67
+ @og = nil
68
+ end
69
+
70
+ def teardown
71
+ @og.store.close
72
+ @og.store.class.destroy(@og.options)
73
+ @og = nil
74
+ end
74
75
 
75
76
  =begin
76
- def test_kirby
77
- @og = Og.setup(
78
- :destroy => true,
79
- :store => :kirby,
80
- :name => 'test',
81
- :embedded => true
82
- )
83
- features_test
84
- # conversions_test
85
- end
77
+ def test_kirby
78
+ @og = Og.setup(
79
+ :destroy => true,
80
+ :store => :kirby,
81
+ :name => 'test',
82
+ :embedded => true
83
+ )
84
+ features_test
85
+ # conversions_test
86
+ end
86
87
  =end
87
- =begin
88
- def test_psql
89
- @og = Og.setup(
90
- :destroy => true,
91
- :store => :psql,
92
- :name => 'test',
93
- :min_messages => 'ERROR',
94
- :user => 'postgres',
95
- :password => 'navelrulez'
96
- )
97
- features_test
98
- conversions_test
99
- end
88
+ #=begin
89
+ def test_psql
90
+ @og = Og.setup(
91
+ :destroy => true,
92
+ :store => :psql,
93
+ :name => 'test',
94
+ :min_messages => 'ERROR',
95
+ :user => 'postgres',
96
+ :password => 'navelrulez'
97
+ )
98
+ features_test
99
+ conversions_test
100
+ end
101
+ #=end
102
+ =begin
103
+ def test_mysql
104
+ @og = Og.setup(
105
+ :destroy => true,
106
+ :store => :mysql,
107
+ :name => 'test',
108
+ :user => 'root',
109
+ :table_type => 'InnoDB',
110
+ :password => 'navelrulez'
111
+ )
112
+ features_test
113
+ # conversions_test
114
+ end
100
115
  =end
101
116
  =begin
102
- def test_mysql
103
- @og = Og.setup(
104
- :destroy => true,
105
- :store => :mysql,
106
- :name => 'test',
107
- :user => 'root',
108
- :table_type => 'InnoDB',
109
- :password => 'navelrulez'
110
- )
111
- features_test
112
- # conversions_test
113
- end
117
+ def test_sqlite
118
+ @og = Og.setup(
119
+ :destroy => true,
120
+ :store => :sqlite,
121
+ :name => 'test'
122
+ )
123
+ features_test
124
+ conversions_test
125
+ end
114
126
  =end
115
- #=begin
116
- def test_sqlite
117
- @og = Og.setup(
118
- :destroy => true,
119
- :store => :sqlite,
120
- :name => 'test'
121
- )
122
- features_test
123
- conversions_test
124
- end
125
- #=end
126
127
  =begin
127
- def test_memory
128
- @og = Og.setup(
129
- :store => :memory,
130
- :name => :test,
131
- :destroy => true
132
- )
133
- features_test
134
- end
128
+ def test_memory
129
+ @og = Og.setup(
130
+ :store => :memory,
131
+ :name => :test,
132
+ :destroy => true
133
+ )
134
+ features_test
135
+ end
135
136
  =end
136
137
 
137
- def features_test
138
- u = User.create('gmosx')
139
-
140
- a1 = Article.new('Article 1')
141
- @og.store.save(a1)
142
-
143
- a2 = @og.store.load(1, Article)
144
-
145
- assert_equal a1.body, a2.body
146
-
147
- # custom select.
148
-
149
- acs = Article.select("SELECT * FROM #{Article.table} WHERE oid=1")
150
- assert_equal 'Article 1', acs.first.body
151
-
152
- acs = Article.select_one("SELECT * FROM #{Article.table} WHERE oid=1")
153
- assert_equal 'Article 1', acs.body
154
-
155
- acs = Article.select_one("WHERE oid=1")
156
- assert_equal 'Article 1', acs.body
157
-
158
- acs = Article.find(:sql => "SELECT * FROM #{Article.table} WHERE oid=1")
159
- assert_equal 'Article 1', acs.first.body
160
-
161
- # prefered way?
162
-
163
- acs = Article.find(:sql => "WHERE oid=1")
164
- assert_equal 'Article 1', acs.first.body
165
-
166
- # exist?
167
-
168
- assert Article.exist?(1)
169
- assert_equal nil, Article.exist?(999)
170
-
171
- # update
172
-
173
- a = Article[1]
174
- a.body = 'Changed'
175
- # test affected rows.
176
- assert_equal 1, a.save
177
-
178
- #
179
-
180
- a3 = Article.create do |a|
181
- a.title = 'Title 3'
182
- a.body = 'Article 3'
183
- end
184
-
185
- a0 = Article.one(:condition => "body='Article 3'")
186
- assert_equal 'Article 3', a0.body
187
-
188
- @og.store.delete(a3)
189
-
190
- assert @og.store.load(1, Article)
191
- assert !Article[2]
192
- assert Article.load(1)
193
-
194
- a2.delete
195
-
196
- a4 = Article.new('Article 4')
197
- a4.author = u
198
- a4.owner = u
199
- a4.save
200
-
201
- # add some children.
202
-
203
- a4.comments << Comment.new('Comment 1', u)
204
- a4.comments.push(Comment.new('Comment 2', u))
205
- a4.comments.add(Comment.new('Comment 3', u))
206
-
207
- assert_equal 3, a4.comments.size
208
-
209
- assert_not_equal a4.comments[1].body, a4.comments[0].body
210
-
211
-
212
- assert_not_equal a4.comments[0].body, a4.comments[1].body
213
-
214
- c1 = Comment.new('Comment 4')
215
- c1.article = a4
216
- c1.user = u
217
- c1.save
218
-
219
- c1.reload
220
- assert_equal 'Comment 4', c1.body
221
-
222
- # count
223
-
224
- assert_equal 4, @og.store.count(:class => Comment)
225
- assert_equal 1, @og.store.count(:class => Comment, :condition => "body = 'Comment 4'")
226
- assert_equal 4, Comment.count
227
- assert_equal 1, Comment.count(:condition => "body = 'Comment 2'")
228
-
229
- # update_properties
230
-
231
- assert_equal 4, Comment.update_properties('@hits = @hits + 1')
232
- cc = Comment[1]
233
- assert_equal 1, cc.hits
234
- Comment.update_properties('@hits = @hits + 1', :condition => 'oid = 1')
235
- cc.reload
236
- assert_equal 2, cc.hits
237
- cc.update_properties('@hits = @hits + 1')
238
- cc.reload
239
- assert_equal 3, cc.hits
240
-
241
- # update selected properties.
242
-
243
- cc.hits = 5
244
- cc.update :only => :hits
245
- assert_equal 5, cc.hits
246
- cc.reload
247
- assert_equal 5, cc.hits
248
-
249
- cc.hits += 1
250
- cc.body = 'Wow!'
251
- cc.update :only => [:hits, :body]
252
- cc.reload
253
- assert_equal 'Wow!', cc.body
254
-
255
- # join
256
-
257
- c3 = Comment.one(:condition => "body = 'Comment 4'", :include => :user)
258
- assert_equal 'Comment 4', c3.body
259
- # is eagerly loaded.
260
- assert_equal 'gmosx', c3.user.name
261
- assert_equal 'Article 4', c3.article.body
262
-
263
- comments = a4.comments(:reload => true, :include => [:user, :article])
264
- assert_equal 'gmosx', comments[0].user.name
265
- assert_equal 'Article 4', comments.first.article.body
266
-
267
- # thanks to reloading detects the manually added
268
- # comment.
269
-
270
- assert_equal 4, a4.comments(:reload => true).size
271
-
272
- assert_equal 2, a4.comments(:limit => 2, :reload => true).size
273
-
274
- # bug:
275
- assert_equal 4, a4.comments(:reload => true).size
276
-
277
- a4.comments.delete(c1)
278
- assert_equal 3, a4.comments.size
279
-
280
- assert_equal 3, @og.store.count(:class => Comment)
281
-
282
- a4.comments.delete_all
283
- assert_equal 0, a4.comments.size
284
-
285
- # has_one
286
-
287
- assert_equal 'gmosx', a4.author.name
288
-
289
- # refers_to
290
-
291
- assert_equal 'gmosx', a4.owner.name
292
-
293
- # generated finders
294
-
295
- assert User.respond_to?(:find_by_name)
296
- assert Comment.respond_to?(:find_by_body)
297
-
298
- u = User.find_by_name('gmosx')
299
- assert_equal 'gmosx', u.name
300
-
301
- # inspection.
302
-
303
- assert_equal 2, Comment.relations.size
304
-
305
- rel = Comment.relation(:article)
306
- assert_equal Og::BelongsTo, rel.class
307
-
308
- # joins_many / many_to_many relations.
309
-
310
- c1 = Category.create('News')
311
- c2 = Category.create('Sports')
312
- a = Article.create('Hello')
313
- a.categories << c1
314
- a.save
315
- a.categories << c2
316
- a.save
317
-
318
- assert_equal 2, a.categories.size
319
-
320
- a = Article.find_by_body('Hello').first
321
- assert_equal 2, a.categories.size
322
- assert_equal 'News', a.categories[0].title
323
-
324
- c = Category.find_by_title('News')
325
- assert_equal 1, c.articles.size
326
-
327
- # bug: self join bug.
328
-
329
- b1 = Bugger.create
330
- b2 = Bugger.create
331
-
332
- b1.buggers << b2
333
-
334
- assert b1.buggers.first
335
- end
336
-
337
- def conversions_test
338
- store = @og.store
339
-
340
- assert_equal '13', store.quote(13)
341
- assert_equal '13.23', store.quote(13.23)
342
- assert_equal "'can''t quote'", store.quote("can't quote")
343
-
344
- t = Time.now
345
-
346
- assert_equal t.day, store.parse_timestamp(store.timestamp(t)).day
347
- assert_equal t.year, store.parse_timestamp(store.timestamp(t)).year
348
- assert_equal t.month, store.parse_timestamp(store.timestamp(t)).month
349
- assert_equal t.hour, store.parse_timestamp(store.timestamp(t)).hour
350
- assert_equal t.min, store.parse_timestamp(store.timestamp(t)).min
351
- assert_equal t.sec, store.parse_timestamp(store.timestamp(t)).sec
352
-
353
- d = Date.new
354
-
355
- assert_equal d, store.parse_date(store.date(d))
356
- end
357
-
138
+ def features_test
139
+ u = User.create('gmosx')
140
+
141
+ a1 = Article.new('Article 1')
142
+ @og.store.save(a1)
143
+
144
+ a2 = @og.store.load(1, Article)
145
+
146
+ assert_equal a1.body, a2.body
147
+
148
+ # custom select.
149
+
150
+ acs = Article.select("SELECT * FROM #{Article.table} WHERE oid=1")
151
+ assert_equal 'Article 1', acs.first.body
152
+
153
+ acs = Article.select_one("SELECT * FROM #{Article.table} WHERE oid=1")
154
+ assert_equal 'Article 1', acs.body
155
+
156
+ acs = Article.select_one("WHERE oid=1")
157
+ assert_equal 'Article 1', acs.body
158
+
159
+ acs = Article.find(:sql => "SELECT * FROM #{Article.table} WHERE oid=1")
160
+ assert_equal 'Article 1', acs.first.body
161
+
162
+ # prefered way?
163
+
164
+ acs = Article.find(:sql => "WHERE oid=1")
165
+ assert_equal 'Article 1', acs.first.body
166
+
167
+ # exist?
168
+
169
+ assert Article.exist?(1)
170
+ assert_equal nil, Article.exist?(999)
171
+
172
+ # update
173
+
174
+ a = Article[1]
175
+ a.body = 'Changed'
176
+ # test affected rows.
177
+ assert_equal 1, a.save
178
+
179
+ #
180
+
181
+ a3 = Article.create do |a|
182
+ a.title = 'Title 3'
183
+ a.body = 'Article 3'
184
+ end
185
+
186
+ a0 = Article.one(:condition => "body='Article 3'")
187
+ assert_equal 'Article 3', a0.body
188
+
189
+ @og.store.delete(a3)
190
+
191
+ assert @og.store.load(1, Article)
192
+ assert !Article[2]
193
+ assert Article.load(1)
194
+
195
+ a2.delete
196
+
197
+ a4 = Article.new('Article 4')
198
+ a4.author = u
199
+ a4.owner = u
200
+ a4.save
201
+
202
+ # add some children.
203
+
204
+ a4.comments << Comment.new('Comment 1', u)
205
+ a4.comments.push(Comment.new('Comment 2', u))
206
+ a4.comments.add(Comment.new('Comment 3', u))
207
+
208
+ assert_equal 3, a4.comments.size
209
+
210
+ # test override bug.
211
+ assert a4.comments(:condition => '1 = 1').first
212
+ assert_not_equal a4.comments[1].body, a4.comments[0].body
213
+ assert_not_equal a4.comments[0].body, a4.comments[1].body
214
+
215
+ c1 = Comment.new('Comment 4')
216
+ c1.article = a4
217
+ c1.user = u
218
+ c1.save
219
+
220
+ c1.reload
221
+ assert_equal 'Comment 4', c1.body
222
+
223
+ # count
224
+
225
+ assert_equal 4, @og.store.count(:class => Comment)
226
+ assert_equal 1, @og.store.count(:class => Comment, :condition => "body = 'Comment 4'")
227
+ assert_equal 4, Comment.count
228
+ assert_equal 1, Comment.count(:condition => "body = 'Comment 2'")
229
+
230
+ # update_properties
231
+
232
+ assert_equal 4, Comment.update_properties('@hits = @hits + 1')
233
+ cc = Comment[1]
234
+ assert_equal 1, cc.hits
235
+ Comment.update_properties('@hits = @hits + 1', :condition => 'oid = 1')
236
+ cc.reload
237
+ assert_equal 2, cc.hits
238
+ cc.update_properties('@hits = @hits + 1')
239
+ cc.reload
240
+ assert_equal 3, cc.hits
241
+
242
+ # update selected properties.
243
+
244
+ cc.hits = 5
245
+ cc.update :only => :hits
246
+ assert_equal 5, cc.hits
247
+ cc.reload
248
+ assert_equal 5, cc.hits
249
+
250
+ cc.hits += 1
251
+ cc.body = 'Wow!'
252
+ cc.update :only => [:hits, :body]
253
+ cc.reload
254
+ assert_equal 'Wow!', cc.body
255
+
256
+ # join
257
+
258
+ c3 = Comment.one(:condition => "body = 'Comment 4'", :include => :user)
259
+ assert_equal 'Comment 4', c3.body
260
+ # is eagerly loaded.
261
+ assert_equal 'gmosx', c3.user.name
262
+ assert_equal 'Article 4', c3.article.body
263
+
264
+ comments = a4.comments(:reload => true, :include => [:user, :article])
265
+ assert_equal 'gmosx', comments[0].user.name
266
+ assert_equal 'Article 4', comments.first.article.body
267
+
268
+ # thanks to reloading detects the manually added
269
+ # comment.
270
+
271
+ assert_equal 4, a4.comments(:reload => true).size
272
+
273
+ assert_equal 2, a4.comments(:limit => 2, :reload => true).size
274
+
275
+ # bug:
276
+ assert_equal 4, a4.comments(:reload => true).size
277
+
278
+ a4.comments.delete(c1)
279
+ assert_equal 3, a4.comments.size
280
+
281
+ assert_equal 3, @og.store.count(:class => Comment)
282
+
283
+ a4.comments.delete_all
284
+ assert_equal 0, a4.comments.size
285
+
286
+ # has_one
287
+
288
+ assert_equal 'gmosx', a4.author.name
289
+
290
+ # refers_to
291
+
292
+ assert_equal 'gmosx', a4.owner.name
293
+
294
+ # generated finders
295
+
296
+ assert User.respond_to?(:find_by_name)
297
+ assert Comment.respond_to?(:find_by_body)
298
+
299
+ u = User.find_by_name('gmosx')
300
+ assert_equal 'gmosx', u.name
301
+
302
+ # inspection.
303
+
304
+ assert_equal 2, Comment.relations.size
305
+
306
+ rel = Comment.relation(:article)
307
+ assert_equal Og::BelongsTo, rel.class
308
+
309
+ # joins_many / many_to_many relations.
310
+
311
+ c1 = Category.create('News')
312
+ c2 = Category.create('Sports')
313
+ a = Article.create('Hello')
314
+ a.categories << c1
315
+ a.save
316
+ a.categories << c2
317
+ a.save
318
+
319
+ assert_equal 2, a.categories.size
320
+
321
+ a = Article.find_by_body('Hello').first
322
+ assert_equal 2, a.categories.size
323
+ assert_equal 'News', a.categories[0].title
324
+
325
+ c = Category.find_by_title('News')
326
+ assert_equal 1, c.articles.size
327
+
328
+ # bug: self join bug.
329
+
330
+ b1 = Bugger.create
331
+ b2 = Bugger.create
332
+
333
+ b1.buggers << b2
334
+
335
+ assert b1.buggers.first
336
+
337
+ # bug: refers_to nil
338
+
339
+ a = Article.create
340
+ a.owner = nil
341
+
342
+ assert_equal 1, $schema_after
343
+ end
344
+
345
+ def conversions_test
346
+ store = @og.store
347
+
348
+ assert_equal '13', store.quote(13)
349
+ assert_equal '13.23', store.quote(13.23)
350
+ assert_equal "'can''t quote'", store.quote("can't quote")
351
+
352
+ t = Time.now
353
+
354
+ assert_equal t.day, store.parse_timestamp(store.timestamp(t)).day
355
+ assert_equal t.year, store.parse_timestamp(store.timestamp(t)).year
356
+ assert_equal t.month, store.parse_timestamp(store.timestamp(t)).month
357
+ assert_equal t.hour, store.parse_timestamp(store.timestamp(t)).hour
358
+ assert_equal t.min, store.parse_timestamp(store.timestamp(t)).min
359
+ assert_equal t.sec, store.parse_timestamp(store.timestamp(t)).sec
360
+
361
+ d = Date.new
362
+
363
+ assert_equal d, store.parse_date(store.date(d))
364
+ end
365
+
358
366
  end