thingtank 0.1.0 → 0.2.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.
data/README.md CHANGED
@@ -1,8 +1,10 @@
1
- thingtank: play different roles [![Build Status](https://secure.travis-ci.org/metakeule/thingtank.png)](https://secure.travis-ci.org/metakeule/thingtank)
2
- =====================
1
+ thingtank: let couchrest docs have multiple characters at the same time
2
+ =======================================================================
3
+
4
+ [![Build Status](https://secure.travis-ci.org/metakeule/thingtank.png)](https://secure.travis-ci.org/metakeule/thingtank)
3
5
 
4
6
  ThingTank is a library that uses couchrest and couchrest model to create arbitrary
5
- objects that may have different roles. The roles determine the
7
+ objects that may have multiple characters. The characters determine the
6
8
  properties and they can be mixed and matched at will.
7
9
 
8
10
 
@@ -24,7 +26,7 @@ Examples:
24
26
 
25
27
  Imagine a Caesar is born
26
28
 
27
- class Born < ThingTank::Role
29
+ class Born < ThingTank::Character
28
30
  property :birth_date, :alias => :born_at
29
31
  property :birth_place
30
32
  validates_presence_of :birth_date # make sure a date is given
@@ -32,7 +34,7 @@ Imagine a Caesar is born
32
34
 
33
35
  just in case he might die....we might want to have a date and maybe even a place
34
36
 
35
- class Dead < ThingTank::Role
37
+ class Dead < ThingTank::Character
36
38
  property :date_of_death
37
39
  property :place_of_death
38
40
  validates_presence_of :date_of_death
@@ -40,7 +42,7 @@ just in case he might die....we might want to have a date and maybe even a place
40
42
 
41
43
  and then he needs a name
42
44
 
43
- class Person < ThingTank::Role
45
+ class Person < ThingTank::Character
44
46
  property :name
45
47
  property :gender
46
48
  validates_presence_of :name
@@ -73,7 +75,7 @@ later...
73
75
  when he is adult, he wants to marry. now things are getting a bit more complicated:
74
76
 
75
77
  # he needs a marriage and a women
76
- class Married < ThingTank::Role
78
+ class Married < ThingTank::Character
77
79
  property :date # the date of the marriage
78
80
  property :end # when the marriage ended
79
81
  property :spouse # doc_id of the spouse
@@ -83,20 +85,20 @@ when he is adult, he wants to marry. now things are getting a bit more complicat
83
85
  validate :spouse_should_be_a_person
84
86
  # ensure that 'spouse' is a doc_id of a Person
85
87
  def spouse_should_be_a_person
86
- Person.get(self["spouse"]).valid? # loads doc as role Person and validates, same as ThingTank.get(self["spouse"]).as(Person).valid?
88
+ Person.get(self["spouse"]).valid? # loads doc as character Person and validates, same as ThingTank.get(self["spouse"]).as(Person).valid?
87
89
  end
88
90
  end
89
91
 
90
92
  we want easy access to the name of the spouse
91
93
 
92
- class Spouse < ThingTank::Role
94
+ class Spouse < ThingTank::Character
93
95
  property :married # doc must have "married" property (should be of class married, we don't check this at the moment)
94
96
  property :married_state
95
97
 
96
98
  validate :spouse_should_be_married
97
99
 
98
100
  def married
99
- self["married"] # contains a Married role
101
+ self["married"] # contains a Married character
100
102
  end
101
103
 
102
104
  def spouse_should_be_married
@@ -118,10 +120,10 @@ we want easy access to the name of the spouse
118
120
 
119
121
  now we could easily get julius married
120
122
 
121
- conny = ThingTank.create :gender => "f", :name => 'Cornelia', :roles => ['Person']
123
+ conny = ThingTank.create :gender => "f", :name => 'Cornelia', :characters => ['Person']
122
124
  julius["married"] = {"date" => "84 BC", "spouse" => conny.id}
123
125
  julius["married_state"] = "married"
124
- julius.with("married").is(Married).valid? # => true # "married" is a property that plays the Married role
126
+ julius.with("married").is(Married).valid? # => true # "married" is a property that has the Married character
125
127
  julius.has(Spouse).valid? # #has is an alias of #is
126
128
  julius.save
127
129
  julius.reload
@@ -140,8 +142,8 @@ while that is nice, let see if we could make it more comfortable:
140
142
  self["state"] = 'married'
141
143
  _doc["married_state"] = 'married'
142
144
 
143
- unless person["married"] && person.last_role(Married, "married").spouse == _doc["_id"]
144
- person.add_role(Married, "married") do |m|
145
+ unless person["married"] && person.last_character(Married, "married").spouse == _doc["_id"]
146
+ person.add_character(Married, "married") do |m|
145
147
  m.date = self["date"]
146
148
  m.marry _doc
147
149
  end
@@ -164,7 +166,7 @@ while that is nice, let see if we could make it more comfortable:
164
166
 
165
167
  class Spouse
166
168
  def married(&code)
167
- _doc.last_role Married, "married", &code
169
+ _doc.last_character Married, "married", &code
168
170
  end
169
171
 
170
172
  def divorce(date)
@@ -175,7 +177,7 @@ while that is nice, let see if we could make it more comfortable:
175
177
 
176
178
  class Person
177
179
  def marry(date, person)
178
- _doc.add_role Married, "married", do |m|
180
+ _doc.add_character Married, "married", do |m|
179
181
  m.date = "84 BC"
180
182
  m.marry person
181
183
  end
@@ -189,7 +191,7 @@ it now becomes much less work and Cornelia also knows that she is married to Jul
189
191
  julius.reload
190
192
  julius.has(Spouse).name # => 'Cornelia'
191
193
  julius.has(Spouse).married_state # => 'married'
192
- conny_id = julius.last_role(Married,"married").spouse
194
+ conny_id = julius.last_character(Married,"married").spouse
193
195
  conny = ThingTank.get conny_id
194
196
  conny.has(Spouse).married_state # => 'married'
195
197
 
@@ -211,10 +213,10 @@ julius is still married with Cornelia but he should not
211
213
  if Cornelia died before his second marriage, it would not be a problem:
212
214
 
213
215
  class Dead
214
- # all callbacks of roles are called and defined like corresponding callbacks of the doc
216
+ # all callbacks of characters are called and defined like corresponding callbacks of the doc
215
217
  before_save do
216
218
  if _doc.is?(Spouse) && _doc['married_state'] == 'married'
217
- Spouse.get(_doc.last_role(Married, 'married').spouse).widowed(self["date_of_death"])
219
+ Spouse.get(_doc.last_character(Married, 'married').spouse).widowed(self["date_of_death"])
218
220
  end
219
221
  true
220
222
  end
@@ -259,14 +261,14 @@ if Cornelia died before his second marriage, it would not be a problem:
259
261
 
260
262
  since julius is immortal, no one should be able to destroy him:
261
263
 
262
- class Undestroyable < ThingTank::Role
264
+ class Undestroyable < ThingTank::Character
263
265
  before_destroy do
264
266
  false # never allow to destroy
265
267
  end
266
268
  end
267
269
 
268
270
  julius.is(Undestroyable)
269
- julius.save # save the role
271
+ julius.save # save the character
270
272
 
271
273
  id = julius.id
272
274
  julius = ThingTank.get id
@@ -279,7 +281,7 @@ since julius is immortal, no one should be able to destroy him:
279
281
  ThingTank.get(id).nil? # => julius is still there
280
282
 
281
283
  You may subclass ThingTank to do further separation and mix the
282
- native properties of ThingTanks / its subclasses with the roles properties.
284
+ native properties of ThingTanks / its subclasses with the characters properties.
283
285
 
284
286
 
285
287
  Contributing to thingtank
data/Rakefile CHANGED
@@ -17,7 +17,7 @@ Jeweler::Tasks.new do |gem|
17
17
  gem.name = "thingtank"
18
18
  gem.homepage = "http://github.com/metakeule/thingtank"
19
19
  gem.license = "MIT"
20
- gem.summary = %Q{thin wrapper around couchrest}
20
+ gem.summary = %Q{let couchrest docs have multiple characters at the same time}
21
21
  gem.email = "Base64.decode64(bGludXhAbWFyY3JlbmVhcm5zLmRl\n)"
22
22
  gem.authors = ["Marc Rene Arns"]
23
23
  # dependencies defined in Gemfile
@@ -31,11 +31,6 @@ Rake::TestTask.new(:test) do |test|
31
31
  test.verbose = true
32
32
  end
33
33
 
34
- desc "guard"
35
- task :guard do
36
- exec("bundle exec guard")
37
- end
38
-
39
34
  task :default => :test
40
35
 
41
36
  require 'yard'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -1,4 +1,4 @@
1
- class Born < ThingTank::Role
1
+ class Born < ThingTank::Character
2
2
  property :birth_date, :alias => :born_at
3
3
  property :birth_place
4
4
 
@@ -6,14 +6,14 @@ class Born < ThingTank::Role
6
6
  end
7
7
 
8
8
  # just in case he might die....we might want to have a date and maybe even a place
9
- class Dead < ThingTank::Role
9
+ class Dead < ThingTank::Character
10
10
  property :date_of_death
11
11
  property :place_of_death
12
12
 
13
13
  validates_presence_of :date_of_death
14
14
  end
15
15
 
16
- class Person < ThingTank::Role
16
+ class Person < ThingTank::Character
17
17
  property :name
18
18
  property :gender
19
19
 
@@ -40,10 +40,10 @@ def test_bear_julius
40
40
  assert_equal 'Gaius Iulius Caesar', julius["name"]
41
41
  assert_equal 'Rome', julius["birth_place"]
42
42
 
43
- assert !julius["roles"].nil?
44
- assert_equal 2, julius["roles"].size
45
- assert julius["roles"].include? Person.to_s
46
- assert julius["roles"].include? Born.to_s
43
+ assert !julius["characters"].nil?
44
+ assert_equal 2, julius["characters"].size
45
+ assert julius["characters"].include? Person.to_s
46
+ assert julius["characters"].include? Born.to_s
47
47
  assert_equal "100 BC", julius.is(Born).born_at
48
48
 
49
49
  return julius
@@ -1,7 +1,7 @@
1
1
  require_relative 'bear_julius.rb'
2
2
 
3
3
  # he needs a marriage and a women
4
- class Married < ThingTank::Role
4
+ class Married < ThingTank::Character
5
5
  property :date # the date of the marriage
6
6
  property :end # when the marriage ended
7
7
  property :spouse # doc_id of the spouse
@@ -18,7 +18,7 @@ class Married < ThingTank::Role
18
18
  end
19
19
 
20
20
  # we want easy access to the name of the spouse
21
- class Spouse < ThingTank::Role
21
+ class Spouse < ThingTank::Character
22
22
  property :married
23
23
  property :married_state
24
24
 
@@ -47,7 +47,7 @@ end
47
47
 
48
48
  def test_first_marriage()
49
49
  julius = test_bear_julius
50
- conny = create :gender => "f", :name => 'Cornelia', :roles => ['Person']
50
+ conny = create :gender => "f", :name => 'Cornelia', :characters => ['Person']
51
51
 
52
52
  julius["married"] = {"date" => "84 BC", "spouse" => conny.id}
53
53
  julius["married_state"] = "married"
@@ -65,7 +65,7 @@ end
65
65
 
66
66
  def test_first_marriage_shortcuts()
67
67
  julius = test_bear_julius
68
- conny = create :gender => "f", :name => 'Cornelia', :roles => ['Person']
68
+ conny = create :gender => "f", :name => 'Cornelia', :characters => ['Person']
69
69
 
70
70
  julius["married"] = {"date" => "84 BC", "spouse" => conny.id}
71
71
  julius["married_state"] = "married"
@@ -1,6 +1,6 @@
1
1
  require_relative 'bear_julius.rb'
2
2
 
3
- class Undestroyable < ThingTank::Role
3
+ class Undestroyable < ThingTank::Character
4
4
  before_destroy do
5
5
  false # never allow to destroy
6
6
  end
@@ -9,7 +9,7 @@ end
9
9
  def test_julius_immortal
10
10
  julius = test_bear_julius()
11
11
  julius.is(Undestroyable)
12
- julius.save # save the role
12
+ julius.save # save the character
13
13
 
14
14
  id = julius.id
15
15
  julius = db_load id
@@ -12,8 +12,8 @@ class Married
12
12
  self["state"] = 'married'
13
13
  _doc["married_state"] = 'married'
14
14
 
15
- unless person["married"] && person.last_role(Married, "married").spouse == _doc["_id"]
16
- person.add_role(Married, "married") do |m|
15
+ unless person["married"] && person.last_character(Married, "married").spouse == _doc["_id"]
16
+ person.add_character(Married, "married") do |m|
17
17
  m.date = self["date"]
18
18
  m.marry _doc
19
19
  end
@@ -36,7 +36,7 @@ end
36
36
 
37
37
  class Spouse
38
38
  def married(&code)
39
- _doc.last_role Married, "married", &code
39
+ _doc.last_character Married, "married", &code
40
40
  end
41
41
 
42
42
  def divorce(date)
@@ -47,7 +47,7 @@ end
47
47
 
48
48
  class Person
49
49
  def marry(date, person)
50
- _doc.add_role Married, "married" do |m|
50
+ _doc.add_character Married, "married" do |m|
51
51
  m.date = "84 BC"
52
52
  m.marry person
53
53
  end
@@ -64,13 +64,13 @@ def test_improved_marriage()
64
64
  assert_equal 'Cornelia', julius.has(Spouse).name
65
65
  assert_equal 'married', julius.has(Spouse).married_state
66
66
 
67
- conny = db_load julius.last_role(Married,"married").spouse
67
+ conny = db_load julius.last_character(Married,"married").spouse
68
68
 
69
69
  assert_equal 'Gaius Iulius Caesar', conny.has(Spouse).name
70
70
  assert_equal 'married', conny.has(Spouse).married_state
71
71
 
72
- assert_equal julius['_id'], conny.last_role(Married,"married").spouse
73
- assert_equal "84 BC", conny.last_role(Married,"married").date
72
+ assert_equal julius['_id'], conny.last_character(Married,"married").spouse
73
+ assert_equal "84 BC", conny.last_character(Married,"married").date
74
74
 
75
75
  return julius
76
76
  end
@@ -85,16 +85,16 @@ def test_improved_marriage_divorce()
85
85
  assert_equal nil, julius.has(Spouse).name
86
86
  assert_equal 'Cornelia', julius.has(Spouse).ex
87
87
  assert_equal 'divorced', julius["married_state"]
88
- assert_equal "85 BC", julius.last_role(Married,"married").end
88
+ assert_equal "85 BC", julius.last_character(Married,"married").end
89
89
 
90
- conny = db_load julius.last_role(Married,"married").spouse
90
+ conny = db_load julius.last_character(Married,"married").spouse
91
91
 
92
92
  assert_equal nil, conny.has(Spouse).name
93
93
  assert_equal 'Gaius Iulius Caesar', conny.has(Spouse).ex
94
94
  assert_equal 'divorced', conny["married_state"]
95
95
 
96
- assert_equal julius['_id'], conny.last_role(Married,"married").spouse
97
- assert_equal "85 BC", conny.last_role(Married,"married").end
96
+ assert_equal julius['_id'], conny.last_character(Married,"married").spouse
97
+ assert_equal "85 BC", conny.last_character(Married,"married").end
98
98
  return julius
99
99
  end
100
100
 
@@ -2,10 +2,10 @@ require_relative 'marriage_improvement.rb'
2
2
 
3
3
  class Dead
4
4
 
5
- # all callbacks of roles are called and defined like corresponding callbacks of the doc
5
+ # all callbacks of characters are called and defined like corresponding callbacks of the doc
6
6
  before_save do
7
7
  if _doc.is?(Spouse) && _doc['married_state'] == 'married'
8
- Spouse.get(_doc.last_role(Married, 'married').spouse).widowed(self["date_of_death"])
8
+ Spouse.get(_doc.last_character(Married, 'married').spouse).widowed(self["date_of_death"])
9
9
  end
10
10
  true
11
11
  end
@@ -2,13 +2,13 @@
2
2
 
3
3
  class CouchRest::Model::Designs::DesignMapper
4
4
 
5
- # generate a view to show only ThingTanks of a certain role, define them all in a ThingTank subclass (not in a role)
6
- def role_view(klass, name, opts={})
5
+ # generate a view to show only ThingTanks of a certain character, define them all in a ThingTank subclass (not in a character)
6
+ def character_view(klass, name, opts={})
7
7
  name = "#{klass.to_s.downcase}_#{name}"
8
8
  opts ||= {}
9
9
  opts[:guards] ||= []
10
10
  # there is no "inArray" like function in couchdb, see http://stackoverflow.com/questions/3740464/i-have-to-write-every-function-i-need-for-couchdb
11
- opts[:guards] << "((doc['roles'] !== undefined) && (function (item,arr) { for(p=0;p<arr.length;p++) if (item == arr[p]) return true; return false;})('#{klass.to_s}',doc['roles']))"
11
+ opts[:guards] << "((doc['characters'] !== undefined) && (function (item,arr) { for(p=0;p<arr.length;p++) if (item == arr[p]) return true; return false;})('#{klass.to_s}',doc['characters']))"
12
12
  view(name, opts)
13
13
  end
14
14
 
@@ -18,7 +18,7 @@ class ThingTank
18
18
  # mimic the destroy_document method from https://github.com/langalex/couch_potato/blob/master/lib/couch_potato/database.rb
19
19
  before_destroy do
20
20
  ok = true
21
- (self["roles"] || []).each do |klass|
21
+ (self["characters"] || []).each do |klass|
22
22
  document = self.as(klass.constantize)
23
23
  (ok = false) if false == document.run_callbacks(:destroy) do
24
24
  true
@@ -1,7 +1,7 @@
1
1
 
2
2
  class ThingTank
3
3
 
4
- class Role < CouchRest::Model::Base
4
+ class Character < CouchRest::Model::Base
5
5
 
6
6
  include ThingTank::ForceUpdate
7
7
  include ThingTank::SharedMethods
@@ -9,13 +9,13 @@ class ThingTank
9
9
  class << self
10
10
 
11
11
  def property(name, *args)
12
- @role_properties ||= []
13
- @role_properties << name.to_s
12
+ @character_properties ||= []
13
+ @character_properties << name.to_s
14
14
  super
15
15
  end
16
16
 
17
- def role_properties
18
- @role_properties
17
+ def character_properties
18
+ @character_properties
19
19
  end
20
20
 
21
21
  def -(key)
@@ -25,12 +25,12 @@ class ThingTank
25
25
  def get(id, db = database)
26
26
  doc = ThingTank.get(id)
27
27
  return nil if doc.nil?
28
- return doc.to_role(self)
28
+ return doc.to_character(self)
29
29
  end
30
30
 
31
31
  def get!(id, db = database)
32
32
  doc = ThingTank.get!(id)
33
- doc.to_role(self)
33
+ doc.to_character(self)
34
34
  end
35
35
 
36
36
  def wants(*modules)
@@ -43,11 +43,11 @@ class ThingTank
43
43
  end
44
44
 
45
45
  def design
46
- raise "design is not supported in ThingTank::Role, please use the 'role_view' method in a ThingTank subclass design definition"
46
+ raise "design is not supported in ThingTank::Character, please use the 'character_view' method in a ThingTank subclass design definition"
47
47
  end
48
48
 
49
49
  def view_by(*args)
50
- raise "view_by is not supported in ThingTank::Role, please use the 'role_view_by' method in a ThingTank subclass"
50
+ raise "view_by is not supported in ThingTank::Character, please use the 'character_view_by' method in a ThingTank subclass"
51
51
  end
52
52
 
53
53
  end
@@ -65,9 +65,9 @@ class ThingTank
65
65
  end
66
66
 
67
67
  # the virtual _doc that contains me, you should not need it normally
68
- def _role_doc
68
+ def _character_doc
69
69
  if database.is_a?(FakeBase)
70
- database._role_doc
70
+ database._character_doc
71
71
  else
72
72
  nil
73
73
  end
@@ -75,35 +75,35 @@ class ThingTank
75
75
 
76
76
  def flush_to_doc
77
77
  if changed?
78
- changed_to_role_hash().each do |k,v|
79
- _role_doc[k] = v
78
+ changed_to_character_hash().each do |k,v|
79
+ _character_doc[k] = v
80
80
  end
81
- _role_doc.save
81
+ _character_doc.save
82
82
  @changed_attributes.clear
83
83
  end
84
84
  end
85
85
 
86
86
  def reload
87
- attrs = _role_doc.as(self.class).to_role_hash
87
+ attrs = _character_doc.as(self.class).to_character_hash
88
88
  prepare_all_attributes(attrs, :directly_set_attributes => true)
89
89
  @changed_attributes.clear
90
90
  self
91
91
  end
92
92
 
93
- def to_role(klass, key, &code)
94
- _role_doc.to_role(klass, key, &code)
93
+ def to_character(klass, key, &code)
94
+ _character_doc.to_character(klass, key, &code)
95
95
  end
96
96
 
97
97
  def first(key)
98
- _role_doc.first(key)
98
+ _character_doc.first(key)
99
99
  end
100
100
 
101
101
  def last(key)
102
- _role_doc.last(key)
102
+ _character_doc.last(key)
103
103
  end
104
104
 
105
- def add_role(klass, key=nil, &code)
106
- _role_doc.add_role(klass, key, &code)
105
+ def add_character(klass, key=nil, &code)
106
+ _character_doc.add_character(klass, key, &code)
107
107
  end
108
108
  end
109
109