thingtank 0.3.5 → 0.3.6

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