couchpillow 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6c941b4db98918cd72e334fb39d97ce2bb6ea24b
4
- data.tar.gz: 28babdcc130a232e33d10f72c8771291729b45ce
3
+ metadata.gz: c8a125e7eabce1a8d19853040151e38791c57d07
4
+ data.tar.gz: ec143b133ab55a2ec34ec2fd7b4f3c9b84831fad
5
5
  SHA512:
6
- metadata.gz: 5350184abf2713d2385ebb6c810047696fe38dc37a9ec2984777d8099ec342afc363ed0257e75933930dc6269b3a2f049a51a5a1420ce7dbaf6ee453758db808
7
- data.tar.gz: d0428814d6e6811a16c43db27f096a55472f2c82b7fcb1e957f4f654e477033907af5a35bf9f72a30938183ff1e43999de52b1400c96be1a40c16b1091231f03
6
+ metadata.gz: 0d3ce4a39378e5fbe15e642bcee30e97a03506316741c6ee5e3a242398a3b249e79f2ee6e88d08279bb57aabd3f07968f3c1430930921cf8b310efc42f8b4d5c
7
+ data.tar.gz: ddf7c4cc0c9ade106a817bd89d3557248933e167c8faadf3db1fd6855d911accbca5bbea68866c0633c449381099161e7082b79401c1d0485159b8f161632a42
data/README.markdown CHANGED
@@ -22,7 +22,7 @@ methods.
22
22
  gem install couchpillow
23
23
 
24
24
 
25
- ## How To Use
25
+ ## Quick Start
26
26
 
27
27
  require 'couchpillow'
28
28
 
@@ -62,16 +62,47 @@ Specifying custom id:
62
62
  doc.save!
63
63
 
64
64
  # {
65
- # '_id': '123',
65
+ # '_id': 'user::123',
66
66
  # '_type': 'user',
67
67
  # '_created_at': '2014-07-04 00:00:00 UTC'
68
68
  # '_updated_at': '2014-07-04 00:00:00 UTC'
69
69
  # 'email': 'john@email.com',
70
70
  # }
71
71
 
72
+
73
+ ### Document-Level Directives
74
+
75
+ The following are directives that can be used to trigger specific behaviors
76
+ at the Document level.
77
+
78
+ * `type(T)`
79
+
80
+ Set the type of the Document.
81
+
82
+ * `type_prefix(true|false)`
83
+
84
+ Default to `true`. If set to false, it removes prefixing document id with
85
+ the document type. Leaving this to true is the recommended behavior to avoid
86
+ id conflicts between different types of documents, especially when custom
87
+ ids are being used.
88
+
89
+ * `attribute(name, &block)`
90
+
91
+ Declares an attribute for this Document. You can specify additional
92
+ directives for each attribute. See Attributes section.
93
+
94
+ * `db(connection)`
95
+
96
+ Sets the database connections. If set once, it will set that connection as
97
+ the primary connection. Any subsequent calls to this directive will set
98
+ those connections as secondary connections. See Multiple DB Connections
99
+ section.
100
+
101
+
102
+
72
103
  ### Attributes
73
104
 
74
- Using Attribute Directives:
105
+ Using Attribute Directive:
75
106
 
76
107
  class User < CouchPillow::Document
77
108
  type :user
@@ -164,8 +195,8 @@ via the `db` directive. Example:
164
195
 
165
196
  You can also specify multiple `db` directives. The first time the `db`
166
197
  directive is called, it sets that connection as the primary connection, as the
167
- above example shows. Any subsequent calls will insert that DB connection as
168
- secondary connections, which will only be trigger on write (`save!`, `update!`,
198
+ above example shows. Any subsequent calls will insert those DB connection as
199
+ secondary connections, which will only trigger on write (`save!`, `update!`,
169
200
  and `delete!`).
170
201
 
171
202
 
data/lib/couchpillow.rb CHANGED
@@ -1,13 +1,10 @@
1
1
  require 'securerandom'
2
2
  require 'json'
3
3
  require 'time'
4
- require 'celluloid/autostart'
5
4
  require 'couchbase'
6
5
 
7
6
  module CouchPillow
8
7
 
9
- Celluloid.logger = nil
10
-
11
8
  def self.db= driver
12
9
  @db = driver
13
10
  end
@@ -18,8 +15,11 @@ module CouchPillow
18
15
 
19
16
  end
20
17
 
21
- require 'couchpillow/attribute'
22
- require 'couchpillow/attributive'
18
+ require 'couchpillow/directives/type'
19
+ require 'couchpillow/directives/type_prefix'
20
+ require 'couchpillow/directives/attribute'
21
+ require 'couchpillow/directives/multi_db'
22
+
23
23
  require 'couchpillow/errors'
24
24
  require 'couchpillow/boolean'
25
25
  require 'couchpillow/document'
@@ -1,5 +1,36 @@
1
1
  module CouchPillow
2
2
 
3
+ module AttributeDirective
4
+
5
+ # Declares a new Attribute
6
+ #
7
+ def attribute attr, &block
8
+ attr = attr.to_s.to_sym
9
+ new_attr = Attribute.new(attr)
10
+ attributes[attr] = new_attr
11
+
12
+ # Define accessor methods
13
+ define_method(attr) do
14
+ @data[attr]
15
+ end
16
+ define_method("#{attr}=") do |val|
17
+ @data[attr] = val
18
+ end
19
+
20
+ new_attr.instance_eval &block if block
21
+
22
+ new_attr
23
+ end
24
+
25
+
26
+ def attributes
27
+ @attributes ||= {}
28
+ end
29
+
30
+
31
+ end
32
+
33
+
3
34
  class Attribute
4
35
 
5
36
  attr_reader :name
@@ -8,7 +39,6 @@ module CouchPillow
8
39
  @type = nil
9
40
  @auto_convert = false
10
41
  @default_block = nil
11
- @check_value_message = nil
12
42
  @check_value_block = nil
13
43
 
14
44
 
@@ -69,18 +99,16 @@ module CouchPillow
69
99
 
70
100
  # Directive to perform a validation over the value of this Attribute.
71
101
  #
72
- # @param message Message when block passed fails. Optional.
73
102
  # @yield [v] Value of the Attribute.
74
103
  #
75
104
  # @example
76
- # content("Name must be John") { |v| v == "John" }
77
105
  # content { |v| v == "John" }
78
106
  #
79
- def content message = nil, &block
80
- @check_value_message = message
107
+ def content &block
81
108
  @check_value_block = block
82
109
  self
83
110
  end
111
+ alias_method :validate_content, :content
84
112
 
85
113
 
86
114
  # Check the default value.
@@ -96,7 +124,7 @@ module CouchPillow
96
124
  #
97
125
  def trigger_content_directive value
98
126
  if @check_value_block
99
- raise ValidationError, @check_value_message unless
127
+ raise ValidationError, "Content validation error: #{value}" unless
100
128
  @check_value_block.call(value)
101
129
  end
102
130
  value
@@ -110,10 +138,11 @@ module CouchPillow
110
138
  # Run auto-conversion first.
111
139
  value = trigger_auto_convert_directive(value)
112
140
 
141
+ msg = "Type mismatch for attribute #{@name}"
113
142
  if @type == CouchPillow::Boolean
114
- raise ValidationError unless !!value == value
143
+ raise ValidationError, msg unless !!value == value
115
144
  else
116
- raise ValidationError unless value.is_a?(@type)
145
+ raise ValidationError, msg unless value.is_a?(@type)
117
146
  end
118
147
  end
119
148
 
@@ -157,5 +186,3 @@ module CouchPillow
157
186
 
158
187
  end
159
188
  end
160
-
161
-
@@ -0,0 +1,70 @@
1
+ require 'celluloid/autostart'
2
+
3
+ Celluloid.logger = nil
4
+
5
+ module CouchPillow
6
+
7
+ module MultiDBDirective
8
+
9
+ # Set a DB connection. Overrides the default CouchPillow.db connection
10
+ # for the first time this method gets called. Subsequent calls will set
11
+ # secondary connections, which will only be used for write only.
12
+ #
13
+ # Example:
14
+ # db primary_db # use for both read and write
15
+ # db backup_db1 # write only
16
+ # db backup_db2 # write only
17
+ #
18
+ def db conn
19
+ # set the primary db connection
20
+ @primary_db ||= conn
21
+
22
+ # insert as backup db connections
23
+ if conn && @primary_db && conn != @primary_db
24
+ _secondary_dbs << conn
25
+ end
26
+ end
27
+
28
+
29
+ def _default_db
30
+ @default_db ||= (@primary_db || CouchPillow.db)
31
+ end
32
+
33
+
34
+ def _secondary_dbs
35
+ @secondary_dbs ||= []
36
+ end
37
+
38
+
39
+ def _write_to_secondary_dbs &block
40
+ unless _secondary_dbs.empty?
41
+ _futures << Celluloid::Future.new do
42
+ _secondary_dbs.each do |db|
43
+ block.call(db)
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+
50
+ def _futures
51
+ @futures ||= []
52
+ end
53
+
54
+
55
+ # Blocks until all pending tasks has completed.
56
+ # Returns the result of those tasks in an array.
57
+ #
58
+ def wait
59
+ result = []
60
+ until _futures.empty?
61
+ f = _futures.shift
62
+ result << f.value
63
+ end
64
+
65
+ result
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,28 @@
1
+ module CouchPillow
2
+
3
+ module TypeDirective
4
+
5
+ # Sets the type of this Document.
6
+ #
7
+ def type value
8
+ @type = value.to_s
9
+ end
10
+
11
+
12
+ def _doc_type
13
+ @type ||= "couchpillow"
14
+ end
15
+
16
+
17
+ # Helper method to sanitize an id string
18
+ #
19
+ def _sanitize_id id
20
+ key = "#{_doc_type}::"
21
+ id = id.to_s
22
+ id.start_with?(key) and
23
+ id = id[key.length..-1] or
24
+ id
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ module CouchPillow
2
+
3
+ module TypePrefixDirective
4
+
5
+
6
+ def type_prefix v
7
+ @type_prefix = v == true
8
+ end
9
+
10
+
11
+ def _is_type_prefixed?
12
+ @type_prefix == true
13
+ end
14
+
15
+ end
16
+ end
@@ -2,19 +2,23 @@ module CouchPillow
2
2
 
3
3
  class Document
4
4
 
5
- extend Attributive
5
+ extend TypeDirective
6
+ extend TypePrefixDirective
7
+ extend AttributeDirective
8
+ extend MultiDBDirective
6
9
 
7
- attr_reader :id
10
+ attr_accessor :id
8
11
 
9
12
  RESERVED_KEYS = %i[_id _type _created_at _updated_at]
10
13
 
11
- DEFAULT_TYPE = "couchpillow".freeze
12
-
13
14
  EVENTS = [ :cas_conflict ].freeze
14
15
 
15
16
  CAS_CONFLICT_RETRY_COUNT = 5
16
17
 
17
18
 
19
+ type_prefix true
20
+
21
+
18
22
  attribute :_created_at do
19
23
  required
20
24
  type Time
@@ -37,19 +41,18 @@ module CouchPillow
37
41
  # @param flags Flags of the document, from the CB client. Optional.
38
42
  #
39
43
  def initialize hash = {},
40
- id = "#{self.class.doc_type}::#{SecureRandom.hex}",
44
+ id = SecureRandom.hex,
41
45
  cas = nil
42
46
 
43
47
  @data = self.class.symbolize(hash)
44
48
  @original = Marshal.load(Marshal.dump(@data))
45
49
 
46
- @id = id
50
+ @id = self.class._is_type_prefixed? ? self.class._sanitize_id(id) : id
51
+
47
52
  time = Time.now.utc
48
53
  @data[:_created_at] ||= time
49
54
  @data[:_updated_at] = time
50
55
 
51
- @futures = []
52
-
53
56
  @cas = cas
54
57
 
55
58
  rename!
@@ -75,19 +78,19 @@ module CouchPillow
75
78
  result = nil
76
79
 
77
80
  # write to the primary db first
78
- result = cas_handler do
81
+ result = _cas_handler do
79
82
  whitelist!
80
83
  sort!
81
- timestamp!
84
+ _timestamp!
82
85
  validate!
83
86
  opts[:cas] = @cas
84
- self.class.default_db.set(@id, to_save, opts)
87
+ self.class._default_db.set(db_id, _to_save, opts)
85
88
  end
86
89
 
87
90
  # write to the secondary only if the primary succeeds
88
91
  # and ignore CAS for secondary DBs.
89
- write_to_secondary_dbs do |db|
90
- db.set @id, to_save
92
+ self.class._write_to_secondary_dbs do |db|
93
+ db.set(db_id, _to_save)
91
94
  end if result
92
95
 
93
96
  result
@@ -97,11 +100,11 @@ module CouchPillow
97
100
  # Delete this document from the server.
98
101
  #
99
102
  def delete!
100
- result = self.class.default_db.delete @id
103
+ result = self.class._default_db.delete(db_id)
101
104
 
102
105
  # write to the secondary only if the primary succeeds
103
- write_to_secondary_dbs do |db|
104
- db.delete @id
106
+ self.class._write_to_secondary_dbs do |db|
107
+ db.delete(db_id)
105
108
  end if result
106
109
 
107
110
  result
@@ -114,20 +117,20 @@ module CouchPillow
114
117
  def update! opts = {}
115
118
 
116
119
  # write to the primary db first
117
- result = cas_handler do
120
+ result = _cas_handler do
118
121
  whitelist!
119
122
  sort!
120
- timestamp!
123
+ _timestamp!
121
124
  validate!
122
125
  opts[:cas] = @cas
123
- result = self.class.default_db.replace(@id, to_save, opts)
126
+ result = self.class._default_db.replace(db_id, _to_save, opts)
124
127
  end
125
128
 
126
129
  # write to the secondary only if the primary succeeds
127
130
  # and ignore CAS for secondary DBs.
128
131
  opts.delete :cas
129
- write_to_secondary_dbs do |db|
130
- db.replace @id, to_save
132
+ self.class._write_to_secondary_dbs do |db|
133
+ db.replace(db_id, _to_save)
131
134
  end if result
132
135
 
133
136
  result
@@ -165,7 +168,7 @@ module CouchPillow
165
168
  # Convert this Document to a Hash
166
169
  #
167
170
  def to_hash
168
- { :_id => @id, :_type => self.class.doc_type }.merge!(@data)
171
+ { :_id => @id, :_type => doc_type }.merge!(@data)
169
172
  end
170
173
 
171
174
 
@@ -173,21 +176,7 @@ module CouchPillow
173
176
  # Can't really name this `type`. Need to avoid name conflict with Ruby's own `type` method.
174
177
  #
175
178
  def doc_type
176
- self.class.doc_type
177
- end
178
-
179
-
180
- # Blocks until all pending tasks has completed.
181
- # Returns the result of those tasks in an array.
182
- #
183
- def wait
184
- result = []
185
- until @futures.empty?
186
- f = @futures.shift
187
- result << f.value
188
- end
189
-
190
- result
179
+ self.class._doc_type
191
180
  end
192
181
 
193
182
 
@@ -256,11 +245,13 @@ module CouchPillow
256
245
  # @return nil if not found or Document is of a different type.
257
246
  #
258
247
  def self.get id
259
- result, _, cas = default_db.get(id, extended: true)
248
+ id = _sanitize_id(id)
249
+ tid = _is_type_prefixed? ? "#{_doc_type}::#{id}" : id
250
+ result, _, cas = _default_db.get(tid, extended: true)
260
251
 
261
252
  result and
262
253
  type = result[:_type] || result["_type"] and
263
- type == doc_type and
254
+ type == _doc_type and
264
255
  new(result, id, cas) or
265
256
  nil
266
257
  end
@@ -277,33 +268,6 @@ module CouchPillow
277
268
  end
278
269
 
279
270
 
280
- # Sets the type of this Document.
281
- #
282
- def self.type value
283
- @type = value.to_s
284
- end
285
-
286
-
287
- # Set a DB connection. Overrides the default CouchPillow.db connection
288
- # for the first time this method gets called. Subsequent calls will set
289
- # secondary connections, which will only be used for write only.
290
- #
291
- # Example:
292
- # db primary_db # use for both read and write
293
- # db backup_db1 # write only
294
- # db backup_db2 # write only
295
- #
296
- def self.db conn
297
- # set the primary db connection
298
- @primary_db ||= conn
299
-
300
- # insert as backup db connections
301
- if conn && @primary_db && conn != @primary_db
302
- secondary_dbs << conn
303
- end
304
- end
305
-
306
-
307
271
  # Registers a listener on a specific event.
308
272
  # See {EVENTS} constant for a list of accepted events.
309
273
  #
@@ -312,28 +276,27 @@ module CouchPillow
312
276
  end
313
277
 
314
278
 
279
+ # Inherit directives
280
+ def self.inherited subclass
281
+ attributes.each do |k, v|
282
+ subclass.attributes[k] = v
283
+ end
284
+ subclass.type_prefix(_is_type_prefixed?)
285
+ subclass.type(_doc_type)
286
+ end
287
+
288
+
315
289
  private
316
290
 
317
291
 
318
292
  # Timestamp this document
319
293
  #
320
- def timestamp!
294
+ def _timestamp!
321
295
  @data[:_updated_at] = Time.now.utc
322
296
  end
323
297
 
324
298
 
325
- def write_to_secondary_dbs &block
326
- unless self.class.secondary_dbs.empty?
327
- @futures << Celluloid::Future.new do
328
- self.class.secondary_dbs.each do |db|
329
- block.call(db)
330
- end
331
- end
332
- end
333
- end
334
-
335
-
336
- def cas_handler &block
299
+ def _cas_handler &block
337
300
  # write to the primary db first
338
301
  rtcount = CAS_CONFLICT_RETRY_COUNT
339
302
  begin
@@ -343,13 +306,13 @@ module CouchPillow
343
306
  raise
344
307
 
345
308
  rescue Couchbase::Error::KeyExists
346
- other_doc, _, newcas = self.class.default_db.get(@id, extended: true)
309
+ other_doc, _, newcas = self.class._default_db.get(db_id, extended: true)
347
310
  raise CASError, "There is a CAS conflict, but DB does not yield a document" unless other_doc
348
311
  raise CASError, "There is a CAS conflict, but no :cas_conflict handler has been defined. See 'on' directive." unless self.class.event_listeners[:cas_conflict]
349
312
 
350
313
  # resolve conflict
351
314
  other_doc = self.class.symbolize(other_doc)
352
- @data = self.class.event_listeners[:cas_conflict].call(@original, other_doc, to_save)
315
+ @data = self.class.event_listeners[:cas_conflict].call(@original, other_doc, _to_save)
353
316
  @cas = newcas
354
317
 
355
318
  rtcount -= 1
@@ -363,20 +326,23 @@ module CouchPillow
363
326
  # Get the final hash that will be saved to the database.
364
327
  # Check if data has been modified.
365
328
  #
366
- def to_save
329
+ def _to_save
367
330
  hash = @data.hash
368
331
  return @tos if @tos && @toshash && @toshash == hash
369
332
 
370
333
  @tos = @data.merge({
371
- :_type => self.class.doc_type
334
+ :_type => doc_type
372
335
  })
373
336
  @toshash = @data.hash
374
337
  @tos
375
338
  end
376
339
 
377
340
 
378
- def self.doc_type
379
- @type ||= DEFAULT_TYPE
341
+ # Get the final id value that will be saved to the database.
342
+ #
343
+ def db_id
344
+ @id = self.class._sanitize_id(@id)
345
+ self.class._is_type_prefixed? ? "#{doc_type}::#{@id}" : @id
380
346
  end
381
347
 
382
348
 
@@ -385,16 +351,6 @@ module CouchPillow
385
351
  end
386
352
 
387
353
 
388
- def self.default_db
389
- @default_db ||= (@primary_db || CouchPillow.db)
390
- end
391
-
392
-
393
- def self.secondary_dbs
394
- @secondary_dbs ||= []
395
- end
396
-
397
-
398
354
  def self.event_listeners
399
355
  @event_listeners ||= {}
400
356
  end
@@ -1,5 +1,5 @@
1
1
  module CouchPillow
2
2
  GEM_NAME = "couchpillow"
3
3
  NAME = "CouchPillow"
4
- VERSION = "0.4.5"
4
+ VERSION = "0.4.6"
5
5
  end
@@ -209,8 +209,8 @@ class TestDocument < Minitest::Test
209
209
 
210
210
 
211
211
  def test_get_returns_nil
212
- CouchPillow.db.expects(:get).with('123', { extended: true }).returns(nil)
213
- Document.expects(:default_db).returns(CouchPillow.db)
212
+ CouchPillow.db.expects(:get).with('couchpillow::123', { extended: true }).returns(nil)
213
+ Document.expects(:_default_db).returns(CouchPillow.db)
214
214
  d = Document.get('123')
215
215
  assert_equal nil, d
216
216
  end
@@ -221,11 +221,6 @@ class TestDocument < Minitest::Test
221
221
  type 'test'
222
222
  end
223
223
 
224
- CouchPillow.db
225
- .expects(:get)
226
- .with('123', { extended: true })
227
- .returns( { '_type' => 'something else', 'stuff' => 'data' } )
228
-
229
224
  d = klass.get('123')
230
225
  assert_equal nil, d
231
226
  end
@@ -417,7 +412,7 @@ class TestDocument < Minitest::Test
417
412
  def test_custom_db_connection
418
413
  conn1 = FakeCouchbaseServer.new
419
414
 
420
- d = Class.new(Document) do
415
+ klass = Class.new(Document) do
421
416
  type 'test'
422
417
 
423
418
  db conn1
@@ -428,20 +423,16 @@ class TestDocument < Minitest::Test
428
423
  required
429
424
  default { "tester" }
430
425
  end
426
+ end
431
427
 
432
-
433
- def initialize doc = {}
434
- super(doc, "1")
435
- end
436
-
437
- end.new
428
+ d = klass.new({}, "1")
438
429
  d.foo = "hello"
439
430
  d.save!
440
431
 
441
- fromdefdb = CouchPillow.db.get("1")
432
+ fromdefdb = CouchPillow.db.get("test::1")
442
433
  assert_nil fromdefdb
443
434
 
444
- fromprimdb = conn1.get("1")
435
+ fromprimdb = conn1.get("test::1")
445
436
  assert_equal "hello", fromprimdb[:foo]
446
437
  end
447
438
 
@@ -451,8 +442,9 @@ class TestDocument < Minitest::Test
451
442
  db2 = FakeCouchbaseServer.new
452
443
  db3 = FakeCouchbaseServer.new
453
444
 
454
- d = Class.new(Document) do
445
+ klass = Class.new(Document) do
455
446
  type 'test'
447
+ type_prefix false
456
448
 
457
449
  db db1
458
450
  db db2
@@ -465,16 +457,13 @@ class TestDocument < Minitest::Test
465
457
  default { "tester" }
466
458
  end
467
459
 
460
+ end
468
461
 
469
- def initialize doc = {}
470
- super(doc, "1")
471
- end
472
-
473
- end.new
462
+ d = klass.new( {}, "1" )
474
463
  d.foo = "hello"
475
464
  d.save!
476
465
 
477
- res = d.wait
466
+ res = klass.wait
478
467
 
479
468
  data = db1.get("1")
480
469
  assert_equal "hello", data[:foo]
@@ -551,4 +540,124 @@ class TestDocument < Minitest::Test
551
540
  end
552
541
 
553
542
 
543
+ def test_type_prefix_directive_default
544
+ assert Document._is_type_prefixed?, "type_prefix default is not true"
545
+ end
546
+
547
+
548
+ def test_type_prefix_directive_false
549
+ klass = Class.new(Document) do
550
+ type 'test'
551
+ type_prefix false
552
+
553
+ attribute :foo do
554
+ type String
555
+ end
556
+ end
557
+
558
+ d = klass.new( { foo: "Hello" } , "10" )
559
+ d.save!
560
+
561
+ dataindb = CouchPillow.db.get("10")
562
+ assert dataindb
563
+ assert_equal "Hello", dataindb[:foo]
564
+ end
565
+
566
+
567
+ def test_type_prefix_directive_true
568
+ klass = Class.new(Document) do
569
+ type 'test'
570
+
571
+ attribute :foo do
572
+ type String
573
+ end
574
+ end
575
+
576
+ d = klass.new( { foo: "Hello" } , "10" )
577
+ assert_equal "10", d.id
578
+ d.save!
579
+
580
+ d1 = klass.get("10")
581
+ assert_equal "Hello", d1.foo
582
+
583
+ dataindb = CouchPillow.db.get("test::10")
584
+ assert dataindb
585
+ assert_equal "Hello", dataindb[:foo]
586
+ end
587
+
588
+
589
+ def test_new_with_type_prefix
590
+ klass = Class.new(Document) do
591
+ type 'test'
592
+
593
+ attribute :foo do
594
+ type String
595
+ end
596
+ end
597
+
598
+ d = klass.new( { foo: "Hello" } , "test::10" )
599
+ assert_equal "10", d.id
600
+
601
+ d = klass.new( { foo: "Hello" } , "wrong::10" )
602
+ assert_equal "wrong::10", d.id
603
+
604
+ klass = Class.new(Document) do
605
+ type 'test'
606
+ type_prefix false
607
+
608
+ attribute :foo do
609
+ type String
610
+ end
611
+ end
612
+
613
+ d = klass.new( { foo: "Hello" } , "test::10" )
614
+ assert_equal "test::10", d.id
615
+
616
+ d = klass.new( { foo: "Hello" } , "wrong::10" )
617
+ assert_equal "wrong::10", d.id
618
+ end
619
+
620
+
621
+ def test_content_directive
622
+ klass = Class.new(Document) do
623
+ type 'test'
624
+
625
+ attribute :foo do
626
+ type String
627
+ content { |v| v == "must" }
628
+ end
629
+ end
630
+
631
+ d = klass.new( foo: "Hello" )
632
+
633
+ assert_raises CouchPillow::ValidationError do
634
+ d.save!
635
+ end
636
+
637
+ d.foo = "must"
638
+ d.save!
639
+ end
640
+
641
+
642
+ def test_validate_content_alias
643
+ klass = Class.new(Document) do
644
+ type 'test'
645
+
646
+ attribute :foo do
647
+ type String
648
+ validate_content { |v| v == "must" }
649
+ end
650
+ end
651
+
652
+ d = klass.new( foo: "Hello" )
653
+
654
+ assert_raises CouchPillow::ValidationError do
655
+ d.save!
656
+ end
657
+
658
+ d.foo = "must"
659
+ d.save!
660
+ end
661
+
662
+
554
663
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couchpillow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Albert Tedja
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-14 00:00:00.000000000 Z
11
+ date: 2015-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: celluloid
@@ -92,9 +92,11 @@ files:
92
92
  - Rakefile
93
93
  - couchpillow.gemspec
94
94
  - lib/couchpillow.rb
95
- - lib/couchpillow/attribute.rb
96
- - lib/couchpillow/attributive.rb
97
95
  - lib/couchpillow/boolean.rb
96
+ - lib/couchpillow/directives/attribute.rb
97
+ - lib/couchpillow/directives/multi_db.rb
98
+ - lib/couchpillow/directives/type.rb
99
+ - lib/couchpillow/directives/type_prefix.rb
98
100
  - lib/couchpillow/document.rb
99
101
  - lib/couchpillow/errors.rb
100
102
  - lib/couchpillow/version.rb
@@ -1,39 +0,0 @@
1
- module CouchPillow
2
-
3
- module Attributive
4
-
5
- # Declares a new Attribute
6
- #
7
- def attribute attr, &block
8
- attr = attr.to_s.to_sym
9
- new_attr = Attribute.new(attr)
10
- attributes[attr] = new_attr
11
-
12
- # Define accessor methods
13
- define_method(attr) do
14
- @data[attr]
15
- end
16
- define_method("#{attr}=") do |val|
17
- @data[attr] = val
18
- end
19
-
20
- new_attr.instance_eval &block if block
21
-
22
- new_attr
23
- end
24
-
25
-
26
- def attributes
27
- @attributes ||= {}
28
- end
29
-
30
-
31
- def inherited(subclass)
32
- # Copy existing attributes to subclasses
33
- attributes.each do |k, v|
34
- subclass.attributes[k] = v
35
- end
36
- end
37
-
38
- end
39
- end