couchpillow 0.4.5 → 0.4.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.
- checksums.yaml +4 -4
- data/README.markdown +36 -5
- data/lib/couchpillow.rb +5 -5
- data/lib/couchpillow/{attribute.rb → directives/attribute.rb} +37 -10
- data/lib/couchpillow/directives/multi_db.rb +70 -0
- data/lib/couchpillow/directives/type.rb +28 -0
- data/lib/couchpillow/directives/type_prefix.rb +16 -0
- data/lib/couchpillow/document.rb +51 -95
- data/lib/couchpillow/version.rb +1 -1
- data/test/test_document.rb +132 -23
- metadata +6 -4
- data/lib/couchpillow/attributive.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8a125e7eabce1a8d19853040151e38791c57d07
|
4
|
+
data.tar.gz: ec143b133ab55a2ec34ec2fd7b4f3c9b84831fad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
##
|
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
|
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
|
168
|
-
secondary connections, which will only
|
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/
|
22
|
-
require 'couchpillow/
|
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
|
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,
|
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
|
data/lib/couchpillow/document.rb
CHANGED
@@ -2,19 +2,23 @@ module CouchPillow
|
|
2
2
|
|
3
3
|
class Document
|
4
4
|
|
5
|
-
extend
|
5
|
+
extend TypeDirective
|
6
|
+
extend TypePrefixDirective
|
7
|
+
extend AttributeDirective
|
8
|
+
extend MultiDBDirective
|
6
9
|
|
7
|
-
|
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 =
|
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 =
|
81
|
+
result = _cas_handler do
|
79
82
|
whitelist!
|
80
83
|
sort!
|
81
|
-
|
84
|
+
_timestamp!
|
82
85
|
validate!
|
83
86
|
opts[:cas] = @cas
|
84
|
-
self.class.
|
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
|
-
|
90
|
-
db.set
|
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.
|
103
|
+
result = self.class._default_db.delete(db_id)
|
101
104
|
|
102
105
|
# write to the secondary only if the primary succeeds
|
103
|
-
|
104
|
-
db.delete
|
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 =
|
120
|
+
result = _cas_handler do
|
118
121
|
whitelist!
|
119
122
|
sort!
|
120
|
-
|
123
|
+
_timestamp!
|
121
124
|
validate!
|
122
125
|
opts[:cas] = @cas
|
123
|
-
result = self.class.
|
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
|
-
|
130
|
-
db.replace
|
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 =>
|
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.
|
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
|
-
|
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 ==
|
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
|
294
|
+
def _timestamp!
|
321
295
|
@data[:_updated_at] = Time.now.utc
|
322
296
|
end
|
323
297
|
|
324
298
|
|
325
|
-
def
|
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.
|
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,
|
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
|
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 =>
|
334
|
+
:_type => doc_type
|
372
335
|
})
|
373
336
|
@toshash = @data.hash
|
374
337
|
@tos
|
375
338
|
end
|
376
339
|
|
377
340
|
|
378
|
-
|
379
|
-
|
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
|
data/lib/couchpillow/version.rb
CHANGED
data/test/test_document.rb
CHANGED
@@ -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(:
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =
|
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.
|
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-
|
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
|