thingtank 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +72 -90
- data/VERSION +1 -1
- data/test/helper.rb +1 -1
- metadata +19 -19
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
thingtank: play different roles
|
2
2
|
=====================
|
3
3
|
|
4
|
-
ThingTank is a library that uses couchrest and couchrest model create arbitrary
|
4
|
+
ThingTank is a library that uses couchrest and couchrest model to create arbitrary
|
5
5
|
objects that may have different roles. The roles determine the
|
6
6
|
properties and they can be mixed and matched at will.
|
7
7
|
|
@@ -31,33 +31,33 @@ To simplify the class building we let them all inherit from a role class
|
|
31
31
|
validates_presence_of :birth_date # make sure a date is given
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
34
|
Imagine a Caesar is born
|
36
35
|
|
37
36
|
class Born < ThingTank::Role
|
38
37
|
property :birth_date, :alias => :born_at
|
39
38
|
property :birth_place
|
40
|
-
|
41
39
|
validates_presence_of :birth_date # make sure a date is given
|
42
40
|
end
|
43
41
|
|
44
|
-
|
42
|
+
just in case he might die....we might want to have a date and maybe even a place
|
43
|
+
|
45
44
|
class Dead < ThingTank::Role
|
46
45
|
property :date_of_death
|
47
46
|
property :place_of_death
|
48
|
-
|
49
47
|
validates_presence_of :date_of_death
|
50
48
|
end
|
51
49
|
|
50
|
+
and then he needs a name
|
51
|
+
|
52
52
|
class Person < ThingTank::Role
|
53
53
|
property :name
|
54
54
|
property :gender
|
55
|
-
|
56
55
|
validates_presence_of :name
|
57
56
|
end
|
58
57
|
|
58
|
+
now we can create julius
|
59
59
|
|
60
|
-
julius = ThingTank.create
|
60
|
+
julius = ThingTank.create :gender => :m, :name => 'Gaius Iulius Caesar'
|
61
61
|
julius["birth_date"] = "100 BC"
|
62
62
|
julius["birth_place"] = "Rome"
|
63
63
|
julius.is(Born)
|
@@ -73,6 +73,7 @@ Imagine a Caesar is born
|
|
73
73
|
id = julius.id
|
74
74
|
|
75
75
|
later...
|
76
|
+
|
76
77
|
julius = ThingTank.get id
|
77
78
|
julius["birth_date"] # => "100BC"
|
78
79
|
julius.is? Person # => true
|
@@ -86,18 +87,17 @@ when he is adult, he wants to marry. now things are getting a bit more complicat
|
|
86
87
|
property :end # when the marriage ended
|
87
88
|
property :spouse # doc_id of the spouse
|
88
89
|
property :state # state of the marriage
|
89
|
-
|
90
90
|
validates_presence_of :date
|
91
91
|
validates_presence_of :spouse
|
92
92
|
validate :spouse_should_be_a_person
|
93
|
-
|
94
93
|
# ensure that 'spouse' is a doc_id of a Person
|
95
94
|
def spouse_should_be_a_person
|
96
95
|
Person.get(self["spouse"]).valid? # loads doc as role Person and validates
|
97
96
|
end
|
98
97
|
end
|
99
98
|
|
100
|
-
|
99
|
+
we want easy access to the name of the spouse
|
100
|
+
|
101
101
|
class Spouse < ThingTank::Role
|
102
102
|
property :married # doc must have "married" property (should be of class married)
|
103
103
|
property :married_state
|
@@ -130,21 +130,15 @@ now we could easily get julius married
|
|
130
130
|
conny = ThingTank.create :gender => "f", :name => 'Cornelia', :roles => ['Person']
|
131
131
|
julius["married"] = {"date" => "84 BC", "spouse" => conny.id}
|
132
132
|
julius["married_state"] = "married"
|
133
|
-
|
134
133
|
julius.with("married").is(Married).valid? # => true # "married" is a property that plays the Married
|
135
|
-
|
136
134
|
julius.has(Spouse).valid? # #has is an alias of #is
|
137
|
-
|
138
135
|
julius.save
|
139
136
|
julius.reload
|
140
|
-
|
141
137
|
julius.has(Spouse).name # => 'Cornelia'
|
142
138
|
|
143
139
|
while that is nice, let see if we could make it more comfortable:
|
144
140
|
|
145
|
-
|
146
141
|
class Married
|
147
|
-
|
148
142
|
# marry a doc or hash
|
149
143
|
def marry(person)
|
150
144
|
person = ThingTank.new(person) if person.is_a?(Hash)
|
@@ -201,22 +195,16 @@ it now becomes much less work and Cornelia also knows that she is married to Jul
|
|
201
195
|
|
202
196
|
julius.as(Person).marry "84 BC", :gender => "f", :name => 'Cornelia'
|
203
197
|
julius.save
|
204
|
-
julius.reload
|
205
|
-
|
198
|
+
julius.reload
|
206
199
|
julius.has(Spouse).name # => 'Cornelia'
|
207
200
|
julius.has(Spouse).married_state # => 'married'
|
208
|
-
|
209
201
|
conny_id = julius.last_role(Married,"married").spouse
|
210
202
|
conny = ThingTank.get conny_id
|
211
203
|
conny.has(Spouse).married_state # => 'married'
|
212
204
|
|
213
|
-
|
214
205
|
julius could even marry a second time, i.e. marriage becomes an Array of Marriage objects
|
215
206
|
|
216
207
|
julius.as(Person).marry "68-65 BC", :gender => "f", :name => 'Pompeia'
|
217
|
-
|
218
|
-
|
219
|
-
|
220
208
|
Person.get(julius["married"].first["spouse"]).name # => 'Cornelia'
|
221
209
|
Person.get(julius["married"].last["spouse"]).name # => 'Pompeia'
|
222
210
|
julius.has(Spouse).name # => 'Pompeia'
|
@@ -232,87 +220,80 @@ julius is still married with Cornelia but he should not
|
|
232
220
|
|
233
221
|
if Cornelia died before his second marriage, it should'nt be a problem:
|
234
222
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
223
|
+
class Dead
|
224
|
+
# all callbacks of roles are called and defined like corresponding callbacks of the doc
|
225
|
+
before_save do
|
226
|
+
if _doc.is?(Spouse) && _doc['married_state'] == 'married'
|
227
|
+
Spouse.get(_doc.last_role(Married, 'married').spouse).widowed(self["date_of_death"])
|
228
|
+
end
|
229
|
+
true
|
241
230
|
end
|
242
|
-
true
|
243
231
|
end
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
d.date_of_death = date
|
232
|
+
|
233
|
+
class Person
|
234
|
+
def dies(date)
|
235
|
+
_doc.is(Dead) do |d|
|
236
|
+
d.date_of_death = date
|
237
|
+
end
|
251
238
|
end
|
252
239
|
end
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
240
|
+
|
241
|
+
class Married
|
242
|
+
def widow(date)
|
243
|
+
self["state"] = 'widowed'
|
244
|
+
self['end'] = date
|
245
|
+
_doc.save
|
246
|
+
end
|
260
247
|
end
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
248
|
+
|
249
|
+
class Spouse
|
250
|
+
def widowed(date)
|
251
|
+
self["married_state"] = 'widowed'
|
252
|
+
married { |m| m.widow(date) }
|
253
|
+
end
|
267
254
|
end
|
268
|
-
end
|
269
|
-
|
270
|
-
julius.as(Person).marry "84 BC", :gender => "f", :name => 'Cornelia'
|
271
|
-
julius.save
|
272
|
-
julius.reload
|
273
|
-
|
274
|
-
conny = ThingTank.get julius["married"]["spouse"]
|
275
|
-
conny.save
|
276
|
-
conny.reload
|
277
|
-
conny.as(Person).dies "68-65 BC"
|
278
|
-
conny.save
|
279
|
-
|
280
|
-
julius.reload
|
281
|
-
|
282
|
-
julius.as(Person).marry "68-65 BC", :gender => "f", :name => 'Pompeia'
|
283
|
-
|
284
|
-
julius["married"].size # => 2
|
285
|
-
Person.get(julius["married"].first["spouse"]).name # => 'Cornelia'
|
286
|
-
julius["married"].first["state"] # => 'widowed'
|
287
255
|
|
256
|
+
julius.as(Person).marry "84 BC", :gender => "f", :name => 'Cornelia'
|
257
|
+
julius.save
|
258
|
+
julius.reload
|
259
|
+
conny = ThingTank.get julius["married"]["spouse"]
|
260
|
+
conny.save
|
261
|
+
conny.reload
|
262
|
+
conny.as(Person).dies "68-65 BC"
|
263
|
+
conny.save
|
264
|
+
julius.reload
|
265
|
+
julius.as(Person).marry "68-65 BC", :gender => "f", :name => 'Pompeia'
|
266
|
+
julius["married"].size # => 2
|
267
|
+
Person.get(julius["married"].first["spouse"]).name # => 'Cornelia'
|
268
|
+
julius["married"].first["state"] # => 'widowed'
|
269
|
+
|
288
270
|
since julius is immortal, no one should be able to destroy him:
|
289
271
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
272
|
+
class Undestroyable < ThingTank::Role
|
273
|
+
before_destroy do
|
274
|
+
false # never allow to destroy
|
275
|
+
end
|
294
276
|
end
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
ThingTank.get(id).nil? # => julius is still there
|
309
|
-
|
277
|
+
|
278
|
+
julius.is(Undestroyable)
|
279
|
+
julius.save # save the role
|
280
|
+
|
281
|
+
id = julius.id
|
282
|
+
julius = ThingTank.get id
|
283
|
+
|
284
|
+
julius.as(Undestroyable).destroy
|
285
|
+
ThingTank.get(id).nil? # => julius is still there
|
286
|
+
|
287
|
+
julius.destroy
|
288
|
+
|
289
|
+
ThingTank.get(id).nil? # => julius is still there
|
310
290
|
|
311
291
|
You may subclass Hanswurst to do further separation and mix the
|
312
292
|
native properties of Hanswursts / its subclasses with the roles properties.
|
313
293
|
|
314
294
|
|
315
|
-
|
295
|
+
Contributing to thingtank
|
296
|
+
--------------------------
|
316
297
|
|
317
298
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
318
299
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
@@ -322,7 +303,8 @@ native properties of Hanswursts / its subclasses with the roles properties.
|
|
322
303
|
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
323
304
|
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
324
305
|
|
325
|
-
|
306
|
+
Copyright
|
307
|
+
----------
|
326
308
|
|
327
309
|
Copyright (c) 2012 Marc Rene Arns. See LICENSE.txt for
|
328
310
|
further details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/test/helper.rb
CHANGED
@@ -12,7 +12,7 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
12
12
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
13
|
#$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib', 'thingtank'))
|
14
14
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'examples'))
|
15
|
-
require 'thingtank'
|
15
|
+
require 'thingtank.rb'
|
16
16
|
|
17
17
|
require 'minitest/autorun'
|
18
18
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thingtank
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-02-03 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: couchrest
|
16
|
-
requirement: &
|
16
|
+
requirement: &24145540 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *24145540
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: couchrest_model
|
27
|
-
requirement: &
|
27
|
+
requirement: &24144880 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *24144880
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: yard
|
38
|
-
requirement: &
|
38
|
+
requirement: &24144300 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 0.6.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *24144300
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bundler
|
49
|
-
requirement: &
|
49
|
+
requirement: &24143760 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 1.0.0
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *24143760
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: jeweler
|
60
|
-
requirement: &
|
60
|
+
requirement: &24143160 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.6.4
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *24143160
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rcov
|
71
|
-
requirement: &
|
71
|
+
requirement: &24142560 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *24142560
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: linecache19
|
82
|
-
requirement: &
|
82
|
+
requirement: &24141960 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *24141960
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: ruby-debug19
|
93
|
-
requirement: &
|
93
|
+
requirement: &24141360 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *24141360
|
102
102
|
description:
|
103
103
|
email: ! 'Base64.decode64(bGludXhAbWFyY3JlbmVhcm5zLmRl
|
104
104
|
|
@@ -156,7 +156,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
156
156
|
version: '0'
|
157
157
|
segments:
|
158
158
|
- 0
|
159
|
-
hash:
|
159
|
+
hash: 309771975574738322
|
160
160
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
161
|
none: false
|
162
162
|
requirements:
|