mongoid_revisions 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +18 -2
- data/lib/mongoid_revisions.rb +1 -106
- data/lib/mongoid_revisions/revisions.rb +123 -0
- data/lib/mongoid_revisions/revisions/version.rb +3 -0
- data/lib/mongoid_revisions/version.rb +1 -1
- data/mongoid_revisions.gemspec +4 -3
- data/spec/mongoid/models/contributor.rb +9 -0
- data/spec/mongoid/models/deadline.rb +9 -0
- data/spec/mongoid/models/milestone.rb +1 -0
- data/spec/mongoid/models/project.rb +3 -0
- data/spec/mongoid_revisions/revisions_spec.rb +27 -1
- metadata +17 -13
data/README.md
CHANGED
@@ -36,6 +36,10 @@ To add support for revisions to a Mongoid documents, include the module to your
|
|
36
36
|
- revise
|
37
37
|
- branch
|
38
38
|
|
39
|
+
### Added Class Method
|
40
|
+
|
41
|
+
- revisions
|
42
|
+
|
39
43
|
### Token Field
|
40
44
|
|
41
45
|
Token is a randomly generated string that is common to all revisions of the same document and it is write protected to preserve the functionality of this library.
|
@@ -73,7 +77,7 @@ and the returned document will have a different token and will be at revision 0.
|
|
73
77
|
To access all revisions for a given document, use
|
74
78
|
|
75
79
|
```ruby
|
76
|
-
|
80
|
+
revisions :exclude => [:users,:books]
|
77
81
|
```
|
78
82
|
|
79
83
|
### Tag a revision
|
@@ -110,6 +114,15 @@ You can navigate thru all revisions of a document by using the 'next' and 'previ
|
|
110
114
|
@comment.previous
|
111
115
|
```
|
112
116
|
|
117
|
+
### Excluding a related object from revisions
|
118
|
+
|
119
|
+
Sometimes you don't want that all documents' related objects undergo revisions process. In this case, add the following statement to your class definition
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
@comment.next
|
123
|
+
```
|
124
|
+
|
125
|
+
|
113
126
|
## Relations Gotcha
|
114
127
|
|
115
128
|
At present time, not all relation types supported by Mongoid get cloned by this gem.
|
@@ -123,12 +136,15 @@ Here follow a list of all relation types with the indication in they are support
|
|
123
136
|
- embeds_many : UNSUPPORTED
|
124
137
|
- embeds_one : UNSUPPORTED
|
125
138
|
|
139
|
+
**Please note that starting from version 0.0.5 the revision process is recursive, so that if an associated object supports revision then it will undergo revision an so will be with all its associated objects, and so on.**
|
140
|
+
|
126
141
|
## Future changes (sort of TODO list)
|
127
142
|
|
128
|
-
- Recursive revision to linked documents
|
129
143
|
- Add search method for tag
|
130
144
|
- Add support for cloning of "embeds_many" and "embeds_one" relations
|
131
145
|
- Add relation blacklist for all relations you don't want to clone
|
146
|
+
- Verify if Mongoid:Versioning works when using this gem
|
147
|
+
- Verify if Mongoid:Paranoia still works when using this gem
|
132
148
|
|
133
149
|
## Development
|
134
150
|
|
data/lib/mongoid_revisions.rb
CHANGED
@@ -1,106 +1 @@
|
|
1
|
-
require "mongoid_revisions/
|
2
|
-
|
3
|
-
module Mongoid
|
4
|
-
module Revisions
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
field :revision, :type => Integer, :default => 0
|
9
|
-
field :tag, :type => String, :default => "0.0.0"
|
10
|
-
field :token, :type => String
|
11
|
-
|
12
|
-
index :token
|
13
|
-
|
14
|
-
set_callback :create, :before, :create_unique_token
|
15
|
-
end
|
16
|
-
|
17
|
-
# BLOCK ACCESS TO REVISION ATTRIBUTE
|
18
|
-
def revision=(rev)
|
19
|
-
# DOES NOTHING
|
20
|
-
end
|
21
|
-
|
22
|
-
# BLOCK ACCESS TO TOKEN ATTRIBUTE
|
23
|
-
def token=(tok)
|
24
|
-
# DOES NOTHING
|
25
|
-
end
|
26
|
-
|
27
|
-
# RETURN ALL REVISIONS FOR THIS DOCUMENT
|
28
|
-
def revisions
|
29
|
-
self.class.where(:token=>self.token).order_by([[:revision,:asc]])
|
30
|
-
end
|
31
|
-
|
32
|
-
# RETURN A SPECIFIC REVISION
|
33
|
-
def at_revision(revision)
|
34
|
-
self.class.where(:token=>self.token,:revision=>revision.to_i).first
|
35
|
-
end
|
36
|
-
|
37
|
-
# RETURN A SPECIFIC REVISION WITH A SPECIFIC TAG
|
38
|
-
def tagged(tag)
|
39
|
-
self.class.where(:token=>self.token,:tag=>tag).first
|
40
|
-
end
|
41
|
-
|
42
|
-
# RETURN NEXT REVISION
|
43
|
-
def next
|
44
|
-
at_revision(self.revision+1)
|
45
|
-
end
|
46
|
-
|
47
|
-
# RETURN PREVIOUS REVISION
|
48
|
-
def previous
|
49
|
-
at_revision(self.revision-1)
|
50
|
-
end
|
51
|
-
|
52
|
-
# ASSIGN A NEW TAG TO THIS REVISION
|
53
|
-
def tag_revision(tag)
|
54
|
-
self.tag=tag
|
55
|
-
self.save
|
56
|
-
end
|
57
|
-
|
58
|
-
# CREATE A NEW REVISION FOR THE DOCUMENT
|
59
|
-
def revise
|
60
|
-
self._revise_or_branch((self.revision || 1) + 1,self.token)
|
61
|
-
end
|
62
|
-
|
63
|
-
# CREATE A NEW BRANCH
|
64
|
-
def branch
|
65
|
-
self._revise_or_branch(0)
|
66
|
-
end
|
67
|
-
|
68
|
-
protected
|
69
|
-
|
70
|
-
def _revise_or_branch(revision,token=nil)
|
71
|
-
new = self.class.create self.attributes.except("_id")
|
72
|
-
new._token = token
|
73
|
-
new._revision = revision
|
74
|
-
new.tag = "#{new.revision}.0.0"
|
75
|
-
new.save
|
76
|
-
self.relations.each do |relation|
|
77
|
-
metadata=relation[1]
|
78
|
-
if metadata[:relation]==Mongoid::Relations::Embedded::Many or metadata[:relation]==Mongoid::Relations::Embedded::One
|
79
|
-
# TODO
|
80
|
-
elsif metadata[:relation]!=Mongoid::Relations::Referenced::In
|
81
|
-
metadata.class_name.constantize.where(metadata.foreign_key.to_sym=>self.id).each do |child|
|
82
|
-
new_child = metadata.class_name.constantize.create child.attributes.except("_id")
|
83
|
-
new_child.revision = child.revision+1
|
84
|
-
new_child.tag = "#{new_child.revision}.0.0"
|
85
|
-
new_child[metadata.foreign_key.to_sym]=new.id
|
86
|
-
new_child.save
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
new
|
91
|
-
end
|
92
|
-
|
93
|
-
def _revision=(rev)
|
94
|
-
self[:revision]=rev
|
95
|
-
end
|
96
|
-
|
97
|
-
def _token=(tok)
|
98
|
-
self[:token]=tok
|
99
|
-
end
|
100
|
-
|
101
|
-
# CREATE A UNIQUE ID FOR THE DOCUMENT BUT ONLY IF TOKEN IS EMPTY
|
102
|
-
def create_unique_token
|
103
|
-
self._token=SecureRandom.hex(16) if self.token.nil?
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
1
|
+
require "mongoid_revisions/revisions"
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Revisions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
field :revision, :type => Integer, :default => 0
|
7
|
+
field :tag, :type => String, :default => "0.0.0"
|
8
|
+
field :token, :type => String
|
9
|
+
|
10
|
+
cattr_accessor :exclude_list
|
11
|
+
|
12
|
+
index :token
|
13
|
+
|
14
|
+
set_callback :create, :before, :create_unique_token
|
15
|
+
end
|
16
|
+
|
17
|
+
# BLOCK ACCESS TO REVISION ATTRIBUTE
|
18
|
+
def revision=(rev)
|
19
|
+
# DOES NOTHING
|
20
|
+
end
|
21
|
+
|
22
|
+
# BLOCK ACCESS TO TOKEN ATTRIBUTE
|
23
|
+
def token=(tok)
|
24
|
+
# DOES NOTHING
|
25
|
+
end
|
26
|
+
|
27
|
+
# RETURN ALL REVISIONS FOR THIS DOCUMENT
|
28
|
+
def revisions
|
29
|
+
self.class.where(:token=>self.token).order_by([[:revision,:asc]])
|
30
|
+
end
|
31
|
+
|
32
|
+
# RETURN A SPECIFIC REVISION
|
33
|
+
def at_revision(revision)
|
34
|
+
self.class.where(:token=>self.token,:revision=>revision.to_i).first
|
35
|
+
end
|
36
|
+
|
37
|
+
# RETURN A SPECIFIC REVISION WITH A SPECIFIC TAG
|
38
|
+
def tagged(tag)
|
39
|
+
self.class.where(:token=>self.token,:tag=>tag).first
|
40
|
+
end
|
41
|
+
|
42
|
+
# RETURN NEXT REVISION
|
43
|
+
def next
|
44
|
+
at_revision(self.revision+1)
|
45
|
+
end
|
46
|
+
|
47
|
+
# RETURN PREVIOUS REVISION
|
48
|
+
def previous
|
49
|
+
at_revision(self.revision-1)
|
50
|
+
end
|
51
|
+
|
52
|
+
# ASSIGN A NEW TAG TO THIS REVISION
|
53
|
+
def tag_revision(tag)
|
54
|
+
self.tag=tag
|
55
|
+
self.save
|
56
|
+
end
|
57
|
+
|
58
|
+
# CREATE A NEW REVISION FOR THE DOCUMENT
|
59
|
+
def revise
|
60
|
+
self._revise_or_branch((self.revision || 1) + 1,self.token)
|
61
|
+
end
|
62
|
+
|
63
|
+
# CREATE A NEW BRANCH
|
64
|
+
def branch
|
65
|
+
self._revise_or_branch(0)
|
66
|
+
end
|
67
|
+
|
68
|
+
module ClassMethods
|
69
|
+
|
70
|
+
def revisions(*fields)
|
71
|
+
|
72
|
+
options = fields.extract_options!
|
73
|
+
|
74
|
+
self.exclude_list = options[:exclude] || []
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
protected
|
81
|
+
|
82
|
+
def _revise_or_branch(revision,token=nil,attributes=nil)
|
83
|
+
new = self.class.create self.attributes.except("_id")
|
84
|
+
new._token = token
|
85
|
+
new._revision = revision
|
86
|
+
new.tag = "#{new.revision}.0.0"
|
87
|
+
unless attributes.nil?
|
88
|
+
attributes.each do |key,value|
|
89
|
+
new[key]=value
|
90
|
+
end
|
91
|
+
end
|
92
|
+
new.save
|
93
|
+
_exclude_list = self.exclude_list || []
|
94
|
+
self.relations.each do |name, metadata|
|
95
|
+
unless _exclude_list.include?(name.to_sym)
|
96
|
+
if metadata[:relation]==Mongoid::Relations::Embedded::Many or metadata[:relation]==Mongoid::Relations::Embedded::One
|
97
|
+
# TODO
|
98
|
+
elsif metadata[:relation]!=Mongoid::Relations::Referenced::In
|
99
|
+
metadata.class_name.constantize.where(metadata.foreign_key.to_sym=>self.id).each do |child|
|
100
|
+
if child.respond_to?(:revise)
|
101
|
+
child._revise_or_branch(child.revision+1,child.token,{metadata.foreign_key=>new.id})
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
new
|
108
|
+
end
|
109
|
+
|
110
|
+
def _revision=(rev)
|
111
|
+
self[:revision]=rev
|
112
|
+
end
|
113
|
+
|
114
|
+
def _token=(tok)
|
115
|
+
self[:token]=tok
|
116
|
+
end
|
117
|
+
|
118
|
+
# CREATE A UNIQUE ID FOR THE DOCUMENT BUT ONLY IF TOKEN IS EMPTY
|
119
|
+
def create_unique_token
|
120
|
+
self._token=SecureRandom.hex(16) if self.token.nil?
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/mongoid_revisions.gemspec
CHANGED
@@ -5,9 +5,10 @@ require "mongoid_revisions/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "mongoid_revisions"
|
7
7
|
s.version = MongoidRevisions::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
8
9
|
s.authors = ["Emiliano Della Casa"]
|
9
10
|
s.email = ["e.dellacasa@engim.eu"]
|
10
|
-
s.homepage = ""
|
11
|
+
s.homepage = "http://github.com/emilianodellacasa/mongoid_revisions"
|
11
12
|
s.summary = %q{Add support for revisions to your Mongoid documents}
|
12
13
|
s.description = %q{Add support for revisions to your Mongoid documents by creating a new version of a document every time you change it and replicating all of its associations}
|
13
14
|
|
@@ -18,8 +19,8 @@ Gem::Specification.new do |s|
|
|
18
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
20
|
s.require_paths = ["lib"]
|
20
21
|
|
21
|
-
|
22
|
+
s.add_dependency 'mongoid', '~> 2.4.2'
|
23
|
+
s.add_development_dependency "rake"
|
22
24
|
s.add_development_dependency 'rspec', '~> 2.8.0'
|
23
|
-
s.add_development_dependency 'mongoid', '~> 2.4.2'
|
24
25
|
s.add_development_dependency 'bson_ext', '~> 1.5.2'
|
25
26
|
end
|
@@ -2,10 +2,13 @@ class Project
|
|
2
2
|
include Mongoid::Document
|
3
3
|
include Mongoid::Revisions
|
4
4
|
|
5
|
+
revisions :exclude=>[:contributors]
|
6
|
+
|
5
7
|
field :name
|
6
8
|
|
7
9
|
has_many :milestones
|
8
10
|
belongs_to :user
|
11
|
+
has_many :contributors
|
9
12
|
has_one :configuration
|
10
13
|
embeds_many :notes
|
11
14
|
embeds_one :version
|
@@ -5,11 +5,13 @@ describe Mongoid::Revisions do
|
|
5
5
|
Project.delete_all
|
6
6
|
@user = User.create!(:username=>"teddy")
|
7
7
|
@project = Project.create!(:name=>"My first project",:user_id=>@user.id)
|
8
|
-
@project.milestones.create!(:description=>"First Milestone")
|
8
|
+
@milestone = @project.milestones.create!(:description=>"First Milestone")
|
9
|
+
@milestone.deadlines.create!(:description=>"First Deadline")
|
9
10
|
@project.create_configuration(:directory_name=>"/opt/project")
|
10
11
|
@project.notes.create!(:text=>"This is a note")
|
11
12
|
@project.create_version(:description=>"1.0.0")
|
12
13
|
@project.teams.create(:name=>"Team A")
|
14
|
+
@milestone = @project.contributors.create!(:username=>"piggy")
|
13
15
|
end
|
14
16
|
|
15
17
|
context "just created" do
|
@@ -63,6 +65,14 @@ describe Mongoid::Revisions do
|
|
63
65
|
it "should have a index on token" do
|
64
66
|
Project.index_options.count.should==1
|
65
67
|
end
|
68
|
+
|
69
|
+
it "has a single deadline" do
|
70
|
+
@project.milestones.first.deadlines.count.should==1
|
71
|
+
end
|
72
|
+
|
73
|
+
it "has a single contributor" do
|
74
|
+
@project.contributors.count.should==1
|
75
|
+
end
|
66
76
|
end
|
67
77
|
|
68
78
|
|
@@ -186,6 +196,22 @@ describe Mongoid::Revisions do
|
|
186
196
|
it "should me give me nil if there is no previous revision" do
|
187
197
|
@project.previous.should==nil
|
188
198
|
end
|
199
|
+
|
200
|
+
it "should create a new deadline" do
|
201
|
+
Deadline.count.should==2
|
202
|
+
end
|
203
|
+
|
204
|
+
it "last revision has a milestone with a single deadline" do
|
205
|
+
@project.revisions.last.milestones.first.deadlines.count.should==1
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should not create a new contributor" do
|
209
|
+
Contributor.count.should==1
|
210
|
+
end
|
211
|
+
|
212
|
+
it "last revision should have no contributors" do
|
213
|
+
@project.revisions.last.contributors.count.should==0
|
214
|
+
end
|
189
215
|
end
|
190
216
|
|
191
217
|
describe "adding a random number of revisions" do
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: mongoid_revisions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.5
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Emiliano Della Casa
|
@@ -10,39 +10,39 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-02-
|
13
|
+
date: 2012-02-27 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: mongoid
|
17
17
|
prerelease: false
|
18
18
|
requirement: &id001 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
|
-
- -
|
21
|
+
- - ~>
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
24
|
-
type: :
|
23
|
+
version: 2.4.2
|
24
|
+
type: :runtime
|
25
25
|
version_requirements: *id001
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
|
-
name:
|
27
|
+
name: rake
|
28
28
|
prerelease: false
|
29
29
|
requirement: &id002 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
32
|
-
- -
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
34
|
+
version: "0"
|
35
35
|
type: :development
|
36
36
|
version_requirements: *id002
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
|
-
name:
|
38
|
+
name: rspec
|
39
39
|
prerelease: false
|
40
40
|
requirement: &id003 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 2.
|
45
|
+
version: 2.8.0
|
46
46
|
type: :development
|
47
47
|
version_requirements: *id003
|
48
48
|
- !ruby/object:Gem::Dependency
|
@@ -72,10 +72,14 @@ files:
|
|
72
72
|
- README.md
|
73
73
|
- Rakefile
|
74
74
|
- lib/mongoid_revisions.rb
|
75
|
+
- lib/mongoid_revisions/revisions.rb
|
76
|
+
- lib/mongoid_revisions/revisions/version.rb
|
75
77
|
- lib/mongoid_revisions/version.rb
|
76
78
|
- mongoid_revisions.gemspec
|
77
79
|
- spec/.rspec
|
78
80
|
- spec/mongoid/models/configuration.rb
|
81
|
+
- spec/mongoid/models/contributor.rb
|
82
|
+
- spec/mongoid/models/deadline.rb
|
79
83
|
- spec/mongoid/models/milestone.rb
|
80
84
|
- spec/mongoid/models/note.rb
|
81
85
|
- spec/mongoid/models/project.rb
|
@@ -84,7 +88,7 @@ files:
|
|
84
88
|
- spec/mongoid/models/version.rb
|
85
89
|
- spec/mongoid_revisions/revisions_spec.rb
|
86
90
|
- spec/spec_helper.rb
|
87
|
-
homepage:
|
91
|
+
homepage: http://github.com/emilianodellacasa/mongoid_revisions
|
88
92
|
licenses: []
|
89
93
|
|
90
94
|
post_install_message:
|
@@ -107,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
111
|
requirements: []
|
108
112
|
|
109
113
|
rubyforge_project: mongoid_revisions
|
110
|
-
rubygems_version: 1.8.
|
114
|
+
rubygems_version: 1.8.17
|
111
115
|
signing_key:
|
112
116
|
specification_version: 3
|
113
117
|
summary: Add support for revisions to your Mongoid documents
|