couchpillow 0.4.6 → 0.4.7
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 +30 -5
- data/couchpillow.gemspec +0 -1
- data/lib/couchpillow.rb +4 -0
- data/lib/couchpillow/directives/migrate.rb +18 -0
- data/lib/couchpillow/directives/multi_db.rb +5 -9
- data/lib/couchpillow/directives/rename.rb +26 -0
- data/lib/couchpillow/document.rb +16 -27
- data/lib/couchpillow/helper.rb +10 -0
- data/lib/couchpillow/version.rb +1 -1
- data/test/test_document.rb +51 -5
- metadata +5 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e78819a058a79be4256e3a0aeaf532ef3e679877
|
4
|
+
data.tar.gz: af259c1e79e2956b8e6e1095108077469fd08038
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a58b3d6500fe3030149da45066d8bad48a60eb26db5d61d3c2918955b3a8b467b1275418c99ab24f7b4fcaf40cdde17fe5fc8b44b98a8708d750d770b1116d1
|
7
|
+
data.tar.gz: fbe8479ae3d03415816f4df902682943ae994a500566ba15f365f7e5c7ea5a9a04855e75d55b9ccdb9259fd9f84f6cc0620d0fd06df5a822956b07790707ea91
|
data/README.markdown
CHANGED
@@ -75,29 +75,38 @@ Specifying custom id:
|
|
75
75
|
The following are directives that can be used to trigger specific behaviors
|
76
76
|
at the Document level.
|
77
77
|
|
78
|
-
* `type
|
78
|
+
* `type T`
|
79
79
|
|
80
80
|
Set the type of the Document.
|
81
81
|
|
82
|
-
* `type_prefix
|
82
|
+
* `type_prefix true|false`
|
83
83
|
|
84
84
|
Default to `true`. If set to false, it removes prefixing document id with
|
85
85
|
the document type. Leaving this to true is the recommended behavior to avoid
|
86
86
|
id conflicts between different types of documents, especially when custom
|
87
87
|
ids are being used.
|
88
88
|
|
89
|
-
* `attribute
|
89
|
+
* `attribute name, &block`
|
90
90
|
|
91
91
|
Declares an attribute for this Document. You can specify additional
|
92
92
|
directives for each attribute. See Attributes section.
|
93
93
|
|
94
|
-
* `db
|
94
|
+
* `db connection`
|
95
95
|
|
96
96
|
Sets the database connections. If set once, it will set that connection as
|
97
97
|
the primary connection. Any subsequent calls to this directive will set
|
98
98
|
those connections as secondary connections. See Multiple DB Connections
|
99
99
|
section.
|
100
100
|
|
101
|
+
* `rename`
|
102
|
+
|
103
|
+
Rename keys. See Migration section.
|
104
|
+
|
105
|
+
* `migrate`
|
106
|
+
|
107
|
+
Migrate the value of a key. This gets triggered when Document is initialized.
|
108
|
+
See Migration section.
|
109
|
+
|
101
110
|
|
102
111
|
|
103
112
|
### Attributes
|
@@ -224,7 +233,7 @@ Using `rename` to rename keys. Useful to maintain document integrity
|
|
224
233
|
after a migration.
|
225
234
|
|
226
235
|
class User < CouchPillow::Document
|
227
|
-
rename :username
|
236
|
+
rename :username => :nickname
|
228
237
|
attribute :nickname
|
229
238
|
end
|
230
239
|
u = User.new( { :username => 'jdoe' } )
|
@@ -235,6 +244,22 @@ that queries each document in the database and updates them, or you can
|
|
235
244
|
simply use this inside your application code, so it only migrates the document
|
236
245
|
as it reads them.
|
237
246
|
|
247
|
+
You can also migrate the values. The `migrate` directive is trigger when
|
248
|
+
Document is initialized, but after the `rename`.
|
249
|
+
This is useful if you have Documents whose values are in the old format
|
250
|
+
and you want to convert them.
|
251
|
+
|
252
|
+
class User < CouchPillow::Document
|
253
|
+
rename :nickname => :nicknames
|
254
|
+
|
255
|
+
attribute :nicknames
|
256
|
+
|
257
|
+
migrate :nicknames do |v|
|
258
|
+
v.class == String ? [v] : v
|
259
|
+
end
|
260
|
+
end
|
261
|
+
u = User.new( { :nickname => 'jdoe' } )
|
262
|
+
u.nicknames # ['jdoe']
|
238
263
|
|
239
264
|
|
240
265
|
## Design Docs and Views
|
data/couchpillow.gemspec
CHANGED
data/lib/couchpillow.rb
CHANGED
@@ -15,10 +15,14 @@ module CouchPillow
|
|
15
15
|
|
16
16
|
end
|
17
17
|
|
18
|
+
require 'couchpillow/helper'
|
19
|
+
|
18
20
|
require 'couchpillow/directives/type'
|
19
21
|
require 'couchpillow/directives/type_prefix'
|
20
22
|
require 'couchpillow/directives/attribute'
|
21
23
|
require 'couchpillow/directives/multi_db'
|
24
|
+
require 'couchpillow/directives/rename'
|
25
|
+
require 'couchpillow/directives/migrate'
|
22
26
|
|
23
27
|
require 'couchpillow/errors'
|
24
28
|
require 'couchpillow/boolean'
|
@@ -1,7 +1,3 @@
|
|
1
|
-
require 'celluloid/autostart'
|
2
|
-
|
3
|
-
Celluloid.logger = nil
|
4
|
-
|
5
1
|
module CouchPillow
|
6
2
|
|
7
3
|
module MultiDBDirective
|
@@ -38,7 +34,7 @@ module CouchPillow
|
|
38
34
|
|
39
35
|
def _write_to_secondary_dbs &block
|
40
36
|
unless _secondary_dbs.empty?
|
41
|
-
|
37
|
+
_threads << Thread.new do
|
42
38
|
_secondary_dbs.each do |db|
|
43
39
|
block.call(db)
|
44
40
|
end
|
@@ -47,8 +43,8 @@ module CouchPillow
|
|
47
43
|
end
|
48
44
|
|
49
45
|
|
50
|
-
def
|
51
|
-
@
|
46
|
+
def _threads
|
47
|
+
@threads ||= []
|
52
48
|
end
|
53
49
|
|
54
50
|
|
@@ -57,8 +53,8 @@ module CouchPillow
|
|
57
53
|
#
|
58
54
|
def wait
|
59
55
|
result = []
|
60
|
-
until
|
61
|
-
f =
|
56
|
+
until _threads.empty?
|
57
|
+
f = _threads.shift
|
62
58
|
result << f.value
|
63
59
|
end
|
64
60
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module CouchPillow
|
2
|
+
|
3
|
+
module RenameDirective
|
4
|
+
|
5
|
+
RESERVED_KEYS = %i[_id _type _created_at _updated_at]
|
6
|
+
|
7
|
+
# Rename keys from one to another
|
8
|
+
#
|
9
|
+
def rename map
|
10
|
+
map.each do |k, v|
|
11
|
+
raise ArgumentError, "Cannot rename reserved keys" if
|
12
|
+
RESERVED_KEYS.include?(k) || RESERVED_KEYS.include?(v)
|
13
|
+
end
|
14
|
+
|
15
|
+
smap = CouchPillow.symbolize(map)
|
16
|
+
|
17
|
+
rename_keys.merge!(smap)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def rename_keys
|
22
|
+
@rename_keys ||= {}
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/lib/couchpillow/document.rb
CHANGED
@@ -6,10 +6,11 @@ module CouchPillow
|
|
6
6
|
extend TypePrefixDirective
|
7
7
|
extend AttributeDirective
|
8
8
|
extend MultiDBDirective
|
9
|
+
extend RenameDirective
|
10
|
+
extend MigrateDirective
|
9
11
|
|
10
12
|
attr_accessor :id
|
11
13
|
|
12
|
-
RESERVED_KEYS = %i[_id _type _created_at _updated_at]
|
13
14
|
|
14
15
|
EVENTS = [ :cas_conflict ].freeze
|
15
16
|
|
@@ -44,7 +45,7 @@ module CouchPillow
|
|
44
45
|
id = SecureRandom.hex,
|
45
46
|
cas = nil
|
46
47
|
|
47
|
-
@data =
|
48
|
+
@data = CouchPillow.symbolize(hash)
|
48
49
|
@original = Marshal.load(Marshal.dump(@data))
|
49
50
|
|
50
51
|
@id = self.class._is_type_prefixed? ? self.class._sanitize_id(id) : id
|
@@ -58,6 +59,7 @@ module CouchPillow
|
|
58
59
|
rename!
|
59
60
|
whitelist!
|
60
61
|
assign_defaults!
|
62
|
+
migrate!
|
61
63
|
auto_convert!
|
62
64
|
end
|
63
65
|
|
@@ -137,6 +139,17 @@ module CouchPillow
|
|
137
139
|
end
|
138
140
|
|
139
141
|
|
142
|
+
# Run the migration directive
|
143
|
+
#
|
144
|
+
def migrate!
|
145
|
+
self.class.migrate_keys.each do |k, pr|
|
146
|
+
if @data.has_key? k
|
147
|
+
@data[k] = pr.call @data[k]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
140
153
|
# Updates the attributes in the document.
|
141
154
|
# Existing attributes will be overwritten and new ones will be added.
|
142
155
|
# Any other existing attributes that are not present in the hash will be ignored.
|
@@ -257,17 +270,6 @@ module CouchPillow
|
|
257
270
|
end
|
258
271
|
|
259
272
|
|
260
|
-
# Rename an existing key to a new key. This is invoked right after
|
261
|
-
# initialize.
|
262
|
-
#
|
263
|
-
def self.rename from, to
|
264
|
-
raise ArgumentError, "Cannot rename reserved keys" if
|
265
|
-
RESERVED_KEYS.include?(from) || RESERVED_KEYS.include?(to)
|
266
|
-
|
267
|
-
rename_keys << [from.to_s.to_sym, to.to_s.to_sym]
|
268
|
-
end
|
269
|
-
|
270
|
-
|
271
273
|
# Registers a listener on a specific event.
|
272
274
|
# See {EVENTS} constant for a list of accepted events.
|
273
275
|
#
|
@@ -311,7 +313,7 @@ module CouchPillow
|
|
311
313
|
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]
|
312
314
|
|
313
315
|
# resolve conflict
|
314
|
-
other_doc =
|
316
|
+
other_doc = CouchPillow.symbolize(other_doc)
|
315
317
|
@data = self.class.event_listeners[:cas_conflict].call(@original, other_doc, _to_save)
|
316
318
|
@cas = newcas
|
317
319
|
|
@@ -346,22 +348,9 @@ module CouchPillow
|
|
346
348
|
end
|
347
349
|
|
348
350
|
|
349
|
-
def self.rename_keys
|
350
|
-
@rename_keys ||= []
|
351
|
-
end
|
352
|
-
|
353
|
-
|
354
351
|
def self.event_listeners
|
355
352
|
@event_listeners ||= {}
|
356
353
|
end
|
357
354
|
|
358
|
-
|
359
|
-
def self.symbolize hash
|
360
|
-
hash.inject({}) do |memo,(k,v)|
|
361
|
-
memo[k.to_sym] = v
|
362
|
-
memo
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
355
|
end
|
367
356
|
end
|
data/lib/couchpillow/version.rb
CHANGED
data/test/test_document.rb
CHANGED
@@ -155,7 +155,7 @@ class TestDocument < Minitest::Test
|
|
155
155
|
attribute(:bar)
|
156
156
|
attribute(:other)
|
157
157
|
|
158
|
-
rename :foo
|
158
|
+
rename :foo => :bar
|
159
159
|
end.new( { :foo => 123, :other => 'abc' } )
|
160
160
|
assert_equal 123, d[:bar]
|
161
161
|
assert_equal 123, d.bar
|
@@ -165,28 +165,44 @@ class TestDocument < Minitest::Test
|
|
165
165
|
end
|
166
166
|
|
167
167
|
|
168
|
+
def test_rename_keys_multiple
|
169
|
+
d = Class.new(Document) do
|
170
|
+
attribute(:bar)
|
171
|
+
attribute(:other)
|
172
|
+
|
173
|
+
rename :foo => :bar, :dump => :other
|
174
|
+
end.new( { :foo => 123, :dump => 'abc' } )
|
175
|
+
assert_equal 123, d[:bar]
|
176
|
+
assert_equal 123, d.bar
|
177
|
+
assert_equal nil, d[:foo]
|
178
|
+
refute d.respond_to?(:foo)
|
179
|
+
refute d.respond_to?(:dump)
|
180
|
+
assert_equal 'abc', d.other
|
181
|
+
end
|
182
|
+
|
183
|
+
|
168
184
|
def test_rename_keys_reserved_keys
|
169
185
|
assert_raises ArgumentError do
|
170
186
|
d = Class.new(Document) do
|
171
|
-
rename :_id
|
187
|
+
rename :_id => :bad
|
172
188
|
end.new
|
173
189
|
end
|
174
190
|
|
175
191
|
assert_raises ArgumentError do
|
176
192
|
d = Class.new(Document) do
|
177
|
-
rename :_type
|
193
|
+
rename :_type => :err
|
178
194
|
end.new
|
179
195
|
end
|
180
196
|
|
181
197
|
assert_raises ArgumentError do
|
182
198
|
d = Class.new(Document) do
|
183
|
-
rename :_created_at
|
199
|
+
rename :_created_at => :err
|
184
200
|
end.new
|
185
201
|
end
|
186
202
|
|
187
203
|
assert_raises ArgumentError do
|
188
204
|
d = Class.new(Document) do
|
189
|
-
rename :bla
|
205
|
+
rename :bla => :_updated_at
|
190
206
|
end.new
|
191
207
|
end
|
192
208
|
end
|
@@ -660,4 +676,34 @@ class TestDocument < Minitest::Test
|
|
660
676
|
end
|
661
677
|
|
662
678
|
|
679
|
+
def test_migrate
|
680
|
+
klass = Class.new(Document) do
|
681
|
+
type 'test'
|
682
|
+
|
683
|
+
attribute :foo do
|
684
|
+
type String
|
685
|
+
end
|
686
|
+
|
687
|
+
migrate :foo do |v|
|
688
|
+
if v.class == Hash
|
689
|
+
"omg"
|
690
|
+
elsif v.class == Array
|
691
|
+
123
|
692
|
+
else
|
693
|
+
"yes"
|
694
|
+
end
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
698
|
+
d = klass.new( foo: "Hello" )
|
699
|
+
assert_equal "yes", d.foo
|
700
|
+
|
701
|
+
d = klass.new( foo: { :complex => "data" } )
|
702
|
+
assert_equal "omg", d.foo
|
703
|
+
|
704
|
+
d = klass.new( foo: ["some", "array"] )
|
705
|
+
assert_equal 123, d.foo
|
706
|
+
end
|
707
|
+
|
708
|
+
|
663
709
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
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.7
|
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-
|
11
|
+
date: 2015-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: celluloid
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0.16'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0.16'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: couchbase
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,11 +80,14 @@ files:
|
|
94
80
|
- lib/couchpillow.rb
|
95
81
|
- lib/couchpillow/boolean.rb
|
96
82
|
- lib/couchpillow/directives/attribute.rb
|
83
|
+
- lib/couchpillow/directives/migrate.rb
|
97
84
|
- lib/couchpillow/directives/multi_db.rb
|
85
|
+
- lib/couchpillow/directives/rename.rb
|
98
86
|
- lib/couchpillow/directives/type.rb
|
99
87
|
- lib/couchpillow/directives/type_prefix.rb
|
100
88
|
- lib/couchpillow/document.rb
|
101
89
|
- lib/couchpillow/errors.rb
|
90
|
+
- lib/couchpillow/helper.rb
|
102
91
|
- lib/couchpillow/version.rb
|
103
92
|
- test/helper.rb
|
104
93
|
- test/test_attribute.rb
|