kb-acts_as_revisable 1.0.4 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/acts_as_revisable/acts/common.rb +2 -2
- data/lib/acts_as_revisable/acts/deletable.rb +1 -2
- data/lib/acts_as_revisable/acts/revisable.rb +12 -6
- data/lib/acts_as_revisable/acts/revision.rb +4 -14
- data/lib/acts_as_revisable/base.rb +2 -0
- data/lib/acts_as_revisable/validations.rb +11 -0
- data/lib/acts_as_revisable/version.rb +2 -2
- data/spec/find_spec.rb +4 -0
- data/spec/general_spec.rb +36 -0
- data/spec/spec_helper.rb +30 -2
- data/spec/sti_spec.rb +42 -0
- data/spec/validations_spec.rb +25 -0
- metadata +8 -8
@@ -20,9 +20,9 @@ module WithoutScope
|
|
20
20
|
|
21
21
|
base.instance_eval do
|
22
22
|
define_callbacks :before_branch, :after_branch
|
23
|
-
has_many :branches, (revisable_options.revision_association_options || {}).merge({:class_name => base.
|
23
|
+
has_many :branches, (revisable_options.revision_association_options || {}).merge({:class_name => base.name, :foreign_key => :revisable_branched_from_id})
|
24
24
|
|
25
|
-
belongs_to :branch_source, :class_name => base.
|
25
|
+
belongs_to :branch_source, :class_name => base.name, :foreign_key => :revisable_branched_from_id
|
26
26
|
after_save :execute_blocks_after_save
|
27
27
|
end
|
28
28
|
end
|
@@ -40,11 +40,11 @@ module WithoutScope
|
|
40
40
|
has_many assoc, (revisable_options.revision_association_options || {}).merge({:class_name => revision_class_name, :foreign_key => :revisable_original_id, :order => "#{quoted_table_name}.#{connection.quote_column_name(:revisable_number)} DESC", :dependent => :destroy})
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
if !Object.const_defined?(base.revision_class_name) && base.revisable_options.generate_revision_class?
|
45
|
-
Object.const_set(base.revision_class_name, Class.new(ActiveRecord::Base)).
|
45
|
+
Object.const_set(base.revision_class_name, Class.new(ActiveRecord::Base)).instance_eval do
|
46
46
|
acts_as_revision
|
47
|
-
end
|
47
|
+
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -77,7 +77,7 @@ module WithoutScope
|
|
77
77
|
by
|
78
78
|
when :first
|
79
79
|
revisions.last
|
80
|
-
when :previous
|
80
|
+
when :previous, :last
|
81
81
|
revisions.first
|
82
82
|
when Time
|
83
83
|
revisions.find(:first, :conditions => ["? >= ? and ? <= ?", :revisable_revised_at, by, :revisable_current_at, by])
|
@@ -329,7 +329,13 @@ module WithoutScope
|
|
329
329
|
self.revisable_revision = nil
|
330
330
|
return true
|
331
331
|
elsif self.revisable_revision
|
332
|
-
self.
|
332
|
+
if self.class.revision_class.respond_to?(:without_stamps)
|
333
|
+
self.class.revision_class.without_stamps do
|
334
|
+
self.revisable_revision.save
|
335
|
+
end
|
336
|
+
else
|
337
|
+
self.revisable_revision.save
|
338
|
+
end
|
333
339
|
revisions.reload
|
334
340
|
run_callbacks(:after_revise)
|
335
341
|
end
|
@@ -446,7 +452,7 @@ module WithoutScope
|
|
446
452
|
# Returns the +revision_class_name+ as configured in
|
447
453
|
# +acts_as_revisable+.
|
448
454
|
def revision_class_name #:nodoc:
|
449
|
-
self.revisable_options.revision_class_name || "#{self.
|
455
|
+
self.revisable_options.revision_class_name || "#{self.name}Revision"
|
450
456
|
end
|
451
457
|
|
452
458
|
# Returns the actual +Revision+ class based on the
|
@@ -29,15 +29,7 @@ module WithoutScope
|
|
29
29
|
[:current_revision, revisable_association_name.to_sym].each do |a|
|
30
30
|
belongs_to a, :class_name => revisable_class_name, :foreign_key => :revisable_original_id
|
31
31
|
end
|
32
|
-
|
33
|
-
# add an author association if there is such a class
|
34
|
-
begin
|
35
|
-
if User.is_a?(Class) && User.respond_to?('current_user')
|
36
|
-
belongs_to :author, :class_name => 'User', :foreign_key => 'revisable_author_id'
|
37
|
-
end
|
38
|
-
rescue NameError
|
39
|
-
end
|
40
|
-
|
32
|
+
|
41
33
|
[[:ancestors, "<"], [:descendants, ">"]].each do |a|
|
42
34
|
# Jumping through hoops here to try and make sure the
|
43
35
|
# :finder_sql is cross-database compatible. :finder_sql
|
@@ -73,15 +65,13 @@ module WithoutScope
|
|
73
65
|
|
74
66
|
# Sets some initial values for a new revision.
|
75
67
|
def revision_setup #:nodoc:
|
76
|
-
now = Time.
|
68
|
+
now = Time.current
|
77
69
|
prev = current_revision.revisions.first
|
78
70
|
prev.update_attribute(:revisable_revised_at, now) if prev
|
79
71
|
self[:revisable_current_at] = now + 1.second
|
80
72
|
self[:revisable_is_current] = false
|
81
|
-
self[:revisable_author_id] = (User.current_user.id rescue nil)
|
82
73
|
self[:revisable_branched_from_id] = current_revision[:revisable_branched_from_id]
|
83
|
-
self[:revisable_type] = current_revision[:type]
|
84
|
-
self[:revisable_number] = (self.class.maximum(:revisable_number, :conditions => {:revisable_original_id => self[:revisable_original_id]}) || 0) + 1
|
74
|
+
self[:revisable_type] = current_revision[:type] || current_revision.class.name
|
85
75
|
end
|
86
76
|
|
87
77
|
def grab_my_branches
|
@@ -112,7 +102,7 @@ module WithoutScope
|
|
112
102
|
# Returns the +revisable_class_name+ as configured in
|
113
103
|
# +acts_as_revisable+.
|
114
104
|
def revisable_class_name #:nodoc:
|
115
|
-
self.revisable_options.revisable_class_name || self.
|
105
|
+
self.revisable_options.revisable_class_name || self.name.gsub(/Revision/, '')
|
116
106
|
end
|
117
107
|
|
118
108
|
# Returns the actual +Revisable+ class based on the
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'acts_as_revisable/options'
|
2
2
|
require 'acts_as_revisable/quoted_columns'
|
3
|
+
require 'acts_as_revisable/validations'
|
3
4
|
require 'acts_as_revisable/acts/common'
|
4
5
|
require 'acts_as_revisable/acts/revision'
|
5
6
|
require 'acts_as_revisable/acts/revisable'
|
@@ -45,6 +46,7 @@ module WithoutScope
|
|
45
46
|
self.revisable_options = Options.new(options, &block)
|
46
47
|
|
47
48
|
self.send(:include, Common)
|
49
|
+
self.send(:extend, Validations) unless self.revisable_options.no_validation_scoping?
|
48
50
|
self.send(:include, WithoutScope::QuotedColumnConditions)
|
49
51
|
end
|
50
52
|
end
|
data/spec/find_spec.rb
CHANGED
@@ -26,5 +26,9 @@ describe WithoutScope::ActsAsRevisable do
|
|
26
26
|
it "should find revisions with conditions" do
|
27
27
|
Project.find(:all, :conditions => {:name => "Rich"}, :with_revisions => true).should == [@project1.find_revision(:previous)]
|
28
28
|
end
|
29
|
+
|
30
|
+
it "should find last revision" do
|
31
|
+
@project1.find_revision(:last).should == @project1.find_revision(:previous)
|
32
|
+
end
|
29
33
|
end
|
30
34
|
end
|
data/spec/general_spec.rb
CHANGED
@@ -7,6 +7,22 @@ describe WithoutScope::ActsAsRevisable do
|
|
7
7
|
|
8
8
|
before(:each) do
|
9
9
|
@project = Project.create(:name => "Rich", :notes => "this plugin's author")
|
10
|
+
@post = Post.create(:name => 'a name')
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "with auto-detected revision class" do
|
14
|
+
it "should find the revision class" do
|
15
|
+
Post.revision_class.should == PostRevision
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should find the revisable class" do
|
19
|
+
PostRevision.revisable_class.should == Post
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should use the revision class" do
|
23
|
+
@post.update_attribute(:name, 'another name')
|
24
|
+
@post.revisions(true).first.class.should == PostRevision
|
25
|
+
end
|
10
26
|
end
|
11
27
|
|
12
28
|
describe "with auto-generated revision class" do
|
@@ -54,6 +70,10 @@ describe WithoutScope::ActsAsRevisable do
|
|
54
70
|
@project.sessions.size.should == 1
|
55
71
|
end
|
56
72
|
|
73
|
+
it "should have a single revision with a revision_number of zero" do
|
74
|
+
@project.revisions.collect{ |rev| rev.revision_number }.should == [0]
|
75
|
+
end
|
76
|
+
|
57
77
|
it "should return an instance of the revision class" do
|
58
78
|
@project.revisions.first.should be_an_instance_of(Session)
|
59
79
|
end
|
@@ -63,6 +83,22 @@ describe WithoutScope::ActsAsRevisable do
|
|
63
83
|
end
|
64
84
|
end
|
65
85
|
|
86
|
+
describe "with multiple revisions" do
|
87
|
+
before(:each) do
|
88
|
+
@project.update_attribute(:name, "Stephen")
|
89
|
+
@project.update_attribute(:name, "Michael")
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should have a revision_number of two" do
|
93
|
+
@project.revision_number.should == 2
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should have revisions with revision_number values of zero and one" do
|
97
|
+
@project.revisions.collect{ |rev| rev.revision_number }.should == [1,0]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
66
102
|
describe "with excluded columns modified" do
|
67
103
|
before(:each) do
|
68
104
|
@project.update_attribute(:unimportant, "a new value")
|
data/spec/spec_helper.rb
CHANGED
@@ -15,7 +15,7 @@ end
|
|
15
15
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
16
16
|
require 'acts_as_revisable'
|
17
17
|
|
18
|
-
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :
|
18
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
19
19
|
|
20
20
|
def setup_db
|
21
21
|
ActiveRecord::Schema.define(:version => 1) do
|
@@ -45,6 +45,14 @@ def setup_db
|
|
45
45
|
t.datetime :revisable_current_at, :revisable_revised_at, :revisable_deleted_at
|
46
46
|
t.timestamps
|
47
47
|
end
|
48
|
+
|
49
|
+
create_table :posts do |t|
|
50
|
+
t.string :name, :revisable_name, :revisable_type, :type
|
51
|
+
t.boolean :revisable_is_current
|
52
|
+
t.integer :revisable_original_id, :revisable_branched_from_id, :revisable_number
|
53
|
+
t.datetime :revisable_current_at, :revisable_revised_at, :revisable_deleted_at
|
54
|
+
t.timestamps
|
55
|
+
end
|
48
56
|
end
|
49
57
|
end
|
50
58
|
|
@@ -89,5 +97,25 @@ class Session < ActiveRecord::Base
|
|
89
97
|
end
|
90
98
|
|
91
99
|
class Foo < ActiveRecord::Base
|
92
|
-
acts_as_revisable :generate_revision_class => true
|
100
|
+
acts_as_revisable :generate_revision_class => true, :no_validation_scoping => true
|
101
|
+
|
102
|
+
validates_uniqueness_of :name
|
103
|
+
end
|
104
|
+
|
105
|
+
class Post < ActiveRecord::Base
|
106
|
+
acts_as_revisable
|
107
|
+
|
108
|
+
validates_uniqueness_of :name
|
109
|
+
end
|
110
|
+
|
111
|
+
class PostRevision < ActiveRecord::Base
|
112
|
+
acts_as_revision
|
113
|
+
end
|
114
|
+
|
115
|
+
class Article < Post
|
116
|
+
acts_as_revisable
|
117
|
+
end
|
118
|
+
|
119
|
+
class ArticleRevision < PostRevision
|
120
|
+
acts_as_revision
|
93
121
|
end
|
data/spec/sti_spec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe WithoutScope::ActsAsRevisable, "with single table inheritance" do
|
4
|
+
after(:each) do
|
5
|
+
cleanup_db
|
6
|
+
end
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@article = Article.create(:name => 'an article')
|
10
|
+
@post = Post.create(:name => 'a post')
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "after a revision" do
|
14
|
+
it "an article has revisions of the right type" do
|
15
|
+
@article.revise!
|
16
|
+
@article.revisions(true).first.class.should == ArticleRevision
|
17
|
+
end
|
18
|
+
|
19
|
+
it "a post has revisions of the right type" do
|
20
|
+
@post.revise!
|
21
|
+
@post.revisions(true).first.class.should == PostRevision
|
22
|
+
end
|
23
|
+
|
24
|
+
it "revisable_type column is nil for the root type" do
|
25
|
+
@post.revise!
|
26
|
+
@post.revisions(true).first.revisable_type.should == 'Post'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "revisable_type column is set properly" do
|
30
|
+
@article.revise!
|
31
|
+
@article.revisions(true).first.revisable_type.should == 'Article'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can find an article by name" do
|
35
|
+
Article.find_by_name('an article').should_not be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can find a post by name" do
|
39
|
+
Post.find_by_name('a post').should_not be_nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe WithoutScope::ActsAsRevisable, "with validations" do
|
4
|
+
after(:each) do
|
5
|
+
cleanup_db
|
6
|
+
end
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@post = Post.create(:name => 'a post')
|
10
|
+
@foo = Foo.create(:name => 'a foo')
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "unique fields" do
|
15
|
+
it "should allow revisions" do
|
16
|
+
lambda {@post.revise!; @post.revise!}.should_not raise_error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "unique fields with validation scoping off" do
|
21
|
+
it "should not allow revisions" do
|
22
|
+
lambda {@foo.revise!; @foo.revise!}.should raise_error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kb-acts_as_revisable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rich Cavanaugh
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-10-06 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -37,8 +37,8 @@ files:
|
|
37
37
|
- spec/revert_spec.rb
|
38
38
|
- spec/spec.opts
|
39
39
|
- spec/spec_helper.rb
|
40
|
-
-
|
41
|
-
-
|
40
|
+
- spec/sti_spec.rb
|
41
|
+
- spec/validations_spec.rb
|
42
42
|
- lib/acts_as_revisable/acts/common.rb
|
43
43
|
- lib/acts_as_revisable/acts/deletable.rb
|
44
44
|
- lib/acts_as_revisable/acts/revisable.rb
|
@@ -47,16 +47,16 @@ files:
|
|
47
47
|
- lib/acts_as_revisable/gem_spec_options.rb
|
48
48
|
- lib/acts_as_revisable/options.rb
|
49
49
|
- lib/acts_as_revisable/quoted_columns.rb
|
50
|
+
- lib/acts_as_revisable/validations.rb
|
50
51
|
- lib/acts_as_revisable/version.rb
|
51
52
|
- lib/acts_as_revisable.rb
|
52
|
-
- generators/revisable_migration
|
53
53
|
- generators/revisable_migration/revisable_migration_generator.rb
|
54
|
-
- generators/revisable_migration/templates
|
55
54
|
- generators/revisable_migration/templates/migration.rb
|
56
55
|
- rails/init.rb
|
57
56
|
has_rdoc: true
|
58
57
|
homepage: http://github.com/rich/acts_as_revisable
|
59
|
-
licenses:
|
58
|
+
licenses: []
|
59
|
+
|
60
60
|
post_install_message:
|
61
61
|
rdoc_options:
|
62
62
|
- --main
|
@@ -80,7 +80,7 @@ requirements: []
|
|
80
80
|
rubyforge_project:
|
81
81
|
rubygems_version: 1.3.5
|
82
82
|
signing_key:
|
83
|
-
specification_version:
|
83
|
+
specification_version: 3
|
84
84
|
summary: acts_as_revisable enables revision tracking, querying, reverting and branching of ActiveRecord models. Inspired by acts_as_versioned.
|
85
85
|
test_files: []
|
86
86
|
|