rufus-doric 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.txt +9 -1
- data/TODO.txt +1 -1
- data/lib/rufus/doric/model.rb +117 -16
- data/lib/rufus/doric/models.rb +4 -0
- data/lib/rufus/doric/version.rb +1 -1
- data/rufus-doric.gemspec +5 -3
- data/test/ut_1_model.rb +23 -0
- data/test/ut_6_model_associations.rb +21 -10
- data/test/ut_7_looser_associations.rb +104 -0
- data/test/ut_8_belongings.rb +92 -0
- metadata +5 -3
data/CHANGELOG.txt
CHANGED
@@ -2,7 +2,15 @@
|
|
2
2
|
= rufus-doric CHANGELOG.txt
|
3
3
|
|
4
4
|
|
5
|
-
== rufus-doric - 0.1.
|
5
|
+
== rufus-doric - 0.1.2 released 2010/03/23
|
6
|
+
|
7
|
+
- person.belongings() returns all the object whose person_id is person._id
|
8
|
+
- multi-class associations : owner.vehicles.collect &class #=> [ Car, Boat ]
|
9
|
+
- introduced the Rufus::Doric.types hash ({ 'car' => MyDomain::Car })
|
10
|
+
- added property as an alias to h_accessor
|
11
|
+
|
12
|
+
|
13
|
+
== rufus-doric - 0.1.1 released 2010/03/22
|
6
14
|
|
7
15
|
- associations are in (_id[s]) for Model
|
8
16
|
- equality and hash for Model
|
data/TODO.txt
CHANGED
data/lib/rufus/doric/model.rb
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
# Made in Japan.
|
23
23
|
#++
|
24
24
|
|
25
|
-
|
25
|
+
require 'cgi'
|
26
26
|
|
27
27
|
|
28
28
|
module Rufus
|
@@ -41,6 +41,39 @@ module Doric
|
|
41
41
|
}
|
42
42
|
}
|
43
43
|
|
44
|
+
# Returns a hash of all the types (models) seen/registered.
|
45
|
+
#
|
46
|
+
# For example, after this class definition :
|
47
|
+
#
|
48
|
+
# class Concept < Rufus::Doric::Model
|
49
|
+
# db :doric
|
50
|
+
# doric_type :concepts
|
51
|
+
# _id_field :name
|
52
|
+
# property :name
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# this
|
56
|
+
#
|
57
|
+
# p Rufus::Doric.types
|
58
|
+
#
|
59
|
+
# will yield
|
60
|
+
#
|
61
|
+
# {"concepts"=>Concept}
|
62
|
+
#
|
63
|
+
def self.types
|
64
|
+
|
65
|
+
(@types ||= {})
|
66
|
+
end
|
67
|
+
|
68
|
+
# Given a document (a Hash instance), will look at its 'doric_type' and
|
69
|
+
# return an instance of a Rufus::Doric::Model or nil if there is
|
70
|
+
# no model defined for that doric_type
|
71
|
+
#
|
72
|
+
def self.instantiate (doc)
|
73
|
+
|
74
|
+
(types[doc['doric_type']].new(doc) rescue nil)
|
75
|
+
end
|
76
|
+
|
44
77
|
#
|
45
78
|
# Classes extending that class have 1 Couch document per instance
|
46
79
|
#
|
@@ -54,7 +87,11 @@ module Doric
|
|
54
87
|
|
55
88
|
def self.doric_type (rt=nil)
|
56
89
|
|
57
|
-
|
90
|
+
if rt
|
91
|
+
@doric_type = rt.to_s
|
92
|
+
Rufus::Doric.types[@doric_type] = self
|
93
|
+
end
|
94
|
+
|
58
95
|
@doric_type
|
59
96
|
end
|
60
97
|
|
@@ -179,6 +216,62 @@ module Doric
|
|
179
216
|
delete
|
180
217
|
end
|
181
218
|
|
219
|
+
# Returns all the other objects in the same db that have a {something}_id
|
220
|
+
# pointing to this object.
|
221
|
+
#
|
222
|
+
# For example, given
|
223
|
+
#
|
224
|
+
# Person.new(
|
225
|
+
# :name => 'friedrisch', :vehicle_id => 'GE1212'
|
226
|
+
# ).save!
|
227
|
+
#
|
228
|
+
# Book.new(
|
229
|
+
# :description => 'romance of the three kingdoms',
|
230
|
+
# :person_id => 'friedrisch'
|
231
|
+
# ).save!
|
232
|
+
# Computer.new(
|
233
|
+
# :description => 'black macbook',
|
234
|
+
# :person_id => 'friedrisch'
|
235
|
+
# ).save!
|
236
|
+
#
|
237
|
+
# then
|
238
|
+
#
|
239
|
+
# f = Person.find('friedrisch')
|
240
|
+
# p f.belongings.map { |b| b.class.name }.sort)
|
241
|
+
#
|
242
|
+
# will print
|
243
|
+
#
|
244
|
+
# ["Book", "Computer"]
|
245
|
+
#
|
246
|
+
def belongings
|
247
|
+
|
248
|
+
dd = db.get('_design/doric') || DORIC_DESIGN_DOC
|
249
|
+
|
250
|
+
s = self.class.doric_type.singularize
|
251
|
+
|
252
|
+
view = "by_#{s}_id"
|
253
|
+
|
254
|
+
unless dd['views'][view]
|
255
|
+
|
256
|
+
dd['views'][view] = {
|
257
|
+
'map' => %{
|
258
|
+
function (doc) {
|
259
|
+
if (doc.doric_type && doc.#{s}_id) emit(doc.#{s}_id, null);
|
260
|
+
}
|
261
|
+
}
|
262
|
+
}
|
263
|
+
db.put(dd)
|
264
|
+
end
|
265
|
+
|
266
|
+
i = CGI.escape(Rufus::Json.encode(_id))
|
267
|
+
|
268
|
+
result = db.get("_design/doric/_view/#{view}?key=#{i}&include_docs=true")
|
269
|
+
|
270
|
+
result['rows'].collect { |r| Rufus::Doric.instantiate(r['doc']) }
|
271
|
+
end
|
272
|
+
|
273
|
+
# All the association magic occur here, except for #belongings
|
274
|
+
#
|
182
275
|
def method_missing (m, *args)
|
183
276
|
|
184
277
|
mm = m.to_s
|
@@ -188,10 +281,30 @@ module Doric
|
|
188
281
|
klass = sm.camelize
|
189
282
|
klass = (self.class.const_get(klass) rescue nil)
|
190
283
|
|
191
|
-
return super unless klass
|
284
|
+
#return super unless klass
|
192
285
|
|
193
286
|
id_method = multiple ? "#{sm}_ids" : "#{mm}_id"
|
194
287
|
|
288
|
+
unless klass
|
289
|
+
|
290
|
+
return super unless self.respond_to?(id_method)
|
291
|
+
|
292
|
+
i = self.send(id_method)
|
293
|
+
|
294
|
+
if multiple
|
295
|
+
|
296
|
+
return [] unless i
|
297
|
+
|
298
|
+
return i.collect { |ii|
|
299
|
+
Rufus::Doric.instantiate(db.get(ii))
|
300
|
+
}.select { |e|
|
301
|
+
e != nil
|
302
|
+
}
|
303
|
+
end
|
304
|
+
|
305
|
+
return Rufus::Doric.instantiate(db.get(i))
|
306
|
+
end
|
307
|
+
|
195
308
|
if multiple
|
196
309
|
|
197
310
|
if self.respond_to?(id_method)
|
@@ -210,6 +323,7 @@ module Doric
|
|
210
323
|
else
|
211
324
|
|
212
325
|
return super unless self.respond_to?(id_method)
|
326
|
+
|
213
327
|
klass.find(self.send(id_method))
|
214
328
|
end
|
215
329
|
end
|
@@ -265,19 +379,6 @@ module Doric
|
|
265
379
|
|
266
380
|
# by_{key} views
|
267
381
|
|
268
|
-
x = {
|
269
|
-
'_id' => '_design/doric',
|
270
|
-
'views' => {
|
271
|
-
'by_doric_type' => {
|
272
|
-
'map' => %{
|
273
|
-
function(doc) {
|
274
|
-
if (doc.doric_type) emit(doc.doric_type, null);
|
275
|
-
}
|
276
|
-
}
|
277
|
-
}
|
278
|
-
}
|
279
|
-
}
|
280
|
-
|
281
382
|
ddoc = db.get(design_path) || {
|
282
383
|
'_id' => design_path,
|
283
384
|
'views' => {}
|
data/lib/rufus/doric/models.rb
CHANGED
@@ -38,6 +38,7 @@ module Doric
|
|
38
38
|
|
39
39
|
#
|
40
40
|
# The including classes get two new class methods : h_reader and h_accessor
|
41
|
+
# plus property as an alias to h_accessor
|
41
42
|
#
|
42
43
|
module WithH
|
43
44
|
|
@@ -64,6 +65,9 @@ module Doric
|
|
64
65
|
end
|
65
66
|
end
|
66
67
|
end
|
68
|
+
def target.property (*names)
|
69
|
+
h_accessor(*names)
|
70
|
+
end
|
67
71
|
end
|
68
72
|
end
|
69
73
|
|
data/lib/rufus/doric/version.rb
CHANGED
data/rufus-doric.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rufus-doric}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["John Mettraux"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-23}
|
13
13
|
s.description = %q{
|
14
14
|
something at the intersection of Rails3, CouchDB and rufus-jig
|
15
15
|
}
|
@@ -51,7 +51,9 @@ something at the intersection of Rails3, CouchDB and rufus-jig
|
|
51
51
|
"test/ut_3_model_lint.rb",
|
52
52
|
"test/ut_4_one_doc_model.rb",
|
53
53
|
"test/ut_5_value.rb",
|
54
|
-
"test/ut_6_model_associations.rb"
|
54
|
+
"test/ut_6_model_associations.rb",
|
55
|
+
"test/ut_7_looser_associations.rb",
|
56
|
+
"test/ut_8_belongings.rb"
|
55
57
|
]
|
56
58
|
s.homepage = %q{http://github.com/jmettraux/rufus-doric/}
|
57
59
|
s.rdoc_options = ["--charset=UTF-8"]
|
data/test/ut_1_model.rb
CHANGED
@@ -32,6 +32,14 @@ class Item < Rufus::Doric::Model
|
|
32
32
|
validates :supplier, :presence => true
|
33
33
|
end
|
34
34
|
|
35
|
+
class Concept < Rufus::Doric::Model
|
36
|
+
|
37
|
+
db :doric
|
38
|
+
doric_type :concepts
|
39
|
+
_id_field :name
|
40
|
+
property :name
|
41
|
+
end
|
42
|
+
|
35
43
|
|
36
44
|
class UtModelTest < Test::Unit::TestCase
|
37
45
|
|
@@ -48,6 +56,12 @@ class UtModelTest < Test::Unit::TestCase
|
|
48
56
|
#def teardown
|
49
57
|
#end
|
50
58
|
|
59
|
+
def test_types
|
60
|
+
|
61
|
+
assert_equal Hash, Rufus::Doric.types.class
|
62
|
+
assert_equal Concept, Rufus::Doric.types['concepts']
|
63
|
+
end
|
64
|
+
|
51
65
|
def test_save
|
52
66
|
|
53
67
|
Thing.new(
|
@@ -151,5 +165,14 @@ class UtModelTest < Test::Unit::TestCase
|
|
151
165
|
assert_not_equal a, c
|
152
166
|
assert_not_equal a.hash, c.hash
|
153
167
|
end
|
168
|
+
|
169
|
+
def test_property
|
170
|
+
|
171
|
+
Concept.new('name' => 'art').save!
|
172
|
+
|
173
|
+
c = Concept.find('art')
|
174
|
+
|
175
|
+
assert_equal 'art', c.name
|
176
|
+
end
|
154
177
|
end
|
155
178
|
|
@@ -56,7 +56,7 @@ class Order < Rufus::Doric::Model
|
|
56
56
|
end
|
57
57
|
|
58
58
|
|
59
|
-
class
|
59
|
+
class UtModelAssociationsTest < Test::Unit::TestCase
|
60
60
|
|
61
61
|
def setup
|
62
62
|
|
@@ -83,6 +83,9 @@ class UtModelTest < Test::Unit::TestCase
|
|
83
83
|
Interest.new(:name => 'litterature').save!
|
84
84
|
Interest.new(:name => 'music').save!
|
85
85
|
Interest.new(:name => 'dance').save!
|
86
|
+
|
87
|
+
@fred = Customer.find('fred')
|
88
|
+
@famke = Customer.find('famke')
|
86
89
|
end
|
87
90
|
|
88
91
|
#def teardown
|
@@ -91,9 +94,8 @@ class UtModelTest < Test::Unit::TestCase
|
|
91
94
|
def test_customer
|
92
95
|
|
93
96
|
o = Order.find('a')
|
94
|
-
c = Customer.find('fred')
|
95
97
|
|
96
|
-
assert_equal
|
98
|
+
assert_equal @fred, o.customer
|
97
99
|
end
|
98
100
|
|
99
101
|
def test_missing_customer
|
@@ -105,9 +107,7 @@ class UtModelTest < Test::Unit::TestCase
|
|
105
107
|
|
106
108
|
def test_orders
|
107
109
|
|
108
|
-
|
109
|
-
|
110
|
-
os = c.orders
|
110
|
+
os = @fred.orders
|
111
111
|
|
112
112
|
assert_equal 2, os.size
|
113
113
|
assert_equal [ Order ], os.collect { |o| o.class }.sort.uniq
|
@@ -115,11 +115,22 @@ class UtModelTest < Test::Unit::TestCase
|
|
115
115
|
|
116
116
|
def test_interests
|
117
117
|
|
118
|
-
|
119
|
-
famke
|
118
|
+
assert_equal [], @fred.interests
|
119
|
+
assert_equal %w[ dance music ], @famke.interests.collect { |i| i.name }.sort
|
120
|
+
end
|
120
121
|
|
121
|
-
|
122
|
-
|
122
|
+
def test_no_link
|
123
|
+
|
124
|
+
assert_raise NoMethodError do
|
125
|
+
@fred.car
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_no_links
|
130
|
+
|
131
|
+
assert_raise NoMethodError do
|
132
|
+
@fred.vehicles
|
133
|
+
end
|
123
134
|
end
|
124
135
|
end
|
125
136
|
|
@@ -0,0 +1,104 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# testing rufus-doric
|
4
|
+
#
|
5
|
+
# Tue Mar 23 11:07:23 JST 2010
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), 'base')
|
9
|
+
|
10
|
+
require 'rufus/doric'
|
11
|
+
|
12
|
+
|
13
|
+
class Owner < Rufus::Doric::Model
|
14
|
+
|
15
|
+
db :doric
|
16
|
+
doric_type :owners
|
17
|
+
|
18
|
+
_id_field :name
|
19
|
+
|
20
|
+
property :name
|
21
|
+
property :vehicle_id
|
22
|
+
end
|
23
|
+
|
24
|
+
class Car < Rufus::Doric::Model
|
25
|
+
|
26
|
+
db :doric
|
27
|
+
doric_type :cars
|
28
|
+
|
29
|
+
_id_field :plate
|
30
|
+
|
31
|
+
property :plate
|
32
|
+
end
|
33
|
+
|
34
|
+
class Boat < Rufus::Doric::Model
|
35
|
+
|
36
|
+
db :doric
|
37
|
+
doric_type :boats
|
38
|
+
|
39
|
+
_id_field :immatriculation
|
40
|
+
|
41
|
+
property :immatriculation
|
42
|
+
end
|
43
|
+
|
44
|
+
class SuperOwner < Rufus::Doric::Model
|
45
|
+
|
46
|
+
db :doric
|
47
|
+
doric_type :super_owners
|
48
|
+
|
49
|
+
_id_field :name
|
50
|
+
|
51
|
+
property :name
|
52
|
+
property :vehicle_ids
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
class UtLooserAssocationsTest < Test::Unit::TestCase
|
57
|
+
|
58
|
+
def setup
|
59
|
+
|
60
|
+
Rufus::Doric.db('doric').delete('.')
|
61
|
+
Rufus::Doric.db('doric').put('.')
|
62
|
+
|
63
|
+
Rufus::Doric.db('doric').http.cache.clear
|
64
|
+
# CouchDB feeds the same etags for views, even after a db has
|
65
|
+
# been deleted and put back, so have to do that 'forgetting'
|
66
|
+
|
67
|
+
Owner.new(
|
68
|
+
:name => 'fred', :vehicle_id => 'GE1212'
|
69
|
+
).save!
|
70
|
+
Owner.new(
|
71
|
+
:name => 'famke', :vehicle_id => 'GE1313'
|
72
|
+
).save!
|
73
|
+
Owner.new(
|
74
|
+
:name => 'fellini', :vehicle_id => 'TO45R4'
|
75
|
+
).save!
|
76
|
+
|
77
|
+
Car.new(:plate => 'GE1212').save!
|
78
|
+
Boat.new(:immatriculation => 'GE1313').save!
|
79
|
+
|
80
|
+
SuperOwner.new(
|
81
|
+
:name => 'aristotle', :vehicle_ids => %w[ GE1212 GE1313 NADA ]).save!
|
82
|
+
|
83
|
+
@fred = Owner.find('fred')
|
84
|
+
@famke = Owner.find('famke')
|
85
|
+
@fellini = Owner.find('fellini')
|
86
|
+
@aristotle = SuperOwner.find('aristotle')
|
87
|
+
end
|
88
|
+
|
89
|
+
#def teardown
|
90
|
+
#end
|
91
|
+
|
92
|
+
def test_vehicles
|
93
|
+
|
94
|
+
assert_equal Car, @fred.vehicle.class
|
95
|
+
assert_equal Boat, @famke.vehicle.class
|
96
|
+
assert_nil @fellini.vehicle
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_super_owner
|
100
|
+
|
101
|
+
assert_equal [ Car, Boat ], @aristotle.vehicles.collect { |v| v.class }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# testing rufus-doric
|
4
|
+
#
|
5
|
+
# Tue Mar 23 13:23:31 JST 2010
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), 'base')
|
9
|
+
|
10
|
+
require 'rufus/doric'
|
11
|
+
|
12
|
+
|
13
|
+
class Person < Rufus::Doric::Model
|
14
|
+
|
15
|
+
db :doric
|
16
|
+
doric_type :persons
|
17
|
+
|
18
|
+
_id_field :name
|
19
|
+
|
20
|
+
property :name
|
21
|
+
end
|
22
|
+
|
23
|
+
class Book < Rufus::Doric::Model
|
24
|
+
|
25
|
+
db :doric
|
26
|
+
doric_type :books
|
27
|
+
|
28
|
+
_id_field :description
|
29
|
+
|
30
|
+
property :description
|
31
|
+
property :person_id
|
32
|
+
end
|
33
|
+
|
34
|
+
class Computer < Rufus::Doric::Model
|
35
|
+
|
36
|
+
db :doric
|
37
|
+
doric_type :computers
|
38
|
+
|
39
|
+
_id_field :description
|
40
|
+
|
41
|
+
property :description
|
42
|
+
property :person_id
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
class UtBelongingsTest < Test::Unit::TestCase
|
47
|
+
|
48
|
+
def setup
|
49
|
+
|
50
|
+
Rufus::Doric.db('doric').delete('.')
|
51
|
+
Rufus::Doric.db('doric').put('.')
|
52
|
+
|
53
|
+
Rufus::Doric.db('doric').http.cache.clear
|
54
|
+
# CouchDB feeds the same etags for views, even after a db has
|
55
|
+
# been deleted and put back, so have to do that 'forgetting'
|
56
|
+
|
57
|
+
Person.new(
|
58
|
+
:name => 'friedrisch', :vehicle_id => 'GE1212'
|
59
|
+
).save!
|
60
|
+
|
61
|
+
Book.new(
|
62
|
+
:description => 'romance of the three kingdoms',
|
63
|
+
:person_id => 'friedrisch'
|
64
|
+
).save!
|
65
|
+
Computer.new(
|
66
|
+
:description => 'black macbook',
|
67
|
+
:person_id => 'friedrisch'
|
68
|
+
).save!
|
69
|
+
Computer.new(
|
70
|
+
:description => 'old thinkpad',
|
71
|
+
:person_id => 'vlad'
|
72
|
+
).save!
|
73
|
+
|
74
|
+
@friedrisch = Person.find('friedrisch')
|
75
|
+
end
|
76
|
+
|
77
|
+
#def teardown
|
78
|
+
#end
|
79
|
+
|
80
|
+
def test_belongings
|
81
|
+
|
82
|
+
assert_equal(
|
83
|
+
%w[ Book Computer ],
|
84
|
+
@friedrisch.belongings.map { |b| b.class.name }.sort)
|
85
|
+
|
86
|
+
assert_equal(
|
87
|
+
%w[ Book Computer ],
|
88
|
+
@friedrisch.belongings.map { |b| b.class.name }.sort)
|
89
|
+
# second run shouldn't insert new design_doc
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 2
|
9
|
+
version: 0.1.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- John Mettraux
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-23 00:00:00 +09:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -139,6 +139,8 @@ files:
|
|
139
139
|
- test/ut_4_one_doc_model.rb
|
140
140
|
- test/ut_5_value.rb
|
141
141
|
- test/ut_6_model_associations.rb
|
142
|
+
- test/ut_7_looser_associations.rb
|
143
|
+
- test/ut_8_belongings.rb
|
142
144
|
has_rdoc: true
|
143
145
|
homepage: http://github.com/jmettraux/rufus-doric/
|
144
146
|
licenses: []
|