memories 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.markdown +84 -0
  2. data/lib/memories/base.rb +51 -11
  3. metadata +7 -6
data/README.markdown ADDED
@@ -0,0 +1,84 @@
1
+ #Introduction
2
+
3
+ A simple gem for adding versioning to your CouchRest::Model::Base documents. When you update a document, the previous version gets
4
+ stored as an attachment on the document. This versioning strategy was originally created here: http://blog.couch.io/post/632718824/simple-document-versioning-with-couchdb
5
+
6
+ ##Installation
7
+
8
+ $ gem install memories
9
+
10
+ ##How does it work?
11
+
12
+ Just "include Memories" in your "CouchRest::Model::Base" classes and let the auto-versioning begin.
13
+
14
+ ###Basic Versioning
15
+
16
+ Here's how basic versioning works. Every time you save your document, you get a new version. You have the ability to roll back to a previous version.
17
+
18
+ class Book < CouchRest::Model::Base
19
+ include Memories
20
+ use_database SOME_DATABASE
21
+
22
+ property :name
23
+ view_by :name
24
+ end
25
+
26
+ b = Book.create :name => "2001"
27
+ b.current_version #==> 1
28
+ b.name = "2001: A Space Odyssey"
29
+ b.save
30
+ b.current_version #==> 2
31
+ b.previous_version #==> 1
32
+ b.name #==> "2001: A Space Odyssey"
33
+ b.revert_to! 1
34
+ b.name #==> "2001"
35
+ b.current_version #==> 3
36
+
37
+ ###Milestones
38
+
39
+ As of version 0.2.0, Memories also supports milestones. Milestones are special versions that you want to flag in some way.
40
+ For example, suppose you were creating a content management system, and every time someone publishes an article to the website, you want to flag the version
41
+ they published as a milestone.
42
+
43
+ class Article < CouchRest::Model::Base
44
+ include Memories
45
+ use_database SOME_DATABASE
46
+
47
+ property :title
48
+ property :author
49
+ property :body
50
+
51
+ def publish!
52
+ # .... publishing logic
53
+ end
54
+ end
55
+
56
+ a = Article.create(
57
+ :title => "Memories gem makes versioning simple",
58
+ :author => "moonmaster9000",
59
+ :body => <<-ARTICLE
60
+ Check it out at http://github.com/moonmaster9000/memories
61
+ ARTICLE
62
+ )
63
+ a.save
64
+ a.publish!
65
+ a.current_version #==> 1
66
+ a.milestone! do
67
+ name "First publish."
68
+ notes "Passed all relevant editing. Signed off by moonmaster10000"
69
+ end
70
+
71
+ Notice that we annotated our milestone; we gave it a name, and some notes. You can annotate with whatever properties you desire. The annotation do block is entirely optional.
72
+ Now that we've created a milestone, let's inspect it:
73
+
74
+ a.milestones.count #==> 1
75
+ a.latest_milestone.version # ==> 1
76
+ a.latest_milestone.annotations.name ==> "First publish."
77
+ a.latest_milestone.annotations.notes ==> "Passed all relevant editing. Signed off by moonmaster 10000"
78
+
79
+ Now, let's imagine that we've made some more edits / saves to the document, but they don't get approved. Now we want to revert to the version the document was
80
+ at at the first milestone. How do we do that? Simple!
81
+
82
+ a.revert_to_milestone! 1
83
+
84
+ And now our document properties are back to the where they were when we first published the document.
data/lib/memories/base.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Memories
2
2
  def self.included(base)
3
3
  base.property(:milestone_memories) do |milestone_memory|
4
- milestone_memory.property :version, Fixnum
4
+ milestone_memory.property :version
5
5
  milestone_memory.property :annotations, Memories::Annotation
6
6
  end
7
7
 
@@ -11,21 +11,40 @@ module Memories
11
11
 
12
12
  VERSION_REGEX = /(?:rev-)?(\d+)-[a-zA-Z0-9]+/
13
13
 
14
- def revert_to!(version=nil)
15
- version ||= previous_version
16
- if (match = version.to_s.match(VERSION_REGEX)) && match[1]
17
- version = match[1].to_i
18
- end
19
-
20
- if properties = JSON.parse(read_attachment(version_id version))
21
- self.update_attributes properties
22
- end
14
+ def revert_to!(version)
15
+ revert version, :hard
16
+ end
17
+
18
+ def revert_to(version)
19
+ revert version
20
+ end
21
+
22
+ def rollback
23
+ self.revert_to self.previous_version
24
+ end
25
+
26
+ def rollback!
27
+ self.revert_to! self.previous_version
23
28
  end
24
29
 
25
30
  def revert_to_milestone!(n)
31
+ verify_milestone_exists n
26
32
  self.revert_to! self.milestones[n.to_i-1].version
27
33
  end
28
34
 
35
+ def revert_to_milestone(n)
36
+ verify_milestone_exists n
37
+ self.revert_to self.milestones[n.to_i-1].version
38
+ end
39
+
40
+ def rollback_to_latest_milestone
41
+ self.revert_to_milestone self.milestones.count
42
+ end
43
+
44
+ def rollback_to_latest_milestone!
45
+ self.revert_to_milestone! self.milestones.count
46
+ end
47
+
29
48
  def version_id(version_num)
30
49
  self["_attachments"].keys.sort {|a,b| version_number(a) <=> version_number(b)}[version_num - 1] if self["_attachments"]
31
50
  end
@@ -45,7 +64,7 @@ module Memories
45
64
  def milestone!(&block)
46
65
  annotations = Memories::Annotation.new
47
66
  annotations.instance_eval(&block) if block
48
- self.milestone_memories << {:version => self.current_version, :annotations => annotations}
67
+ self.milestone_memories << {:version => self.rev, :annotations => annotations}
49
68
  self.save
50
69
  end
51
70
 
@@ -58,6 +77,27 @@ module Memories
58
77
  end
59
78
 
60
79
  private
80
+ def verify_milestone_exists(n)
81
+ raise StandardError, "This document does not have any milestones." if self.milestones.empty?
82
+ raise StandardError, "Unknown milestone" if n > self.milestones.count
83
+ end
84
+
85
+ def revert(version, revert_type = :soft)
86
+ raise StandardError, "Unknown revert type passed to 'revert' method. Allowed types: :soft, :hard." if revert_type != :soft && revert_type != :hard
87
+
88
+ if (match = version.to_s.match(VERSION_REGEX)) && match[1]
89
+ version = match[1].to_i
90
+ end
91
+
92
+ if properties = JSON.parse(read_attachment(version_id version))
93
+ if revert_type == :soft
94
+ self.update_attributes_without_saving properties
95
+ elsif revert_type == :hard
96
+ self.update_attributes properties
97
+ end
98
+ end
99
+ end
100
+
61
101
  def add_version_attachment
62
102
  current_document_version = Attachment.new prep_for_versioning(self.database.get(self.id, :rev => self.rev)).to_json
63
103
 
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: 23
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 0
10
- version: 0.2.0
9
+ - 1
10
+ version: 0.2.1
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-08-28 00:00:00 -04:00
18
+ date: 2010-08-29 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -41,13 +41,14 @@ executables: []
41
41
 
42
42
  extensions: []
43
43
 
44
- extra_rdoc_files: []
45
-
44
+ extra_rdoc_files:
45
+ - README.markdown
46
46
  files:
47
47
  - lib/memories.rb
48
48
  - lib/memories/annotation.rb
49
49
  - lib/memories/attachment.rb
50
50
  - lib/memories/base.rb
51
+ - README.markdown
51
52
  has_rdoc: true
52
53
  homepage: http://github.com/moonmaster9000/memories
53
54
  licenses: []