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.
@@ -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.class_name, :foreign_key => :revisable_branched_from_id})
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.class_name, :foreign_key => :revisable_branched_from_id
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
@@ -8,8 +8,7 @@ module WithoutScope
8
8
  end
9
9
 
10
10
  def destroy
11
- now = Time.zone.now
12
-
11
+ now = Time.current
13
12
  prev = self.revisions.first
14
13
  self.revisable_deleted_at = now
15
14
  self.revisable_is_current = false
@@ -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)).class_eval do
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.revisable_revision.save
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.class_name}Revision"
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.zone.now
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.class_name.gsub(/Revision/, '')
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
@@ -0,0 +1,11 @@
1
+ module WithoutScope
2
+ module ActsAsRevisable
3
+ module Validations
4
+ def validates_uniqueness_of(*args)
5
+ options = args.extract_options!
6
+ (options[:scope] ||= []) << :revisable_is_current
7
+ super(*(args << options))
8
+ end
9
+ end
10
+ end
11
+ end
@@ -2,8 +2,8 @@ module WithoutScope #:nodoc:
2
2
  module ActsAsRevisable
3
3
  module VERSION #:nodoc:
4
4
  MAJOR = 1
5
- MINOR = 0
6
- TINY = 3
5
+ MINOR = 1
6
+ TINY = 1
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY].join('.')
9
9
  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", :dbfile => ":memory:")
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.0.4
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-05-16 00:00:00 -07:00
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
- - lib/acts_as_revisable
41
- - lib/acts_as_revisable/acts
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: 2
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