acts_as_versionable 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,28 +1,29 @@
1
1
  = Acts As Versionable
2
2
 
3
- Minimalist versionable engine for rails > 3
4
- Maintains versions in same table, just adding two new fields
3
+ Minimalist versionable engine for rails > 3
5
4
 
6
-
5
+ Maintains versions in same table, just adding two new fields
7
6
 
8
7
  === Installation
9
8
 
10
9
  gem 'acts_as_versionable'
11
10
 
12
- add two fields to your model
11
+ add two fields to your model
13
12
 
14
13
  version_number:integer
15
14
  version_id:integer
16
15
 
16
+ **Sample migration**
17
+
17
18
  class ActsAsVersionableDocuments < ActiveRecord::Migration
18
19
  def self.up
19
- add_column :documents, :version_number, :default => 0
20
- add_column :documents, :version_id, :default => null
21
-
22
- # optional indexes
23
- add_index :documents, :version_number, :name => "index_documents_on_version_number"
24
- add_index :documents, :version_id, :name => "index_documents_on_version_id"
25
- # optional unique :id, :version_number
20
+ add_column :documents, :version_number, :default => 0
21
+ add_column :documents, :version_id, :default => null
22
+
23
+ # optional indexes
24
+ add_index :documents, :version_number, :name => "index_documents_on_version_number"
25
+ add_index :documents, :version_id, :name => "index_documents_on_version_id"
26
+ # optional unique :id, :version_number
26
27
  end
27
28
 
28
29
  def self.down
@@ -30,17 +31,17 @@
30
31
  remove_column :documents, :version_id
31
32
  end
32
33
  end
33
-
34
+
34
35
  === Example
35
36
 
36
37
  class Document < ActiveRecord::Base
37
38
  acts_as_versionable :limit => 3
38
39
  end
39
40
 
40
- # use scope to get top versions
41
- documents = Document.last_versions => scope that return top versions
41
+ # use scope to get top versions
42
+ documents = Document.last_versions => scope that return most recent versions
42
43
 
43
- # cerate first version
44
+ # create first version
44
45
  document = Document.create(:title => 'title', :body => 'body')
45
46
  document.version => 1
46
47
  document.last_version => 1
@@ -56,14 +57,45 @@
56
57
 
57
58
  # revert to version 1
58
59
  document.revert_to_version(1) => #<Document ...>
59
- document.version => 3 # after revert a new version is created with content of version 1
60
+ document.version => 3 # after revert a new version is created with content of version 1
60
61
  document.title => 'title'
61
-
62
- # get a version
63
- version2 = document.get_version 2 => #<Document ... version_number => 2>
64
- version2.version => 2
65
- version2.title => 'new title"
62
+
63
+ # get a version
64
+ version2 = document.get_version 2 => #<Document ... version_number => 2>
65
+ version2.version => 2
66
+ version2.title => 'new title"
66
67
  version2.last_version => 4
67
68
 
69
+ # you can't edit a version
70
+ version2 = document.get_version 2
71
+ version2.title = "new version"
72
+ version2.save => raise NonEditableVersionError
73
+
74
+ version2.versionable? => false
75
+
76
+ # to edit a version you need get the editable_version
77
+ editable = version2.editable_version
78
+ editable.versionable? => true
79
+ editable.title = "new"
80
+ editable.save
81
+ editable.last_version => 5
82
+
83
+ == How to contribute
84
+
85
+ If you find what you might think is a bug:
86
+
87
+ 1. Check the GitHub issue tracker to see if anyone else has had the same issue.
88
+ http://github.com/csegura/acts_as_versionable/issues/
89
+ 2. If you don't see anything, create an issue with information on how to reproduce it.
90
+
91
+ If you want to contribute an enhancement or a fix:
92
+
93
+ 1. Fork the project on github.
94
+ http://github.com/csegura/acts_as_versionable/
95
+ 2. Make your changes with tests.
96
+ 3. Commit the changes without making changes to the Rakefile, VERSION, or any other files that aren't related to your enhancement or fix
97
+ 4. Send a pull request.
98
+
99
+ Copyright ©2012 Carlos Segura, released under the MIT license
68
100
 
69
101
 
@@ -4,6 +4,8 @@ module ActsAsVersionable
4
4
 
5
5
  class NoSuchVersionError < Exception
6
6
  end
7
+ class NonEditableVersionError < Exception
8
+ end
7
9
 
8
10
  extend ActiveSupport::Concern
9
11
 
@@ -16,6 +18,7 @@ module ActsAsVersionable
16
18
  self.max_versions = (options[:max_versions] || 10)
17
19
 
18
20
  after_save :create_new_version
21
+ before_validation :versionable_validation
19
22
 
20
23
  has_many :internal_versions,
21
24
  :class_name => self.name,
@@ -35,7 +38,7 @@ module ActsAsVersionable
35
38
  module InstanceMethods
36
39
  def revert_to_version(number)
37
40
  version = get_version number
38
- editable = last_version_editable
41
+ editable = editable_version
39
42
  copy_version_values version, editable
40
43
  editable.version_number = nil
41
44
  editable.version_id = nil
@@ -75,13 +78,13 @@ module ActsAsVersionable
75
78
  return 0 if versions.count == 0
76
79
  versions.first.version_number
77
80
  end
78
-
79
- private
80
-
81
+
81
82
  # return the last version editable
82
- def last_version_editable
83
+ def editable_version
83
84
  parent_version.nil? ? self : parent_version
84
- end
85
+ end
86
+
87
+ private
85
88
 
86
89
  # callback after save
87
90
  def create_new_version
@@ -105,6 +108,13 @@ module ActsAsVersionable
105
108
  columns.each {|c| to[c.name] = from[c.name] }
106
109
  to
107
110
  end
111
+
112
+ def versionable_validation
113
+ if !new_record? && !versionable?
114
+ raise NonEditableVersionError, "Can't modify versioned record. Use version.editable_version!!"
115
+ end
116
+ end
117
+
108
118
  end
109
119
 
110
120
  end
@@ -1,3 +1,3 @@
1
1
  module ActsAsVersionable
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.1"
3
3
  end
@@ -0,0 +1,264 @@
1
+ require 'rubygems'
2
+ gem 'activerecord'
3
+ require 'active_record'
4
+ require 'test/unit'
5
+
6
+ #require "#{File.dirname(__FILE__)}/../init"
7
+ require File.join(File.dirname(__FILE__), '../lib', 'acts_as_versionable')
8
+
9
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
10
+
11
+ def setup_db
12
+ ActiveRecord::Schema.define(:version => 1) do
13
+ create_table :documents do |t|
14
+ t.string :title
15
+ t.text :body
16
+ t.integer :user_id
17
+ t.integer :version_number
18
+ t.integer :version_id
19
+ t.timestamps
20
+ end
21
+ end
22
+ end
23
+
24
+ def teardown_db
25
+ ActiveRecord::Base.connection.tables.each do |table|
26
+ ActiveRecord::Base.connection.drop_table(table)
27
+ end
28
+ end
29
+
30
+ class Document < ActiveRecord::Base
31
+ acts_as_versionable
32
+ end
33
+
34
+ class VersionableTest < Test::Unit::TestCase
35
+ def setup
36
+ setup_db
37
+
38
+ (1..3).each do |m|
39
+ document = Document.create!(:title => m.to_s, :body => m.to_s)
40
+ (1..m*2).each do |v|
41
+ document.title = v.to_s
42
+ document.body = v.to_s
43
+ document.save
44
+ end
45
+ end
46
+ end
47
+
48
+ def teardown
49
+ teardown_db
50
+ end
51
+
52
+ def test_documents
53
+ assert_equal 18, Document.all.count
54
+ #Document.last_versions.each do |d|
55
+ # p "title: #{d.title} versions: #{d.last_version}"
56
+ # p "#{d.versions.map &:title}"
57
+ #end
58
+ end
59
+
60
+ def test_if_class_methods_present
61
+ [:last_versions, :get_versionable].each do |method|
62
+ assert_equal true, Document.respond_to?(method)
63
+ end
64
+ end
65
+
66
+ def test_if_mixed_methods_present
67
+ document = Document.first
68
+ [:versions, :get_version, :revert_to_version,
69
+ :last_version, :versionable?, :editable_version,
70
+ :internal_versions, :parent_version].each do |method|
71
+ assert_equal true, document.respond_to?(method)
72
+ end
73
+ end
74
+
75
+ def test_last_versions
76
+ documents = Document.last_versions
77
+ assert_equal 3, documents.count
78
+ end
79
+
80
+ def test_initial_versions_of_the_documents
81
+ documents = Document.last_versions
82
+
83
+ documents.each do |d|
84
+ assert_equal nil, d.version_number
85
+ assert_equal nil, d.version_id
86
+ end
87
+ end
88
+
89
+ def test_get_versionable
90
+ document = Document.get_versionable(1,2).first
91
+ assert_equal 2, document.version_number
92
+ assert_equal '1', document.title
93
+ end
94
+
95
+ def test_versions_created
96
+ document = Document.create(:title => "A", :body => "AAAA")
97
+ assert_equal 1, document.last_version
98
+ assert_equal 1, document.version
99
+ document.title = "B"
100
+ document.save
101
+ assert_equal 2, document.version
102
+ end
103
+
104
+ def test_last_version
105
+ documents = Document.last_versions
106
+
107
+ assert_equal 3, documents[0].last_version
108
+ assert_equal 5, documents[1].last_version
109
+ assert_equal 7, documents[2].last_version
110
+ end
111
+
112
+ def test_version_change_to_2
113
+ document = Document.last_versions.first
114
+ assert_not_nil document
115
+
116
+ assert_equal '2', document.title
117
+ assert_equal 3, document.last_version
118
+
119
+ document.update_attributes(:title => '4', :body => '4')
120
+
121
+ assert_equal 4, document.last_version
122
+ assert_equal '4', document.title
123
+ assert_equal '4', document.body
124
+ end
125
+
126
+ def test_revert_to_version
127
+ document = Document.last_versions.first
128
+ assert_not_nil document
129
+
130
+ document.update_attributes(:title => '4', :body => '4')
131
+ assert_equal 4, document.last_version
132
+
133
+ document = document.revert_to_version(1)
134
+
135
+ assert_equal 5, document.last_version
136
+ assert_equal '1', document.title
137
+ assert_equal '1', document.body
138
+
139
+ document = document.revert_to_version(4)
140
+
141
+ assert_equal 6, document.last_version
142
+ assert_equal '4', document.title
143
+ assert_equal '4', document.body
144
+
145
+ assert_raise ActsAsVersionable::NoSuchVersionError do
146
+ document.revert_to_version(10)
147
+ end
148
+ end
149
+
150
+
151
+ # def test_new_from_version
152
+ # article = Article.first
153
+ # assert_not_nil article
154
+ #
155
+ # dummy = article.new_from_version 1
156
+ #
157
+ # article.revert_to(1)
158
+ # assert_equal dummy.title, article.title
159
+ # assert_equal dummy.body, article.body
160
+ # end
161
+
162
+ def test_versions
163
+ document = Document.last_versions.first
164
+ assert_not_nil document
165
+
166
+ assert_equal 3, document.versions.count
167
+
168
+ document = document.get_version(2)
169
+ assert_equal 3, document.versions.count
170
+ end
171
+
172
+ def test_get_version
173
+ document = Document.last_versions.first
174
+ assert_not_nil document
175
+
176
+ first = document.versions[1]
177
+ one = document.get_version(2)
178
+
179
+ assert_equal first.title, one.title
180
+ assert_equal first.body, one.body
181
+ end
182
+
183
+ def test_get_versions
184
+ document = Document.last_versions.first
185
+ assert_not_nil document
186
+
187
+ version2 = document.get_version 2
188
+ assert_equal 2, version2.version
189
+ end
190
+
191
+ def test_max_versions
192
+ document = Document.last_versions.last
193
+ (1..10).each do |v|
194
+ document.title = v.to_s
195
+ document.save
196
+ end
197
+ assert_equal 10, document.versions.count
198
+ end
199
+
200
+ def test_dependent_destroy
201
+ Document.last_versions.destroy_all
202
+ assert_equal [], Document.all
203
+ end
204
+
205
+ def test_modify_versioned
206
+ document = Document.last_versions.first
207
+ assert_not_nil document
208
+
209
+ assert_equal 3, document.last_version
210
+
211
+ version2 = document.get_version 2
212
+ version2.title = "version2 new"
213
+
214
+ assert_equal false, version2.versionable?
215
+
216
+ assert_raise ActsAsVersionable::NonEditableVersionError do
217
+ version2.save
218
+ end
219
+
220
+ assert_equal 2, version2.version
221
+ assert_equal "version2 new", version2.title
222
+
223
+ assert_equal 3, document.last_version
224
+ end
225
+
226
+ def test_readme
227
+ # cerate first version
228
+ document = Document.create(:title => 'title', :body => 'body')
229
+ assert_equal 1, document.version
230
+ assert_equal 1, document.last_version
231
+
232
+ # modify
233
+ document.title = 'new title'
234
+ document.save
235
+
236
+ # second version was created
237
+ assert_equal 2, document.version
238
+ assert_equal 2, document.last_version
239
+ assert_equal 2, document.versions.count
240
+
241
+ # revert to previous version
242
+ document.revert_to_version(1)
243
+ assert_equal "title", document.title
244
+ # a new version also is created
245
+ assert_equal 3, document.version
246
+
247
+ # get a version
248
+ document = document.get_version(2)
249
+ assert_equal 2, document.version
250
+ assert_equal "new title", document.title
251
+
252
+ # revert to a version
253
+ document = document.revert_to_version(2)
254
+ assert_equal "new title", document.title
255
+ assert_equal 4, document.version
256
+
257
+ version1 = document.get_version(1)
258
+ assert_equal 1, version1.version
259
+ assert_equal 4, version1.last_version
260
+
261
+ end
262
+
263
+ end
264
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_versionable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -26,6 +26,7 @@ files:
26
26
  - acts_as_versionable.gemspec
27
27
  - lib/acts_as_versionable.rb
28
28
  - lib/acts_as_versionable/version.rb
29
+ - test/acts_as_versionable_test.rb
29
30
  homepage: ''
30
31
  licenses: []
31
32
  post_install_message:
@@ -50,4 +51,5 @@ rubygems_version: 1.8.10
50
51
  signing_key:
51
52
  specification_version: 3
52
53
  summary: Minimalist engine for versions
53
- test_files: []
54
+ test_files:
55
+ - test/acts_as_versionable_test.rb