memories 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/memories/attachment.rb +3 -3
- data/lib/memories/base.rb +104 -12
- metadata +4 -4
data/lib/memories/attachment.rb
CHANGED
data/lib/memories/base.rb
CHANGED
@@ -7,6 +7,7 @@ module Memories
|
|
7
7
|
end
|
8
8
|
|
9
9
|
base.before_update :add_version_attachment
|
10
|
+
base.after_create :decode_attachments
|
10
11
|
base.after_update :decode_attachments
|
11
12
|
base.send :extend, ClassMethods
|
12
13
|
end
|
@@ -56,6 +57,46 @@ module Memories
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
60
|
+
# Returns true if self is set up to remember attachments. False otherwise.
|
61
|
+
def remember_attachments?
|
62
|
+
@remember_attachments ? true : false
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns a list of attachment patterns for versioning. The list may contain
|
66
|
+
# strings, denoting the names of attachments to version, but it may
|
67
|
+
# also contain regular expressions, indicating that attachments
|
68
|
+
# with matching names should be versioned.
|
69
|
+
def remember_attachments; @remember_attachments || []; end
|
70
|
+
|
71
|
+
# If you'd like to version attachments, simply call this macro in your
|
72
|
+
# class definition:
|
73
|
+
#
|
74
|
+
# class MyDoc < CouchRest::Model::Base
|
75
|
+
# use_database MY_DB
|
76
|
+
# include Memories
|
77
|
+
#
|
78
|
+
# remember_attachments!
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# If you only want specific attachments versioned, pass
|
82
|
+
# strings and/or regular expressions to this macro. Any attachments
|
83
|
+
# with matching names will be versioned.
|
84
|
+
#
|
85
|
+
# class HtmlPage < CouchRest::Model::Base
|
86
|
+
# use_database MY_DB
|
87
|
+
# include Memories
|
88
|
+
#
|
89
|
+
# remember_attachments! "image.png", %r{stylesheets/.*}
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
def remember_attachments!(*attachment_names)
|
93
|
+
if attachment_names.empty?
|
94
|
+
@remember_attachments = [/.*/]
|
95
|
+
else
|
96
|
+
@remember_attachments = attachment_names
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
59
100
|
def remember_properties #:nodoc
|
60
101
|
@remember_properties ||= nil
|
61
102
|
end
|
@@ -75,6 +116,17 @@ module Memories
|
|
75
116
|
|
76
117
|
VERSION_REGEX = /(?:rev-)?(\d+)-[a-zA-Z0-9]+/
|
77
118
|
|
119
|
+
# Returns a list of attachments it should remember.
|
120
|
+
def attachments_to_remember
|
121
|
+
return [] unless self.class.remember_attachments?
|
122
|
+
(self['_attachments'] || {}).keys.reject do |a|
|
123
|
+
a.match(VERSION_REGEX) ||
|
124
|
+
!(self.class.remember_attachments.map { |attachment_name_pattern|
|
125
|
+
a.match attachment_name_pattern
|
126
|
+
}.inject(false) {|b, sum| sum || b})
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
78
130
|
# Revert the document to a specific version and save.
|
79
131
|
# You can provide either a complete revision number ("1-u54abz3948302sjjej3jej300rj", or "rev-1-u54abz3948302sjjej3jej300rj")
|
80
132
|
# or simply a number (e.g, 1, 4, 100, etc.).
|
@@ -128,7 +180,7 @@ module Memories
|
|
128
180
|
# For example, suppose my doc has 5 versions.
|
129
181
|
# my_doc.version_id 4 #==> "rev-4-74fj838r838fhjkdfklasdjrieu4839493"
|
130
182
|
def version_id(version_num)
|
131
|
-
self["_attachments"].keys.
|
183
|
+
self["_attachments"].keys.select {|a| a.match /^rev-#{version_num}-.*$/}.first if self["_attachments"]
|
132
184
|
end
|
133
185
|
|
134
186
|
# Retrieve the version number, given a revision id.
|
@@ -191,18 +243,29 @@ module Memories
|
|
191
243
|
version = match[1].to_i
|
192
244
|
end
|
193
245
|
|
194
|
-
if properties = JSON.parse(read_attachment(version_id version))
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
246
|
+
if properties = JSON.parse(self.read_attachment(version_id version))
|
247
|
+
revert_attachments properties
|
248
|
+
self.update_attributes_without_saving properties
|
249
|
+
self.save if revert_type == :hard
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def revert_attachments(properties)
|
254
|
+
if versioned_attachments = properties.delete('attachment_memories')
|
255
|
+
versioned_attachments['versioned_attachments'].each do |name, attrs|
|
256
|
+
attachment = { :name => name, :content_type => attrs['content_type'], :file => Attachment.new(Base64.decode64(attrs['data']))}
|
257
|
+
has_attachment?(name) ? self.update_attachment(attachment) : self.create_attachment(attachment)
|
258
|
+
end
|
259
|
+
|
260
|
+
self["_attachments"].keys.select {|a| !a.match(VERSION_REGEX)}.each do |attachment|
|
261
|
+
self.delete_attachment(attachment) unless versioned_attachments['known_attachments'].include?(attachment)
|
199
262
|
end
|
200
263
|
end
|
201
264
|
end
|
202
265
|
|
203
266
|
def add_version_attachment
|
204
267
|
current_document_version = Attachment.new prep_for_versioning(self.database.get(self.id, :rev => self.rev)).to_json
|
205
|
-
|
268
|
+
|
206
269
|
self.create_attachment(
|
207
270
|
:file => current_document_version,
|
208
271
|
:content_type => "application/json",
|
@@ -211,16 +274,45 @@ module Memories
|
|
211
274
|
end
|
212
275
|
|
213
276
|
def prep_for_versioning(doc)
|
277
|
+
versioned_doc = doc.dup
|
278
|
+
strip_unversioned_properties versioned_doc
|
279
|
+
add_attachment_memories versioned_doc if self.class.remember_attachments?
|
280
|
+
versioned_doc
|
281
|
+
end
|
282
|
+
|
283
|
+
def add_attachment_memories(doc)
|
284
|
+
doc['attachment_memories'] = {
|
285
|
+
'versioned_attachments' => base64_encoded_attachments_to_remember,
|
286
|
+
'known_attachments' => (self.database.get(self.id, :rev => self.rev)["_attachments"] || {}).keys.select {|a| !a.match(VERSION_REGEX)}
|
287
|
+
}
|
288
|
+
end
|
289
|
+
|
290
|
+
def base64_encoded_attachments_to_remember
|
291
|
+
encoded_attachments = {}
|
292
|
+
attachments_to_remember.each do |a|
|
293
|
+
attachment_data = self.read_attachment(a) rescue nil
|
294
|
+
if attachment_data
|
295
|
+
encoded_attachments[a] = {
|
296
|
+
:content_type => self['_attachments'][a]['content_type'],
|
297
|
+
:data => Base64.encode64(attachment_data)
|
298
|
+
}
|
299
|
+
end
|
300
|
+
end
|
301
|
+
encoded_attachments
|
302
|
+
end
|
303
|
+
|
304
|
+
def strip_unversioned_properties(doc)
|
214
305
|
if self.class.remember_properties.nil?
|
215
|
-
doc.
|
306
|
+
doc.delete_if {|k,v| self.class.forget_properties.include? k}
|
216
307
|
else
|
217
|
-
doc.
|
218
|
-
end
|
308
|
+
doc.delete_if {|k,v| !self.class.remember_properties.include?(k)}
|
309
|
+
end
|
219
310
|
end
|
220
311
|
|
312
|
+
# why is this necessary? Because couchrest destructively base64 encodes all attachments in your document.
|
221
313
|
def decode_attachments
|
222
314
|
self["_attachments"].each do |attachment_id, attachment_properties|
|
223
|
-
|
224
|
-
end
|
315
|
+
self["_attachments"][attachment_id]["data"] = Base64.decode64 attachment_properties["data"] if attachment_properties["data"]
|
316
|
+
end if self["_attachments"]
|
225
317
|
end
|
226
318
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memories
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 4
|
10
|
+
version: 0.2.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matt Parker
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-10-31 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|