rufus-doric 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -2,7 +2,15 @@
2
2
  = rufus-doric CHANGELOG.txt
3
3
 
4
4
 
5
- == rufus-doric - 0.1.1 not yet released
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
@@ -3,7 +3,7 @@
3
3
  [o] model : validation
4
4
  [o] destroy/delete
5
5
 
6
- [ ] lsof check (jig / patron)
6
+ [x] lsof check (jig / patron)
7
7
 
8
8
  [ ] all, by : limit and skip (pagination)
9
9
 
@@ -22,7 +22,7 @@
22
22
  # Made in Japan.
23
23
  #++
24
24
 
25
- #require 'cgi'
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
- @doric_type = rt.to_s if rt
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' => {}
@@ -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
 
@@ -1,7 +1,7 @@
1
1
 
2
2
  module Rufus
3
3
  module Doric
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
6
6
  end
7
7
 
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.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-22}
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 UtModelTest < Test::Unit::TestCase
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 c, o.customer
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
- c = Customer.find('fred')
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
- fred = Customer.find('fred')
119
- famke = Customer.find('famke')
118
+ assert_equal [], @fred.interests
119
+ assert_equal %w[ dance music ], @famke.interests.collect { |i| i.name }.sort
120
+ end
120
121
 
121
- assert_equal [], fred.interests
122
- assert_equal %w[ dance music ], famke.interests.collect { |i| i.name }.sort
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
- - 1
9
- version: 0.1.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-22 00:00:00 +09:00
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: []