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