thingtank 0.3.5 → 0.3.6

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.5
1
+ 0.3.6
@@ -23,13 +23,14 @@ class Spouse < ThingTank::Character
23
23
  property :married_state
24
24
 
25
25
  validate :spouse_should_be_married
26
+ validates :married, :character => Married # doc must have "married" character
26
27
 
27
28
  def married
28
29
  self["married"]
29
30
  end
30
31
 
31
32
  def spouse_should_be_married
32
- married["spouse"] == self["_id"]
33
+ married && married["spouse"] == self["_id"]
33
34
  end
34
35
 
35
36
  def name
@@ -4,11 +4,36 @@ class ThingTank
4
4
 
5
5
  class Character < CouchRest::Model::Base
6
6
 
7
- include ThingTank::ForceUpdate
8
7
  include ThingTank::SharedMethods
9
8
 
9
+ property :update_me
10
+
11
+ before_validation do |character|
12
+ couchrest_attribute_will_change!('update_me') # or update_me_will_change! will also do
13
+ character.changed_to_character_hash. each do |k,v|
14
+ if v.is_a?(ThingTank)
15
+ if v.id
16
+ self[k] = v.to_sym
17
+ else
18
+ self[k] = v.to_character_hash(true)
19
+ end
20
+ # only do this for [ThingTank.new, ThingTank.new]
21
+ # all of them either having an id or not (just the first entry is checked)
22
+ elsif v && v.is_a?(Array) && !v.empty? && v.first.is_a?(ThingTank)
23
+ if v.first.id
24
+ self[k] = v.collect do |tt|
25
+ tt.to_sym
26
+ end
27
+ else
28
+ self[k] = v.collect do |tt|
29
+ tt.to_character_hash(true)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
10
36
  class << self
11
-
12
37
  # we need this hack with after_inherited and defined or active record is going wild, see: http://stackoverflow.com/questions/790626/ruby-can-i-have-something-like-classinherited-thats-triggered-only-after-the
13
38
  # 'I'm trying to add behavior to activerecord models, but I need all the model customizations to go through before I mess with it. I'm trying to add behavior to activerecord models, but I need all the model customizations to go through before I mess with it. '
14
39
  # exactly my case
@@ -99,10 +124,15 @@ class ThingTank
99
124
  # use to_doc to put characters changes back to the doc without saving the doc
100
125
  def to_doc
101
126
  if changed?
127
+ valid = valid?
102
128
  changed_to_character_hash().each do |k,v|
103
129
  _character_doc[k] = v
104
130
  end
105
- @changed_attributes.clear if @changed_attributes
131
+ if valid
132
+ @changed_attributes.clear if @changed_attributes
133
+ else
134
+ _doc.errors.add self.class.to_s, self.errors.messages
135
+ end
106
136
  end
107
137
  end
108
138
 
@@ -143,5 +173,4 @@ class ThingTank
143
173
  _character_doc.add_character(klass, key, &code)
144
174
  end
145
175
  end
146
-
147
176
  end
@@ -15,6 +15,19 @@ class ThingTank
15
15
  @dependencies
16
16
  end
17
17
 
18
+ def to_sym
19
+ if id = self.id
20
+ "!##{id}"
21
+ else
22
+ nil
23
+ end
24
+ end
25
+
26
+ # it is not possible for whatever reason to overwrite valid?, check it out!
27
+ #def valid?
28
+ # invalid_characters.empty? && self.errors.messages.empty?
29
+ #end
30
+
18
31
  # we don't do this. there is no proper way to update all given characters
19
32
  # one must not rely on a character properties after the doc has been manipulated
20
33
  # use Character#reload to get the latest from the doc object to the character and Character#reload! to reload the doc from the database and reload the character then
@@ -72,3 +72,31 @@ class CharacterValidator < ActiveModel::EachValidator
72
72
  end
73
73
 
74
74
  end
75
+
76
+
77
+ class DocumentValidator < ActiveModel::EachValidator
78
+ def validate_single_doc(record, attribute, value, options)
79
+ if options[:inline]
80
+ return record.errors.add attribute, "#{value.inspect} should be an inlined doc that is converted to a hash" unless value.is_a? Hash
81
+ record.errors.add attribute, character.errors.messages unless ThingTank.new(value).valid?
82
+ else
83
+ match = (value =~ /^\!\#(.+)$/)
84
+ doc_id = $1
85
+ return record.errors.add attribute, "#{value.inspect} does not begin with !# and is therefor no doc id" unless match
86
+ record.errors.add attribute, "doc with id #{doc_id} does not exist" unless record._doc.class.get(doc_id)
87
+ end
88
+ end
89
+
90
+ def validate_each(record, attribute, values)
91
+ case values
92
+ when NilClass
93
+ return nil
94
+ when Array
95
+ values.each do |value|
96
+ validate_single_doc(record, attribute, value, options)
97
+ end
98
+ else
99
+ validate_single_doc(record, attribute, values, options)
100
+ end
101
+ end
102
+ end
@@ -15,11 +15,16 @@ class TestA < ThingTank::Character
15
15
  property :prop2
16
16
  property :foo1
17
17
  property :foo2
18
+ property :doc
19
+ property :inline_doc
18
20
 
19
21
  validates :prop1, :class => Array
20
22
  validates :prop2, :character => TestB
21
23
  validates :foo1, :class => [Integer, String]
22
24
  validates :foo2, :character => [TestB, TestC]
25
+
26
+ validates :doc, :document => true
27
+ validates :inline_doc, :document => {:inline => true}
23
28
  end
24
29
 
25
30
  describe "a classvalidator" do
@@ -114,4 +119,120 @@ describe "a charactervalidator and an array of values" do
114
119
  end
115
120
  assert_equal false, doc.as(TestA).valid?
116
121
  end
122
+ end
123
+
124
+ describe "a doc validator" do
125
+ it "should validate a doc id" do
126
+ doc1 = ThingTank.create :a => 'b'
127
+ doc1.save
128
+ doc2 = ThingTank.create
129
+ doc2.add_character TestA do |c|
130
+ c.doc = doc1.to_sym
131
+ end
132
+ assert_equal true, doc2.as(TestA).valid?
133
+
134
+ doc3 = ThingTank.create
135
+ doc3.add_character TestA do |c|
136
+ c.doc = doc1.id
137
+ end
138
+ assert_equal false, doc3.as(TestA).valid?
139
+
140
+ doc4 = ThingTank.create
141
+ doc4.add_character TestA do |c|
142
+ c.doc = "!#3" + doc1.id
143
+ end
144
+ assert_equal false, doc4.as(TestA).valid?
145
+
146
+ doc5 = ThingTank.create
147
+ doc5.add_character TestA do |c|
148
+ c.doc = doc1
149
+ end
150
+ assert_equal true, doc5.as(TestA).valid?
151
+ end
152
+
153
+ it "should validate an inline doc" do
154
+ doc1 = ThingTank.new :a => 'b'
155
+
156
+ doc2 = ThingTank.create
157
+ doc2.add_character TestA do |c|
158
+ c.inline_doc = doc1.to_character_hash(true)
159
+ end
160
+ assert_equal true, doc2.as(TestA).valid?
161
+
162
+ doc3 = ThingTank.create
163
+ doc3.add_character TestA do |c|
164
+ c.inline_doc = doc1
165
+ end
166
+
167
+ character = doc3.as(TestA)
168
+ assert_equal true, doc3.as(TestA).valid?
169
+
170
+ doc4 = ThingTank.create
171
+ doc4.add_character TestA do |c|
172
+ c.inline_doc = "test"
173
+ end
174
+
175
+ character = doc4.as(TestA)
176
+ assert_equal false, doc4.as(TestA).valid?
177
+ end
178
+
179
+
180
+ it "should validate multiple doc ids" do
181
+ doc0 = ThingTank.create :a => 'b'
182
+ doc0.save
183
+ doc1 = ThingTank.create :c => 'd'
184
+ doc1.save
185
+ doc2 = ThingTank.create
186
+ doc2.add_character TestA do |c|
187
+ c.doc = [doc1.to_sym, doc0.to_sym]
188
+ end
189
+ assert_equal true, doc2.as(TestA).valid?
190
+
191
+ doc3 = ThingTank.create
192
+ doc3.add_character TestA do |c|
193
+ c.doc = [doc1.id, doc0.to_sym]
194
+ end
195
+ assert_equal false, doc3.as(TestA).valid?
196
+
197
+ doc4 = ThingTank.create
198
+ doc4.add_character TestA do |c|
199
+ c.doc = ["!#3" + doc1.id, doc0.to_sym]
200
+ end
201
+ assert_equal false, doc4.as(TestA).valid?
202
+
203
+ doc5 = ThingTank.create
204
+ doc5.add_character TestA do |c|
205
+ c.doc = [doc1, doc0]
206
+ end
207
+ assert_equal true, doc5.as(TestA).valid?
208
+ end
209
+
210
+ it "should validate an multiple inline doc" do
211
+ doc0 = ThingTank.new :a => 'b'
212
+ doc1 = ThingTank.new :c => 'd'
213
+
214
+ doc2 = ThingTank.create
215
+ doc2.add_character TestA do |c|
216
+ c.inline_doc = [doc1.to_character_hash(true), doc0.to_character_hash(true)]
217
+ end
218
+ assert_equal true, doc2.as(TestA).valid?
219
+
220
+ doc3 = ThingTank.create
221
+ doc3.add_character TestA do |c|
222
+ c.inline_doc = [doc1, doc0]
223
+ end
224
+
225
+ character = doc3.as(TestA)
226
+ assert_equal true, doc3.as(TestA).valid?
227
+
228
+ doc4 = ThingTank.create
229
+ doc4.add_character TestA do |c|
230
+ c.inline_doc = ["test", doc1]
231
+ end
232
+
233
+ character = doc4.as(TestA)
234
+ assert_equal false, doc4.as(TestA).valid?
235
+ end
236
+
237
+
117
238
  end
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.3.5
4
+ version: 0.3.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-02-28 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &25566040 !ruby/object:Gem::Requirement
16
+ requirement: &9750780 !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: *25566040
24
+ version_requirements: *9750780
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: couchrest
27
- requirement: &25565060 !ruby/object:Gem::Requirement
27
+ requirement: &9749340 !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: *25565060
35
+ version_requirements: *9749340
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: couchrest_model
38
- requirement: &25564240 !ruby/object:Gem::Requirement
38
+ requirement: &9748700 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *25564240
46
+ version_requirements: *9748700
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: defined
49
- requirement: &25563260 !ruby/object:Gem::Requirement
49
+ requirement: &9747760 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *25563260
57
+ version_requirements: *9747760
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: guard
60
- requirement: &25562380 !ruby/object:Gem::Requirement
60
+ requirement: &9717160 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *25562380
68
+ version_requirements: *9717160
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: libnotify
71
- requirement: &25542460 !ruby/object:Gem::Requirement
71
+ requirement: &9716460 !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: *25542460
79
+ version_requirements: *9716460
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rb-inotify
82
- requirement: &25541360 !ruby/object:Gem::Requirement
82
+ requirement: &9715280 !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: *25541360
90
+ version_requirements: *9715280
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: guard-minitest
93
- requirement: &25540140 !ruby/object:Gem::Requirement
93
+ requirement: &9714000 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *25540140
101
+ version_requirements: *9714000
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: linecache19
104
- requirement: &25539220 !ruby/object:Gem::Requirement
104
+ requirement: &9713360 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *25539220
112
+ version_requirements: *9713360
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: ruby-debug19
115
- requirement: &25538420 !ruby/object:Gem::Requirement
115
+ requirement: &9712280 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *25538420
123
+ version_requirements: *9712280
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: yard
126
- requirement: &25537540 !ruby/object:Gem::Requirement
126
+ requirement: &9711120 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ~>
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: 0.6.0
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *25537540
134
+ version_requirements: *9711120
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: bundler
137
- requirement: &25536680 !ruby/object:Gem::Requirement
137
+ requirement: &9710160 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ~>
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: 1.0.0
143
143
  type: :development
144
144
  prerelease: false
145
- version_requirements: *25536680
145
+ version_requirements: *9710160
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: jeweler
148
- requirement: &25535920 !ruby/object:Gem::Requirement
148
+ requirement: &9703260 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ~>
@@ -153,7 +153,7 @@ dependencies:
153
153
  version: 1.6.4
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *25535920
156
+ version_requirements: *9703260
157
157
  description:
158
158
  email: ! 'Base64.decode64(bGludXhAbWFyY3JlbmVhcm5zLmRl
159
159
 
@@ -217,7 +217,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
217
217
  version: '0'
218
218
  segments:
219
219
  - 0
220
- hash: -2137838232803990585
220
+ hash: 2476284335551452114
221
221
  required_rubygems_version: !ruby/object:Gem::Requirement
222
222
  none: false
223
223
  requirements: