og 0.21.2 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +60 -1
- data/README +10 -6
- data/doc/RELEASES +66 -0
- data/lib/og.rb +26 -18
- data/lib/og/entity.rb +37 -8
- data/lib/og/manager.rb +12 -10
- data/lib/og/mixin/timestamped.rb +4 -2
- data/lib/og/relation.rb +0 -1
- data/lib/og/relation/has_many.rb +4 -2
- data/lib/og/relation/refers_to.rb +5 -1
- data/lib/og/store.rb +1 -1
- data/lib/og/store/filesys.rb +1 -4
- data/lib/og/store/kirby.rb +1 -2
- data/lib/og/store/mysql.rb +9 -4
- data/lib/og/store/psql.rb +6 -2
- data/lib/og/store/sql.rb +27 -8
- data/lib/og/store/sqlite.rb +6 -2
- data/lib/og/test.rb +2 -0
- data/lib/og/test/assertions.rb +175 -0
- data/lib/og/test/testcase.rb +57 -0
- data/test/og/store/tc_filesys.rb +3 -3
- data/test/og/tc_multiple.rb +68 -0
- data/test/og/tc_polymorphic.rb +6 -0
- data/test/og/tc_reverse.rb +78 -0
- data/test/og/tc_store.rb +5 -5
- metadata +9 -4
data/CHANGELOG
CHANGED
@@ -1,7 +1,66 @@
|
|
1
|
+
07-08-2005 George Moschovitis <gm@navel.gr>
|
2
|
+
|
3
|
+
* lib/og/entity.rb: fixed schema_inheritance alias.
|
4
|
+
|
5
|
+
* lib/og.rb: updated comments.
|
6
|
+
|
7
|
+
* doc/RELEASES: updated.
|
8
|
+
|
9
|
+
06-08-2005 George Moschovitis <gm@navel.gr>
|
10
|
+
|
11
|
+
* lib/og/entity.rb: helper method.
|
12
|
+
|
13
|
+
* lib/og/manager.rb (#manage_class): alias,
|
14
|
+
(#get_store): fixed bug in thread_safe mode, allows multiple
|
15
|
+
og's to run in thread safe mode.
|
16
|
+
|
17
|
+
* test/og/tc_multiple.rb: implemented.
|
18
|
+
|
19
|
+
05-08-2005 George Moschovitis <gm@navel.gr>
|
20
|
+
|
21
|
+
* lib/og/relation/has_many.rb: support for legacy schemas,
|
22
|
+
:foreign_field option,
|
23
|
+
quote foreign_key values,
|
24
|
+
fixed foreign_field bug.
|
25
|
+
|
26
|
+
* lib/og/relation/refers_to.rb: support for legacy schemas.
|
27
|
+
|
28
|
+
* lib/og/entity.rb (#set_primary_key): also get primary key class,
|
29
|
+
(#og_quote): added.
|
30
|
+
|
31
|
+
04-08-2005 George Moschovitis <gm@navel.gr>
|
32
|
+
|
33
|
+
* lib/og/store/*: use #field_for_property where needed,
|
34
|
+
don't create the oid property if not needed!
|
35
|
+
fixed enchant some more,
|
36
|
+
fixed finder calculation to honour field override.
|
37
|
+
|
38
|
+
* lib/og/store/sql.rb (#table): honour sql_table metadata,
|
39
|
+
(#field_for_property): implemented,
|
40
|
+
(#eval_og_read): updated to handle custom fields.
|
41
|
+
|
42
|
+
* lib/og/entity.rb (#sql_table): added helper [daval],
|
43
|
+
added set_xxx prefix to some helper.
|
44
|
+
|
45
|
+
* test/og/tc_reverse.rb: introduced,
|
46
|
+
Yeah, I got data written to a legacy table.
|
47
|
+
|
48
|
+
* lib/og/test/testcase.rb: introduced,
|
49
|
+
(fixture): implemented,
|
50
|
+
(og_fixture): implemented.
|
51
|
+
|
52
|
+
* lib/og/test/assertions.rb: introduced.
|
53
|
+
|
54
|
+
30-07-2005 George Moschovitis <gm@navel.gr>
|
55
|
+
|
56
|
+
* test/: renamed from testing.
|
57
|
+
|
1
58
|
28-07-2005 George Moschovitis <gm@navel.gr>
|
2
59
|
|
60
|
+
* --- VERSION 0.21.1 ---
|
61
|
+
|
3
62
|
* lib/og/store/psql.rb: custom eval_og_allocate,
|
4
|
-
fixed inheritance
|
63
|
+
fixed inheritance problem.
|
5
64
|
|
6
65
|
* lib/og/store/sql.rb: factored out eval_og_allocate.
|
7
66
|
|
data/README
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= Og 0.
|
1
|
+
= Og 0.22.0 README
|
2
2
|
|
3
3
|
Og (ObjectGraph) is a powerful and elegant object-relational mapping
|
4
4
|
library. Og manages the lifecycle of Ruby objects and provides
|
@@ -28,21 +28,25 @@ distribution (http://www.nitrohq.com).
|
|
28
28
|
|
29
29
|
The library provides the following features:
|
30
30
|
|
31
|
-
* Object-Relational mapping
|
31
|
+
* Object-Relational mapping, automatically maps standard
|
32
|
+
Ruby objects to sql schemas
|
32
33
|
* Absolutely no configuration files.
|
33
34
|
* Multiple stores (PostgreSQL, MySQL, SQLite, Oraclei, SqlServer, ..).
|
34
|
-
* Supports non SQL stores.
|
35
|
+
* Supports non SQL stores (in-memory, filesystem, ..).
|
36
|
+
* Can 'reverse engineer' legacy database schemase.
|
37
|
+
* Fine-grained or High-level customization of the generated
|
38
|
+
schema.
|
35
39
|
* ActiveRecord-style domain specific language and db synchronized
|
36
40
|
collections.
|
37
41
|
* Transforms resultsets from arbitrary sql queries to Ruby objects.
|
38
|
-
*
|
39
|
-
|
42
|
+
* Independent store for each object class, can support multiple
|
43
|
+
stores in the same application.
|
40
44
|
* Deserialize to Ruby Objects.
|
41
45
|
* Deserialize sql join queries to Ruby Objects.
|
42
46
|
* Eager associations.
|
43
47
|
* Serialize arbitrary ruby object graphs through YAML.
|
44
48
|
* Connection pooling.
|
45
|
-
* Thread safety
|
49
|
+
* Thread safety.
|
46
50
|
* SQL transactions.
|
47
51
|
* Aspect oriented constructs allow interception of lifecycle callbacks.
|
48
52
|
* Transparent support for cascading deletes for all backends.
|
data/doc/RELEASES
CHANGED
@@ -1,3 +1,69 @@
|
|
1
|
+
== Version 0.22.0
|
2
|
+
|
3
|
+
A snapshot of the latest developments. Many requested features
|
4
|
+
where implemented, and many reported bugs fixed.
|
5
|
+
|
6
|
+
* The much requested Og 'reverse mode' is implemented. Og's
|
7
|
+
domain specific language and API is extended to allow fine-grained
|
8
|
+
customization of the schema-to-objects mapping. Og can now handle
|
9
|
+
most of the legacy schemas you can throw at it. Here is an
|
10
|
+
example:
|
11
|
+
|
12
|
+
class User
|
13
|
+
property :name, String, :field => :thename, :uniq => true
|
14
|
+
property :password, String
|
15
|
+
property :age, Fixnum, :field => :age3
|
16
|
+
has_many Comment, :foreign_field => :user
|
17
|
+
set_table :my_users
|
18
|
+
set_primary_key :name, String
|
19
|
+
end
|
20
|
+
|
21
|
+
class Comment
|
22
|
+
property :cid, Fixnum
|
23
|
+
property :body, String
|
24
|
+
belongs_to User, :field => :user
|
25
|
+
set_table :my_comments
|
26
|
+
set_primary_key :cid
|
27
|
+
end
|
28
|
+
|
29
|
+
As you can see, even relation fields can be customized. For
|
30
|
+
higher level customization you can overload methods like #table,
|
31
|
+
#field_for_property etc.
|
32
|
+
|
33
|
+
* Og now handles multiple connections to multiple stores even
|
34
|
+
in thread safe mode. This means you can now have objects serialized
|
35
|
+
in different RDBM systems in the same application. Or you can have
|
36
|
+
some objects managed by an RDBMS store and others by a FAST
|
37
|
+
in-memory store. You can still have relations between objects in
|
38
|
+
different stores. An example:
|
39
|
+
|
40
|
+
mysql = Og.setup(:store => :mysql, ..)
|
41
|
+
psql = Og.setup(:store => :psql, ..)
|
42
|
+
|
43
|
+
class User
|
44
|
+
has_many Comment
|
45
|
+
end
|
46
|
+
|
47
|
+
class Comment
|
48
|
+
belongs_to User
|
49
|
+
end
|
50
|
+
|
51
|
+
mysql.manage_class User
|
52
|
+
psql.manage_class Comment
|
53
|
+
|
54
|
+
user.comments << comment
|
55
|
+
|
56
|
+
* Greatly improved support for testing and test-driven-development.
|
57
|
+
Support for Og fixtures and automatic test database
|
58
|
+
setup is provided. Fixtures can be defined with yml or csv files.
|
59
|
+
|
60
|
+
For an example of the testing infrastructure check out the
|
61
|
+
Spark 0.4.0 sources. Spark is a Wiki powered by Nitro.
|
62
|
+
|
63
|
+
* Many smaller changes and feature implementations that make
|
64
|
+
development with Og so much more pleasurable.
|
65
|
+
|
66
|
+
|
1
67
|
== Version 0.21.2
|
2
68
|
|
3
69
|
This is a bug fix release.
|
data/lib/og.rb
CHANGED
@@ -27,24 +27,32 @@ require 'glue/configuration'
|
|
27
27
|
#
|
28
28
|
# The library provides the following features:
|
29
29
|
#
|
30
|
-
#
|
30
|
+
# * Object-Relational mapping, automatically maps standard
|
31
31
|
# Ruby objects to sql schemas
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
32
|
+
# * Absolutely no configuration files.
|
33
|
+
# * Multiple stores (PostgreSQL, MySQL, SQLite, Oraclei, SqlServer, ..).
|
34
|
+
# * Supports non SQL stores (in-memory, filesystem, ..).
|
35
|
+
# * Can 'reverse engineer' legacy database schemase.
|
36
|
+
# * Fine-grained or High-level customization of the generated
|
37
|
+
# schema.
|
38
|
+
# * ActiveRecord-style domain specific language and db synchronized
|
39
|
+
# collections.
|
40
|
+
# * Transforms resultsets from arbitrary sql queries to Ruby objects.
|
41
|
+
# * Independent store for each object class, can support multiple
|
42
|
+
# stores in the same application.
|
43
|
+
# * Deserialize to Ruby Objects.
|
44
|
+
# * Deserialize sql join queries to Ruby Objects.
|
45
|
+
# * Eager associations.
|
46
|
+
# * Serialize arbitrary ruby object graphs through YAML.
|
47
|
+
# * Connection pooling.
|
48
|
+
# * Thread safety.
|
49
|
+
# * SQL transactions.
|
50
|
+
# * Aspect oriented constructs allow interception of lifecycle callbacks.
|
51
|
+
# * Transparent support for cascading deletes for all backends.
|
52
|
+
# * Hierarchical structures (nested sets)
|
53
|
+
# * Works safely as part of distributed application.
|
54
|
+
# * Optimistic locking.
|
55
|
+
# * Simple implementation.
|
48
56
|
#
|
49
57
|
# === Property Metadata
|
50
58
|
#
|
@@ -75,7 +83,7 @@ module Og
|
|
75
83
|
|
76
84
|
# The version.
|
77
85
|
|
78
|
-
Version = '0.
|
86
|
+
Version = '0.22.0'
|
79
87
|
|
80
88
|
# Library path.
|
81
89
|
|
data/lib/og/entity.rb
CHANGED
@@ -14,7 +14,7 @@ module EntityMixin
|
|
14
14
|
base.module_eval <<-end_eval, __FILE__, __LINE__
|
15
15
|
def save(options = nil)
|
16
16
|
self.class.ogmanager.store.save(self, options)
|
17
|
-
#
|
17
|
+
# return self
|
18
18
|
end
|
19
19
|
alias_method :save!, :save
|
20
20
|
|
@@ -56,6 +56,10 @@ module EntityMixin
|
|
56
56
|
def transaction(&block)
|
57
57
|
self.class.ogmanager.store.transaction(&block)
|
58
58
|
end
|
59
|
+
|
60
|
+
def og_quote(obj)
|
61
|
+
self.class.ogmanager.store.quote(obj)
|
62
|
+
end
|
59
63
|
end_eval
|
60
64
|
|
61
65
|
base.send(:include, RelationMacros)
|
@@ -132,7 +136,13 @@ module EntityMixin
|
|
132
136
|
def transaction(&block)
|
133
137
|
ogmanager.store.transaction(&block)
|
134
138
|
end
|
139
|
+
|
140
|
+
# Return the store (connection) for this class.
|
135
141
|
|
142
|
+
def ogstore
|
143
|
+
ogmanager.store
|
144
|
+
end
|
145
|
+
|
136
146
|
def primary_key
|
137
147
|
unless @__meta and @__meta[:primary_key]
|
138
148
|
self.meta :primary_key, Entity.resolve_primary_key(self)
|
@@ -142,21 +152,37 @@ module EntityMixin
|
|
142
152
|
|
143
153
|
# Set the default find options for this entity.
|
144
154
|
|
145
|
-
def
|
155
|
+
def set_find_options(options)
|
146
156
|
meta :find_options, options
|
147
157
|
end
|
158
|
+
alias_method :find_options, :set_find_options
|
159
|
+
|
160
|
+
# Enable schema inheritance for this Entity class.
|
161
|
+
# The Single Table Inheritance pattern is used.
|
162
|
+
|
163
|
+
def set_schema_inheritance
|
164
|
+
meta :schema_inheritance
|
165
|
+
end
|
166
|
+
alias_method :schema_inheritance, :set_schema_inheritance
|
148
167
|
|
149
168
|
# Set the default order option for this entity.
|
150
169
|
|
151
|
-
def
|
170
|
+
def set_order(order_str)
|
152
171
|
meta :find_options, :order => order_str
|
153
172
|
end
|
173
|
+
alias_method :order, :set_order
|
154
174
|
|
155
|
-
#
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
175
|
+
# Set a custom table name.
|
176
|
+
|
177
|
+
def set_sql_table(table)
|
178
|
+
meta :sql_table, table.to_s
|
179
|
+
end
|
180
|
+
alias_method :set_table, :set_sql_table
|
181
|
+
|
182
|
+
# Set the primary key.
|
183
|
+
|
184
|
+
def set_primary_key(pk, pkclass = Fixnum)
|
185
|
+
meta :primary_key, pk, pkclass
|
160
186
|
end
|
161
187
|
|
162
188
|
# Is this entity a polymorphic parent?
|
@@ -178,6 +204,9 @@ end
|
|
178
204
|
class Entity
|
179
205
|
class << self
|
180
206
|
def resolve_primary_key(klass)
|
207
|
+
if pk = klass.__meta[:primary_key]
|
208
|
+
return pk
|
209
|
+
end
|
181
210
|
for p in klass.properties
|
182
211
|
if p.meta[:primary_key]
|
183
212
|
return p.symbol, p.klass
|
data/lib/og/manager.rb
CHANGED
@@ -40,35 +40,36 @@ class Manager
|
|
40
40
|
@entities = {}
|
41
41
|
@pool = Glue::Pool.new
|
42
42
|
|
43
|
-
store_class = Store.for_name(options[:store])
|
44
|
-
store_class.destroy(options) if options[:destroy]
|
43
|
+
@store_class = Store.for_name(options[:store])
|
44
|
+
@store_class.destroy(options) if options[:destroy]
|
45
45
|
|
46
46
|
if Og.thread_safe
|
47
47
|
(options[:connection_count] || 5).times do
|
48
|
-
@pool << store_class.new(options)
|
48
|
+
@pool << @store_class.new(options)
|
49
49
|
end
|
50
50
|
else
|
51
|
-
@store = store_class.new(options)
|
51
|
+
@store = @store_class.new(options)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
# Get a store from the pool.
|
55
|
+
# Get a store from the pool.
|
56
56
|
|
57
57
|
def get_store
|
58
58
|
if Og.thread_safe
|
59
59
|
thread = Thread.current
|
60
60
|
|
61
|
-
unless
|
62
|
-
|
63
|
-
thread[:og_store] =
|
61
|
+
unless st = thread[:og_store] and st.is_a?(@store_class)
|
62
|
+
st = @pool.pop()
|
63
|
+
thread[:og_store] = st
|
64
64
|
end
|
65
65
|
|
66
|
-
return
|
66
|
+
return st
|
67
67
|
else
|
68
68
|
return @store
|
69
69
|
end
|
70
70
|
end
|
71
71
|
alias_method :store, :get_store
|
72
|
+
alias_method :conn, :get_store
|
72
73
|
|
73
74
|
# Return a store to the pool.
|
74
75
|
|
@@ -111,7 +112,7 @@ class Manager
|
|
111
112
|
# subclass.
|
112
113
|
|
113
114
|
manage(klass.superclass) if has_super?(klass)
|
114
|
-
|
115
|
+
|
115
116
|
klass.module_eval %{
|
116
117
|
def ==(other)
|
117
118
|
other ? @#{klass.primary_key.first} == other.#{klass.primary_key.first} : false
|
@@ -181,6 +182,7 @@ class Manager
|
|
181
182
|
classes.each { |c| Relation.resolve(c, :resolve_options) }
|
182
183
|
classes.each { |c| manage(c) }
|
183
184
|
end
|
185
|
+
alias_method :manage_class, :manage_classes
|
184
186
|
|
185
187
|
end
|
186
188
|
|
data/lib/og/mixin/timestamped.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'glue/aspects'
|
2
|
+
|
1
3
|
module Og
|
2
4
|
|
3
5
|
# Adds timestamping functionality.
|
@@ -7,8 +9,8 @@ module Timestamped
|
|
7
9
|
property :update_time, Time
|
8
10
|
property :access_time, Time
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
before "@create_time = @update_time = Time.now", :on => :og_insert
|
13
|
+
before "@update_time = Time.now", :on => :og_update
|
12
14
|
|
13
15
|
def touch!
|
14
16
|
@access_time = Time.now
|
data/lib/og/relation.rb
CHANGED
@@ -42,7 +42,6 @@ class Relation
|
|
42
42
|
# as a polymorphic parent class.
|
43
43
|
# This class acts as template
|
44
44
|
# to generate customized versions of this class.
|
45
|
-
|
46
45
|
owner_class.meta(:polymorphic, owner_class)
|
47
46
|
elsif target_class.respond_to?(:metadata) and target_class.metadata.polymorphic
|
48
47
|
# If the target class is polymorphic, create a specialized
|
data/lib/og/relation/has_many.rb
CHANGED
@@ -32,6 +32,8 @@ class HasMany < Relation
|
|
32
32
|
self[:owner_singular_name] = owner_class.to_s.demodulize.underscore.downcase
|
33
33
|
self[:target_singular_name] = target_plural_name.to_s.singular
|
34
34
|
self[:foreign_key] = "#{foreign_name || owner_singular_name}_#{owner_pk}"
|
35
|
+
# gmosx: DON'T set self[:foreign_field]
|
36
|
+
foreign_field = self[:foreign_field] || self[:foreign_key]
|
35
37
|
|
36
38
|
owner_class.module_eval %{
|
37
39
|
attr_accessor :#{target_plural_name}
|
@@ -65,7 +67,7 @@ class HasMany < Relation
|
|
65
67
|
|
66
68
|
def find_#{target_plural_name}(options = {})
|
67
69
|
find_options = {
|
68
|
-
:condition => "#{
|
70
|
+
:condition => "#{foreign_field} = \#{og_quote(@#{owner_pk})}"
|
69
71
|
}
|
70
72
|
if options
|
71
73
|
if condition = options.delete(:condition)
|
@@ -77,7 +79,7 @@ class HasMany < Relation
|
|
77
79
|
end
|
78
80
|
|
79
81
|
def count_#{target_plural_name}
|
80
|
-
#{target_class}.count(:condition => "#{
|
82
|
+
#{target_class}.count(:condition => "#{foreign_field} = \#{og_quote(@#{owner_pk})}")
|
81
83
|
end
|
82
84
|
}
|
83
85
|
end
|
@@ -7,9 +7,13 @@ class RefersTo < Relation
|
|
7
7
|
def enchant
|
8
8
|
self[:foreign_key] = "#{foreign_name || target_singular_name}_#{target_pk}"
|
9
9
|
|
10
|
+
if self[:field]
|
11
|
+
field = ", :field => :#{self[:field]}"
|
12
|
+
end
|
13
|
+
|
10
14
|
owner_class.module_eval %{
|
11
15
|
attr_accessor :#{target_singular_name}
|
12
|
-
prop_accessor :#{foreign_key}, #{target_pkclass}
|
16
|
+
prop_accessor :#{foreign_key}, #{target_pkclass}#{field}
|
13
17
|
|
14
18
|
def #{target_singular_name}(reload = false)
|
15
19
|
return nil if @#{foreign_key}.nil?
|
data/lib/og/store.rb
CHANGED
@@ -89,7 +89,7 @@ class Store
|
|
89
89
|
def self.find_by_#{p.symbol}(val, operator = '=', options = {})
|
90
90
|
options.update(
|
91
91
|
:class => #{klass},
|
92
|
-
:condition => "#{p.symbol}\#{operator}\#{ogmanager.store.quote(val)}"
|
92
|
+
:condition => "#{p.meta[:field] || p.symbol}\#{operator}\#{ogmanager.store.quote(val)}"
|
93
93
|
)
|
94
94
|
ogmanager.store.#{finder}(options)
|
95
95
|
end;
|
data/lib/og/store/filesys.rb
CHANGED
@@ -6,7 +6,7 @@ require 'og/store'
|
|
6
6
|
module Og
|
7
7
|
|
8
8
|
# A Store that saves the object on the Filesystem.
|
9
|
-
#
|
9
|
+
# An extension of the Memory store.
|
10
10
|
|
11
11
|
class FilesysStore < Store
|
12
12
|
|
@@ -30,8 +30,6 @@ class FilesysStore < Store
|
|
30
30
|
Logger.error "Cannot destroy '#{name}'"
|
31
31
|
end
|
32
32
|
|
33
|
-
# :section: Misc methods.
|
34
|
-
|
35
33
|
# Initialize a connection to this store.
|
36
34
|
|
37
35
|
def initialize(options)
|
@@ -54,7 +52,6 @@ class FilesysStore < Store
|
|
54
52
|
FileUtils.mkdir_p(path(klass))
|
55
53
|
File.open(spath(klass), 'w') { |f| f << '1' }
|
56
54
|
rescue => ex
|
57
|
-
p ex
|
58
55
|
Logger.error "Cannot create directory to store '#{klass}' classes!"
|
59
56
|
end
|
60
57
|
|
data/lib/og/store/kirby.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
begin
|
2
|
-
require 'lib/
|
2
|
+
require 'lib/vendor/kirbybase'
|
3
3
|
rescue Object => ex
|
4
4
|
Logger.error 'KirbyBase is not installed!'
|
5
5
|
Logger.error ex
|
@@ -282,4 +282,3 @@ end
|
|
282
282
|
end
|
283
283
|
|
284
284
|
# * George Moschovitis <gm@navel.gr>
|
285
|
-
# * Ysabel <deb@isabel.org>
|
data/lib/og/store/mysql.rb
CHANGED
@@ -130,7 +130,11 @@ class MysqlStore < SqlStore
|
|
130
130
|
end
|
131
131
|
|
132
132
|
def enchant(klass, manager)
|
133
|
-
klass.
|
133
|
+
if klass.metadata.primary_key.flatten.first == :oid
|
134
|
+
unless klass.properties.find { |p| p.symbol == :oid }
|
135
|
+
klass.property :oid, Fixnum, :sql => 'integer AUTO_INCREMENT PRIMARY KEY'
|
136
|
+
end
|
137
|
+
end
|
134
138
|
super
|
135
139
|
end
|
136
140
|
|
@@ -183,7 +187,7 @@ private
|
|
183
187
|
|
184
188
|
# Create table constrains.
|
185
189
|
|
186
|
-
if klass.
|
190
|
+
if klass.metadata and constrains = klass.metadata.sql_constrain
|
187
191
|
sql << ", #{constrains.join(', ')}"
|
188
192
|
end
|
189
193
|
|
@@ -293,17 +297,18 @@ private
|
|
293
297
|
def eval_og_insert(klass)
|
294
298
|
props = klass.properties.dup
|
295
299
|
values = props.collect { |p| write_prop(p) }.join(',')
|
296
|
-
|
300
|
+
|
297
301
|
if klass.metadata.superclass or klass.metadata.subclasses
|
298
302
|
props << Property.new(:ogtype, String)
|
299
303
|
values << ", '#{klass}'"
|
300
304
|
end
|
301
305
|
|
302
|
-
sql = "INSERT INTO #{klass::OGTABLE} (#{props.collect {|p| p
|
306
|
+
sql = "INSERT INTO #{klass::OGTABLE} (#{props.collect {|p| field_for_property(p)}.join(',')}) VALUES (#{values})"
|
303
307
|
|
304
308
|
klass.class_eval %{
|
305
309
|
def og_insert(store)
|
306
310
|
#{Aspects.gen_advice_code(:og_insert, klass.advices, :pre) if klass.respond_to?(:advices)}
|
311
|
+
puts "#{sql}"
|
307
312
|
store.conn.query_with_result = false
|
308
313
|
store.conn.query "#{sql}"
|
309
314
|
@#{klass.pk_symbol} = store.conn.insert_id
|
data/lib/og/store/psql.rb
CHANGED
@@ -132,7 +132,11 @@ class PsqlStore < SqlStore
|
|
132
132
|
klass.const_set 'OGSEQ', "#{table(klass)}_oid_seq"
|
133
133
|
end
|
134
134
|
|
135
|
-
klass.
|
135
|
+
if klass.metadata.primary_key.flatten.first == :oid
|
136
|
+
unless klass.properties.find { |p| p.symbol == :oid }
|
137
|
+
klass.property :oid, Fixnum, :sql => 'serial PRIMARY KEY'
|
138
|
+
end
|
139
|
+
end
|
136
140
|
super
|
137
141
|
end
|
138
142
|
|
@@ -278,7 +282,7 @@ private
|
|
278
282
|
values << ", '#{klass}'"
|
279
283
|
end
|
280
284
|
|
281
|
-
sql = "INSERT INTO #{klass::OGTABLE} (#{props.collect {|p| p
|
285
|
+
sql = "INSERT INTO #{klass::OGTABLE} (#{props.collect {|p| field_for_property(p)}.join(',')}) VALUES (#{values})"
|
282
286
|
|
283
287
|
klass.class_eval %{
|
284
288
|
def og_insert(store)
|
data/lib/og/store/sql.rb
CHANGED
@@ -110,7 +110,11 @@ module SqlUtils
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def table(klass)
|
113
|
-
|
113
|
+
if t = klass.metadata.sql_table
|
114
|
+
return t.first
|
115
|
+
else
|
116
|
+
"#{Og.table_prefix}#{tableize(klass)}"
|
117
|
+
end
|
114
118
|
end
|
115
119
|
|
116
120
|
def join_object_ordering(obj1, obj2)
|
@@ -227,8 +231,8 @@ class SqlStore < Store
|
|
227
231
|
def initialize(options)
|
228
232
|
super
|
229
233
|
|
230
|
-
# The default Ruby <-> SQL type mappings, should be valid
|
231
|
-
# RDBM systems.
|
234
|
+
# The default Ruby <-> SQL type mappings, should be valid
|
235
|
+
# for most RDBM systems.
|
232
236
|
|
233
237
|
@typemap = {
|
234
238
|
Integer => 'integer',
|
@@ -483,10 +487,23 @@ private
|
|
483
487
|
raise 'Not implemented'
|
484
488
|
end
|
485
489
|
|
490
|
+
# Drop the sql table where objects of this class are
|
491
|
+
# persisted.
|
492
|
+
|
486
493
|
def drop_table(klass)
|
487
494
|
exec "DROP TABLE #{klass.table}"
|
488
495
|
end
|
489
496
|
|
497
|
+
# Return the field for the given property.
|
498
|
+
|
499
|
+
def field_for_property(property)
|
500
|
+
if f = property.meta[:field]
|
501
|
+
return f.to_s
|
502
|
+
else
|
503
|
+
return property.symbol.to_s
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
490
507
|
# Create the fields that correpsond to the klass properties.
|
491
508
|
# The generated fields array is used in create_table.
|
492
509
|
# If the property has an :sql metadata this overrides the
|
@@ -513,7 +530,7 @@ private
|
|
513
530
|
properties.each do |p|
|
514
531
|
klass.index(p.symbol) if p.meta[:index]
|
515
532
|
|
516
|
-
field = p
|
533
|
+
field = field_for_property(p)
|
517
534
|
|
518
535
|
if p.meta and p.meta[:sql]
|
519
536
|
field << " #{p.meta[:sql]}"
|
@@ -538,7 +555,7 @@ private
|
|
538
555
|
|
539
556
|
return fields
|
540
557
|
end
|
541
|
-
|
558
|
+
|
542
559
|
def type_for_class(klass)
|
543
560
|
@typemap[klass]
|
544
561
|
end
|
@@ -609,7 +626,7 @@ private
|
|
609
626
|
values << ", '#{klass}'"
|
610
627
|
end
|
611
628
|
|
612
|
-
sql = "INSERT INTO #{klass.table} (#{props.collect {|p| p
|
629
|
+
sql = "INSERT INTO #{klass.table} (#{props.collect {|p| field_for_property(p)}.join(',')}) VALUES (#{values})"
|
613
630
|
|
614
631
|
klass.module_eval %{
|
615
632
|
def og_insert(store)
|
@@ -627,7 +644,7 @@ private
|
|
627
644
|
props = klass.properties.reject { |p| pk == p.symbol }
|
628
645
|
|
629
646
|
updates = props.collect { |p|
|
630
|
-
"#{p
|
647
|
+
"#{field_for_property(p)}=#{write_prop(p)}"
|
631
648
|
}
|
632
649
|
|
633
650
|
sql = "UPDATE #{klass::OGTABLE} SET #{updates.join(', ')} WHERE #{pk}=#\{@#{pk}\}"
|
@@ -655,7 +672,9 @@ private
|
|
655
672
|
field_map = create_field_map(klass)
|
656
673
|
|
657
674
|
props.each do |p|
|
658
|
-
|
675
|
+
f = field_for_property(p).intern
|
676
|
+
|
677
|
+
if col = field_map[f]
|
659
678
|
code << "@#{p.symbol} = #{read_prop(p, col)}"
|
660
679
|
end
|
661
680
|
end
|
data/lib/og/store/sqlite.rb
CHANGED
@@ -64,7 +64,11 @@ class SqliteStore < SqlStore
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def enchant(klass, manager)
|
67
|
-
klass.
|
67
|
+
if klass.metadata.primary_key.flatten.first == :oid
|
68
|
+
unless klass.properties.find { |p| p.symbol == :oid }
|
69
|
+
klass.property :oid, Fixnum, :sql => 'integer PRIMARY KEY'
|
70
|
+
end
|
71
|
+
end
|
68
72
|
super
|
69
73
|
end
|
70
74
|
|
@@ -192,7 +196,7 @@ private
|
|
192
196
|
values << ", '#{klass}'"
|
193
197
|
end
|
194
198
|
|
195
|
-
sql = "INSERT INTO #{klass::OGTABLE} (#{props.collect {|p| p
|
199
|
+
sql = "INSERT INTO #{klass::OGTABLE} (#{props.collect {|p| field_for_property(p)}.join(',')}) VALUES (#{values})"
|
196
200
|
|
197
201
|
klass.class_eval %{
|
198
202
|
def og_insert(store)
|
data/lib/og/test.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/unit/assertions'
|
3
|
+
require 'rexml/document'
|
4
|
+
|
5
|
+
#--
|
6
|
+
# Og related assertions.
|
7
|
+
#++
|
8
|
+
|
9
|
+
module Test::Unit::Assertions
|
10
|
+
|
11
|
+
STATUS_MAP = {
|
12
|
+
:success => 200,
|
13
|
+
:ok => 200,
|
14
|
+
:redirect => 307
|
15
|
+
}
|
16
|
+
|
17
|
+
# :section: General assertions.
|
18
|
+
|
19
|
+
# Check the status of the response.
|
20
|
+
|
21
|
+
def assert_response(options = {})
|
22
|
+
unless options.is_a? Hash
|
23
|
+
options = { :status => options }
|
24
|
+
end
|
25
|
+
msg = options[:msg]
|
26
|
+
if status = options.fetch(:status, :success)
|
27
|
+
status = STATUS_MAP[status] if STATUS_MAP.has_key?(status)
|
28
|
+
assert_status(status, msg)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def assert_status(status, msg)
|
33
|
+
msg = format_msg("Status not '#{status}'", msg)
|
34
|
+
assert_block(msg) { @context.status == status }
|
35
|
+
end
|
36
|
+
|
37
|
+
#--
|
38
|
+
# Compile some helpers.
|
39
|
+
#++
|
40
|
+
|
41
|
+
for m in [:get, :post, :put, :delete, :head]
|
42
|
+
eval %{
|
43
|
+
def assert_#{m}(uri, headers = {}, params = {}, session = nil)
|
44
|
+
#{m}(uri, headers, params, session)
|
45
|
+
assert_response :success
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def assert_output(options = {})
|
51
|
+
msg = options[:msg]
|
52
|
+
if re = options[:match] || options[:contains]
|
53
|
+
assert_output_match(re, msg)
|
54
|
+
end
|
55
|
+
if re = options[:no_match] || options[:contains_no]
|
56
|
+
assert_output_not_match(re, msg)
|
57
|
+
end
|
58
|
+
if content_type = options[:content_type]
|
59
|
+
assert_content_type(content_type, msg)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def assert_output_match(re, msg)
|
64
|
+
msg = format_msg("Rendered output does not match '#{re.source}'", msg)
|
65
|
+
assert_block(msg) { @context.body =~ Regexp.new(re) }
|
66
|
+
end
|
67
|
+
alias_method :assert_output_contains, :assert_output_match
|
68
|
+
|
69
|
+
def assert_output_not_match(re, msg)
|
70
|
+
msg = format_msg("Rendered output matches '#{re.source}'", msg)
|
71
|
+
assert_block(msg) { @context.out =~ Regexp.new(re) }
|
72
|
+
end
|
73
|
+
alias_method :assert_output_contains_not, :assert_output_match
|
74
|
+
|
75
|
+
def assert_content_type(ctype, msg)
|
76
|
+
msg = format_msg("Content type is not '#{ctype}' as expected", msg)
|
77
|
+
assert_block(msg) { @context.content_type == ctype }
|
78
|
+
end
|
79
|
+
|
80
|
+
# :section: Session related assertions.
|
81
|
+
|
82
|
+
def assert_session(options = {})
|
83
|
+
msg = options[:msg]
|
84
|
+
if key = options[:has]
|
85
|
+
assert_session_has(key, msg)
|
86
|
+
end
|
87
|
+
if key = options[:has_no] || options[:no]
|
88
|
+
assert_session_has_no(key, msg)
|
89
|
+
end
|
90
|
+
if key = options[:key] and value = options[:value]
|
91
|
+
assert_session_equal(key, value, msg)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def assert_session_has(key, msg = nil)
|
96
|
+
msg = format_msg("Object '#{key}' not found in session", msg)
|
97
|
+
assert_block(msg) { @context.session[key] }
|
98
|
+
end
|
99
|
+
|
100
|
+
def assert_session_has_no(key, msg = nil)
|
101
|
+
msg = format_msg("Unexpected object '#{key}' found in session", msg)
|
102
|
+
assert_block(msg) { !@context.session[key] }
|
103
|
+
end
|
104
|
+
|
105
|
+
def assert_session_equal(key, value, msg = nil)
|
106
|
+
msg = format_msg("The value of session object '#{key}' is '#{@context.session[key]}' but was expected '#{value}'", msg)
|
107
|
+
assert_block(msg) { @context.session[key] == value }
|
108
|
+
end
|
109
|
+
|
110
|
+
# :section: Cookies related assertions.
|
111
|
+
|
112
|
+
def assert_cookie(options = {})
|
113
|
+
msg = options[:msg]
|
114
|
+
if key = options[:has]
|
115
|
+
assert_cookie_has(key, msg)
|
116
|
+
end
|
117
|
+
if key = options[:has_no] || options[:no]
|
118
|
+
assert_cookie_has_no(key, msg)
|
119
|
+
end
|
120
|
+
if key = options[:key] and value = options[:value]
|
121
|
+
assert_cookie_equal(key, value, msg)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def assert_cookie_has(name, msg = nil)
|
126
|
+
msg = format_msg("Cookie '#{name}' not found", msg)
|
127
|
+
assert_block(msg) { @context.response_cookie(name) }
|
128
|
+
end
|
129
|
+
|
130
|
+
def assert_cookie_has_no(name, msg = nil)
|
131
|
+
msg = format_msg("Unexpected cookie '#{name}' found", msg)
|
132
|
+
assert_block(msg) { !@context.response_cookie(name) }
|
133
|
+
end
|
134
|
+
|
135
|
+
def assert_cookie_equal(name, value, msg = nil)
|
136
|
+
unless cookie = @context.response_cookie(name)
|
137
|
+
msg = format_msg("Cookie '#{name}' not found", msg)
|
138
|
+
assert_block(msg) { false }
|
139
|
+
end
|
140
|
+
msg = format_msg("The value of cookie '#{name}' is '#{cookie.value}' but was expected '#{value}'", msg)
|
141
|
+
assert_block(msg) { cookie.value == value }
|
142
|
+
end
|
143
|
+
|
144
|
+
# :section: Template related assertions.
|
145
|
+
|
146
|
+
# :section: Redirection assertions.
|
147
|
+
|
148
|
+
def assert_redirected(options = {})
|
149
|
+
msg = options[:msg]
|
150
|
+
|
151
|
+
msg = format_msg("No redirection (status = #{@context.status})", msg)
|
152
|
+
assert_block(msg) { @context.redirect? }
|
153
|
+
|
154
|
+
if to = options[:to]
|
155
|
+
msg = format_msg("Not redirected to '#{to}'", msg)
|
156
|
+
assert_block(msg) { @context.response_headers['location'] == "http://#{to}" }
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def assert_not_redirected(options = {})
|
161
|
+
msg = options[:msg]
|
162
|
+
msg = format_msg("Unexpected redirection (location = '#{@context.response_headers['location']}')", msg)
|
163
|
+
assert_block(msg) { !@context.redirect? }
|
164
|
+
end
|
165
|
+
|
166
|
+
# :section: Utility methods
|
167
|
+
|
168
|
+
def format_msg(message, extra) # :nodoc:
|
169
|
+
extra += ', ' if extra
|
170
|
+
return "#{extra}#{message}"
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
# * George Moschovitis <gm@navel.gr>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/unit/assertions'
|
3
|
+
|
4
|
+
require 'facet/string/underscore'
|
5
|
+
require 'facet/string/demodulize'
|
6
|
+
require 'facet/string/pluralize'
|
7
|
+
|
8
|
+
require 'glue'
|
9
|
+
require 'glue/fixture'
|
10
|
+
require 'og'
|
11
|
+
require 'og/test/assertions'
|
12
|
+
|
13
|
+
module Test::Unit
|
14
|
+
|
15
|
+
class TestCase
|
16
|
+
|
17
|
+
# Include fixtures in this test case.
|
18
|
+
#--
|
19
|
+
# gmosx: this method should probably be moved to glue.
|
20
|
+
#++
|
21
|
+
|
22
|
+
def fixture(*classes)
|
23
|
+
|
24
|
+
for klass in classes
|
25
|
+
f = Fixture.new(klass)
|
26
|
+
instance_variable_set "@#{klass.to_s.demodulize.underscore.pluralize}", f
|
27
|
+
Fixtures[klass] = f
|
28
|
+
|
29
|
+
# create variables for the fixture objects.
|
30
|
+
|
31
|
+
for name, obj in f
|
32
|
+
instance_variable_set "@#{name}", obj
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
# Include fixtures in this test case, and serialize them in
|
39
|
+
# the active Og store.
|
40
|
+
|
41
|
+
def og_fixture(*classes)
|
42
|
+
fixture(*classes)
|
43
|
+
|
44
|
+
for klass in classes
|
45
|
+
f = Fixtures[klass]
|
46
|
+
|
47
|
+
for obj in f.objects
|
48
|
+
obj.save
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# * George Moschovitis <gm@navel.gr>
|
data/test/og/store/tc_filesys.rb
CHANGED
@@ -40,8 +40,8 @@ class TestCaseOgFilesys < Test::Unit::TestCase # :nodoc: all
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def test_all
|
43
|
-
# p Comment.
|
44
|
-
# p Article.
|
43
|
+
# p Comment.metadata
|
44
|
+
# p Article.metadata
|
45
45
|
|
46
46
|
a1 = Article.new('Article 1')
|
47
47
|
@og.store.save(a1)
|
@@ -65,7 +65,7 @@ class TestCaseOgFilesys < Test::Unit::TestCase # :nodoc: all
|
|
65
65
|
# a = Article[1]
|
66
66
|
|
67
67
|
@og.store.close
|
68
|
-
|
68
|
+
# @og.store.class.destroy(@og.options)
|
69
69
|
end
|
70
70
|
|
71
71
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
|
3
|
+
$DBG = true
|
4
|
+
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
require 'og'
|
8
|
+
|
9
|
+
$og1 = Og.setup(
|
10
|
+
:destroy => true,
|
11
|
+
:store => :mysql,
|
12
|
+
:user => 'root',
|
13
|
+
:password => 'navelrulez',
|
14
|
+
:name => 'test'
|
15
|
+
)
|
16
|
+
|
17
|
+
$og2 = Og.setup(
|
18
|
+
:destroy => true,
|
19
|
+
:store => :psql,
|
20
|
+
:user => 'postgres',
|
21
|
+
:password => 'navelrulez',
|
22
|
+
:name => 'test'
|
23
|
+
)
|
24
|
+
|
25
|
+
class TestMultiple < Test::Unit::TestCase # :nodoc: all
|
26
|
+
include Og
|
27
|
+
|
28
|
+
class User
|
29
|
+
property :name, String, :uniq => true
|
30
|
+
has_many Article
|
31
|
+
|
32
|
+
def initialize(name)
|
33
|
+
@name = name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Article
|
38
|
+
property :title, String
|
39
|
+
belongs_to User
|
40
|
+
|
41
|
+
def initialize(title)
|
42
|
+
@title = title
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_all
|
47
|
+
$og1.manage_class Article
|
48
|
+
$og2.manage_class User
|
49
|
+
|
50
|
+
assert Article.ogmanager.store.is_a?(Og::MysqlStore)
|
51
|
+
assert User.ogmanager.store.is_a?(Og::PsqlStore)
|
52
|
+
|
53
|
+
a1 = Article.create('hello')
|
54
|
+
a2 = Article.create('world')
|
55
|
+
|
56
|
+
u = User.create('gmosx')
|
57
|
+
|
58
|
+
assert_equal 2, Article.count
|
59
|
+
|
60
|
+
u.articles << a1
|
61
|
+
u.articles << a2
|
62
|
+
|
63
|
+
gmosx = User.find_by_name('gmosx')
|
64
|
+
assert_equal 2, gmosx.articles.size
|
65
|
+
assert_equal 'hello', gmosx.articles[0].title
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/test/og/tc_polymorphic.rb
CHANGED
@@ -39,9 +39,15 @@ class TC_OgPolymorphic < Test::Unit::TestCase # :nodoc: all
|
|
39
39
|
|
40
40
|
def setup
|
41
41
|
@og = Og.setup(
|
42
|
+
=begin
|
42
43
|
:destroy => true,
|
43
44
|
:store => :sqlite,
|
44
45
|
:name => 'test'
|
46
|
+
=end
|
47
|
+
:store => :mysql,
|
48
|
+
:name => 'testreverse',
|
49
|
+
:user => 'root',
|
50
|
+
:password => 'navelrulez'
|
45
51
|
)
|
46
52
|
end
|
47
53
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
|
3
|
+
$DBG = true
|
4
|
+
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
require 'og'
|
8
|
+
|
9
|
+
# 'testreverse' is a legacy database schema. Og's advanced
|
10
|
+
# reverse engineering features allows us to map any schema
|
11
|
+
# to our objects.
|
12
|
+
|
13
|
+
$og = Og.setup(
|
14
|
+
:destroy => true,
|
15
|
+
:store => :mysql,
|
16
|
+
:name => 'testreverse',
|
17
|
+
:user => 'root',
|
18
|
+
:password => 'navelrulez'
|
19
|
+
)
|
20
|
+
|
21
|
+
# create a 'legacy' schema.
|
22
|
+
|
23
|
+
$og.store.exec "create table my_users (thename VARCHAR(32) PRIMARY KEY, password TEXT, age3 INTEGER);"
|
24
|
+
$og.store.exec "create table my_comments (cid MEDIUMINT NOT NULL AUTO_INCREMENT, body TEXT, user VARCHAR(32), PRIMARY KEY(cid));"
|
25
|
+
|
26
|
+
class User
|
27
|
+
property :name, String, :field => :thename, :uniq => true
|
28
|
+
property :password, String
|
29
|
+
property :age, Fixnum, :field => :age3
|
30
|
+
has_many Comment, :foreign_field => :user
|
31
|
+
set_table :my_users
|
32
|
+
set_primary_key :name, String
|
33
|
+
|
34
|
+
def initialize(name, password, age)
|
35
|
+
@name, @password, @age = name, password, age
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Comment
|
40
|
+
property :cid, Fixnum
|
41
|
+
property :body, String
|
42
|
+
belongs_to User, :field => :user
|
43
|
+
set_table :my_comments
|
44
|
+
set_primary_key :cid
|
45
|
+
|
46
|
+
def initialize(body)
|
47
|
+
@body = body
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
$og.manage_classes
|
52
|
+
|
53
|
+
class TestReverse < Test::Unit::TestCase # :nodoc: all
|
54
|
+
include Og
|
55
|
+
|
56
|
+
def test_all
|
57
|
+
assert_equal 'my_users', User.table
|
58
|
+
assert_equal 'my_comments', Comment.table
|
59
|
+
|
60
|
+
User.new('gmosx', 'navel', 30).insert
|
61
|
+
User.new('Helen', 'kontesa', 25).insert
|
62
|
+
|
63
|
+
gmosx = User.find_by_name('gmosx')
|
64
|
+
assert_equal 'gmosx', gmosx.name
|
65
|
+
|
66
|
+
helen = User.find_by_age(25).first
|
67
|
+
assert_equal 'Helen', helen.name
|
68
|
+
|
69
|
+
c = Comment.new('hello')
|
70
|
+
c.insert
|
71
|
+
helen.comments << c
|
72
|
+
|
73
|
+
assert_equal 1, helen.comments(:reload => true).size
|
74
|
+
assert_equal 'hello', helen.comments[0].body
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# * George Moschovitis <gm@navel.gr>
|
data/test/og/tc_store.rb
CHANGED
@@ -44,7 +44,7 @@ class TCOgStore < Test::Unit::TestCase # :nodoc: all
|
|
44
44
|
class NewArticle < Article
|
45
45
|
property :more_text, String
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
class Comment
|
49
49
|
property :body, String
|
50
50
|
property :hits, Fixnum
|
@@ -103,7 +103,7 @@ class TCOgStore < Test::Unit::TestCase # :nodoc: all
|
|
103
103
|
conversions_test
|
104
104
|
end
|
105
105
|
=end
|
106
|
-
|
106
|
+
#=begin
|
107
107
|
def test_mysql
|
108
108
|
@og = Og.setup(
|
109
109
|
:destroy => true,
|
@@ -116,8 +116,8 @@ class TCOgStore < Test::Unit::TestCase # :nodoc: all
|
|
116
116
|
features_test
|
117
117
|
# conversions_test
|
118
118
|
end
|
119
|
-
|
120
|
-
|
119
|
+
#=end
|
120
|
+
=begin
|
121
121
|
def test_sqlite
|
122
122
|
@og = Og.setup(
|
123
123
|
:destroy => true,
|
@@ -127,7 +127,7 @@ class TCOgStore < Test::Unit::TestCase # :nodoc: all
|
|
127
127
|
features_test
|
128
128
|
conversions_test
|
129
129
|
end
|
130
|
-
|
130
|
+
=end
|
131
131
|
=begin
|
132
132
|
def test_memory
|
133
133
|
@og = Og.setup(
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: og
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2005-07
|
6
|
+
version: 0.22.0
|
7
|
+
date: 2005-08-07 00:00:00 +03:00
|
8
8
|
summary: Og (ObjectGraph)
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -60,8 +60,9 @@ files:
|
|
60
60
|
- lib/og/errors.rb
|
61
61
|
- lib/og/store.rb
|
62
62
|
- lib/og/validation.rb
|
63
|
-
- lib/og/testing
|
64
63
|
- lib/og/types.rb
|
64
|
+
- lib/og/test
|
65
|
+
- lib/og/test.rb
|
65
66
|
- lib/og/relation/belongs_to.rb
|
66
67
|
- lib/og/relation/has_many.rb
|
67
68
|
- lib/og/relation/has_one.rb
|
@@ -81,6 +82,8 @@ files:
|
|
81
82
|
- lib/og/store/sqlite.rb
|
82
83
|
- lib/og/store/kirby.rb
|
83
84
|
- lib/og/store/memory.rb
|
85
|
+
- lib/og/test/assertions.rb
|
86
|
+
- lib/og/test/testcase.rb
|
84
87
|
- lib/vendor/mysql411.rb
|
85
88
|
- lib/vendor/mysql.rb
|
86
89
|
- lib/vendor/kirbybase.rb
|
@@ -95,6 +98,8 @@ files:
|
|
95
98
|
- test/og/tc_polymorphic.rb
|
96
99
|
- test/og/tc_join.rb
|
97
100
|
- test/og/tc_select.rb
|
101
|
+
- test/og/tc_reverse.rb
|
102
|
+
- test/og/tc_multiple.rb
|
98
103
|
- test/og/store/tc_filesys.rb
|
99
104
|
- test/og/mixin/tc_hierarchical.rb
|
100
105
|
- test/og/mixin/tc_orderable.rb
|
@@ -124,5 +129,5 @@ dependencies:
|
|
124
129
|
-
|
125
130
|
- "="
|
126
131
|
- !ruby/object:Gem::Version
|
127
|
-
version: 0.
|
132
|
+
version: 0.22.0
|
128
133
|
version:
|