thingtank 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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