winton-acts_as_archive 0.1.1 → 0.1.3
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/README.markdown +46 -10
- data/Rakefile +33 -25
- data/acts_as_archive.gemspec +28 -39
- data/bin/acts_as_archive +6 -0
- data/lib/acts_as_archive/base.rb +13 -4
- data/lib/acts_as_archive/base/restore.rb +3 -2
- data/lib/acts_as_archive/base/table.rb +27 -8
- data/rails/init.rb +12 -0
- data/spec/acts_as_archive/base/destroy_spec.rb +8 -19
- data/spec/acts_as_archive/base/restore_spec.rb +4 -12
- data/spec/acts_as_archive/base/table_spec.rb +47 -5
- data/spec/acts_as_archive/base_spec.rb +24 -0
- data/spec/acts_as_archive/migration_spec.rb +12 -11
- data/spec/db/config/{database.yml.example → database.yml} +0 -0
- data/spec/db/migrate_2/001_add_to_articles.rb +9 -0
- data/spec/db/models/article.rb +1 -1
- data/spec/spec_helper.rb +57 -13
- metadata +31 -16
- data/CHANGELOG.markdown +0 -4
- data/spec/db/log/.gitignore +0 -0
data/README.markdown
CHANGED
@@ -2,7 +2,8 @@ ActsAsArchive
|
|
2
2
|
=============
|
3
3
|
|
4
4
|
Don't delete your records, move them to a different table.
|
5
|
-
|
5
|
+
|
6
|
+
Like <code>acts\_as\_paranoid</code>, but doesn't mess with your SQL queries.
|
6
7
|
|
7
8
|
Install
|
8
9
|
-------
|
@@ -23,8 +24,8 @@ sudo gem install winton-acts_as_archive
|
|
23
24
|
config.gem "winton-acts_as_archive", :lib => "acts_as_archive", :source => "http://gems.github.com"
|
24
25
|
</pre>
|
25
26
|
|
26
|
-
|
27
|
-
|
27
|
+
Update models
|
28
|
+
-------------
|
28
29
|
|
29
30
|
Add <code>acts\_as\_archive</code> to your models:
|
30
31
|
|
@@ -34,19 +35,35 @@ class Article < ActiveRecord::Base
|
|
34
35
|
end
|
35
36
|
</pre>
|
36
37
|
|
38
|
+
<a name="run_acts_as_archive"></a>
|
39
|
+
|
40
|
+
Run acts\_as\_archive
|
41
|
+
---------------------
|
42
|
+
|
43
|
+
Terminal:
|
44
|
+
|
45
|
+
<pre>
|
46
|
+
cd your_rails_app
|
47
|
+
acts_as_archive
|
48
|
+
</pre>
|
49
|
+
|
50
|
+
This command creates your archive tables (<code>archived_articles</code> as per the example).
|
51
|
+
|
52
|
+
Archive tables mirror your table's structure, but with an additional <code>deleted_at</code> column.
|
53
|
+
|
54
|
+
Run this command every time you add <code>acts\_as\_archive</code> to a new model.
|
55
|
+
|
37
56
|
That's it!
|
38
57
|
----------
|
39
58
|
|
40
|
-
Next time your Rails instance boots up, the plugin replicates your table's structure into
|
41
|
-
<code>archived\_articles</code> (as per the example), with an additional <code>deleted\_at</code> column.
|
42
|
-
|
43
59
|
Use <code>destroy</code>, <code>delete</code>, and <code>delete_all</code> like you normally would.
|
44
|
-
|
60
|
+
|
61
|
+
Records move into the archive table instead of being destroyed.
|
45
62
|
|
46
63
|
What if my schema changes?
|
47
64
|
--------------------------
|
48
65
|
|
49
|
-
Any new migrations on your
|
66
|
+
Any new migrations on your table are automatically applied to the archive table.
|
50
67
|
|
51
68
|
Query the archive
|
52
69
|
-----------------
|
@@ -69,5 +86,24 @@ Article.restore_all([ 'id = ?', 1 ])
|
|
69
86
|
Auto-migrate from acts\_as\_paranoid
|
70
87
|
------------------------------------
|
71
88
|
|
72
|
-
If
|
73
|
-
records to the archive table
|
89
|
+
If you previously used <code>acts\_as\_paranoid</code>, running the <code>acts\_as\_archive</code>
|
90
|
+
command will automatically move your deleted records to the archive table
|
91
|
+
(see <a href="#run_acts_as_archive">_Run acts\_as\_archive_</a>).
|
92
|
+
|
93
|
+
Original <code>deleted_at</code> values are preserved.
|
94
|
+
|
95
|
+
Add indexes to the archive table
|
96
|
+
--------------------------------
|
97
|
+
|
98
|
+
To keep insertions fast, there are no indexes on your archive table by default.
|
99
|
+
|
100
|
+
If you are querying your archive a lot, you will want to add indexes:
|
101
|
+
|
102
|
+
<pre>
|
103
|
+
class Article < ActiveRecord::Base
|
104
|
+
acts_as_archive :indexes => [ :id, :created_at, :deleted_at ]
|
105
|
+
end
|
106
|
+
</pre>
|
107
|
+
|
108
|
+
Run the <code>acts\_as\_archive</code> command any time you add new indexes
|
109
|
+
(see <a href="#run_acts_as_archive">_Run acts\_as\_archive_</a>).
|
data/Rakefile
CHANGED
@@ -1,41 +1,49 @@
|
|
1
|
-
require 'rake'
|
2
1
|
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/gempackagetask'
|
3
4
|
require 'spec/rake/spectask'
|
4
5
|
|
5
6
|
GEM_NAME = 'acts_as_archive'
|
6
|
-
|
7
|
+
PKG_FILES = FileList['**/*'] - FileList['coverage', 'coverage/**/*', 'spec/db/log/*.log']
|
8
|
+
|
9
|
+
spec = Gem::Specification.new do |s|
|
10
|
+
s.author = "Winton Welsh"
|
11
|
+
s.email = "mail@wintoni.us"
|
12
|
+
s.executables << GEM_NAME
|
13
|
+
s.extra_rdoc_files = [ "README.markdown" ]
|
14
|
+
s.files = PKG_FILES.to_a
|
15
|
+
s.homepage = "http://github.com/winton/#{GEM_NAME}"
|
16
|
+
s.name = GEM_NAME
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.require_path = "lib"
|
19
|
+
s.summary = "Don't delete your records, move them to a different table"
|
20
|
+
s.version = "0.1.3"
|
21
|
+
end
|
7
22
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
parts = spec.split(" # = MANIFEST =\n")
|
12
|
-
fail 'bad spec' if parts.length != 3
|
13
|
-
# Determine file list from git ls-files
|
14
|
-
files = `git ls-files`.
|
15
|
-
split("\n").
|
16
|
-
sort.
|
17
|
-
reject{ |file| file =~ /^\./ }.
|
18
|
-
reject { |file| file =~ /^doc/ }.
|
19
|
-
map{ |file| " #{file}" }.
|
20
|
-
join("\n")
|
21
|
-
# Piece file back together and write
|
22
|
-
parts[1] = " s.files = %w[\n#{files}\n ]\n"
|
23
|
-
spec = parts.join(" # = MANIFEST =\n")
|
24
|
-
File.open(f.name, 'w') { |io| io.write(spec) }
|
25
|
-
puts "Updated #{f.name}"
|
23
|
+
desc "Package gem"
|
24
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
25
|
+
pkg.gem_spec = spec
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
desc "Install gem"
|
29
29
|
task :install do
|
30
|
+
Rake::Task['gem'].invoke
|
30
31
|
`sudo gem uninstall #{GEM_NAME} -x`
|
31
|
-
`gem
|
32
|
-
`
|
33
|
-
|
32
|
+
`sudo gem install pkg/#{GEM_NAME}*.gem`
|
33
|
+
`rm -Rf pkg`
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Generate gemspec"
|
37
|
+
task :gemspec do
|
38
|
+
|
39
|
+
File.open("#{File.dirname(__FILE__)}/#{GEM_NAME}.gemspec", 'w') do |f|
|
40
|
+
f.write(spec.to_ruby)
|
41
|
+
end
|
34
42
|
end
|
35
43
|
|
36
|
-
# rake spec
|
37
44
|
desc "Run specs"
|
38
45
|
Spec::Rake::SpecTask.new do |t|
|
46
|
+
t.rcov = true
|
39
47
|
t.spec_opts = ["--format", "specdoc", "--colour"]
|
40
48
|
t.spec_files = FileList["spec/**/*_spec.rb"]
|
41
49
|
end
|
data/acts_as_archive.gemspec
CHANGED
@@ -1,40 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
1
3
|
Gem::Specification.new do |s|
|
2
|
-
s.name
|
3
|
-
s.version =
|
4
|
-
|
5
|
-
|
6
|
-
s.
|
7
|
-
s.
|
8
|
-
|
9
|
-
s.
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
|
13
|
-
|
14
|
-
s.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
spec/acts_as_archive/base/destroy_spec.rb
|
29
|
-
spec/acts_as_archive/base/restore_spec.rb
|
30
|
-
spec/acts_as_archive/base/table_spec.rb
|
31
|
-
spec/acts_as_archive/migration_spec.rb
|
32
|
-
spec/db/config/database.yml.example
|
33
|
-
spec/db/log/.gitignore
|
34
|
-
spec/db/migrate/001_add_to_articles.rb
|
35
|
-
spec/db/models/article.rb
|
36
|
-
spec/spec.opts
|
37
|
-
spec/spec_helper.rb
|
38
|
-
]
|
39
|
-
# = MANIFEST =
|
40
|
-
end
|
4
|
+
s.name = %q{acts_as_archive}
|
5
|
+
s.version = "0.1.3"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Winton Welsh"]
|
9
|
+
s.date = %q{2009-04-25}
|
10
|
+
s.default_executable = %q{acts_as_archive}
|
11
|
+
s.email = %q{mail@wintoni.us}
|
12
|
+
s.executables = ["acts_as_archive"]
|
13
|
+
s.extra_rdoc_files = ["README.markdown"]
|
14
|
+
s.files = ["acts_as_archive.gemspec", "bin", "bin/acts_as_archive", "init.rb", "lib", "lib/acts_as_archive", "lib/acts_as_archive/base", "lib/acts_as_archive/base/destroy.rb", "lib/acts_as_archive/base/restore.rb", "lib/acts_as_archive/base/table.rb", "lib/acts_as_archive/base.rb", "lib/acts_as_archive/migration.rb", "lib/acts_as_archive.rb", "MIT-LICENSE", "rails", "rails/init.rb", "Rakefile", "README.markdown", "spec", "spec/acts_as_archive", "spec/acts_as_archive/base", "spec/acts_as_archive/base/destroy_spec.rb", "spec/acts_as_archive/base/restore_spec.rb", "spec/acts_as_archive/base/table_spec.rb", "spec/acts_as_archive/base_spec.rb", "spec/acts_as_archive/migration_spec.rb", "spec/db", "spec/db/config", "spec/db/config/database.yml", "spec/db/log", "spec/db/migrate", "spec/db/migrate/001_add_to_articles.rb", "spec/db/migrate_2", "spec/db/migrate_2/001_add_to_articles.rb", "spec/db/models", "spec/db/models/article.rb", "spec/spec.opts", "spec/spec_helper.rb"]
|
15
|
+
s.homepage = %q{http://github.com/winton/acts_as_archive}
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubygems_version = %q{1.3.1}
|
18
|
+
s.summary = %q{Don't delete your records, move them to a different table}
|
19
|
+
|
20
|
+
if s.respond_to? :specification_version then
|
21
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
22
|
+
s.specification_version = 2
|
23
|
+
|
24
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
25
|
+
else
|
26
|
+
end
|
27
|
+
else
|
28
|
+
end
|
29
|
+
end
|
data/bin/acts_as_archive
ADDED
data/lib/acts_as_archive/base.rb
CHANGED
@@ -9,16 +9,25 @@ module ActsAsArchive
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module ActMethods
|
12
|
-
def acts_as_archive
|
13
|
-
include Destroy
|
14
|
-
include Restore
|
15
|
-
include Table
|
12
|
+
def acts_as_archive(options={})
|
16
13
|
class_eval <<-end_eval
|
14
|
+
|
15
|
+
def self.acts_as_archive?
|
16
|
+
self.to_s == #{self.to_s.inspect}
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.archive_indexes
|
20
|
+
#{Array(options[:indexes]).collect(&:to_s).inspect}
|
21
|
+
end
|
22
|
+
|
17
23
|
class Archive < ActiveRecord::Base
|
18
24
|
self.record_timestamps = false
|
19
25
|
self.table_name = "archived_#{self.table_name}"
|
20
26
|
end
|
21
27
|
end_eval
|
28
|
+
include Destroy
|
29
|
+
include Restore
|
30
|
+
include Table
|
22
31
|
end
|
23
32
|
end
|
24
33
|
end
|
@@ -13,9 +13,10 @@ module ActsAsArchive
|
|
13
13
|
|
14
14
|
def copy_from_archive(conditions)
|
15
15
|
add_conditions!(where = '', conditions)
|
16
|
+
col_names = column_names - [ 'deleted_at' ]
|
16
17
|
connection.execute(%{
|
17
|
-
INSERT INTO #{table_name} (#{
|
18
|
-
SELECT #{
|
18
|
+
INSERT INTO #{table_name} (#{col_names.join(', ')})
|
19
|
+
SELECT #{col_names.join(', ')}
|
19
20
|
FROM archived_#{table_name}
|
20
21
|
#{where}
|
21
22
|
})
|
@@ -6,15 +6,17 @@ module ActsAsArchive
|
|
6
6
|
unless base.included_modules.include?(InstanceMethods)
|
7
7
|
base.send :extend, ClassMethods
|
8
8
|
base.send :include, InstanceMethods
|
9
|
-
# Create archive table when Rails starts
|
10
|
-
base.create_archive_table unless $TESTING
|
11
9
|
end
|
12
10
|
end
|
13
11
|
|
14
12
|
module ClassMethods
|
15
13
|
|
14
|
+
def archive_table_exists?
|
15
|
+
connection.table_exists?("archived_#{table_name}")
|
16
|
+
end
|
17
|
+
|
16
18
|
def create_archive_table
|
17
|
-
if
|
19
|
+
if table_exists? && !archive_table_exists?
|
18
20
|
connection.execute(%{
|
19
21
|
CREATE TABLE archived_#{table_name}
|
20
22
|
ENGINE=InnoDB
|
@@ -25,16 +27,33 @@ module ActsAsArchive
|
|
25
27
|
unless columns.include?('deleted_at')
|
26
28
|
connection.add_column("archived_#{table_name}", :deleted_at, :datetime)
|
27
29
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_archive_indexes
|
34
|
+
if archive_table_exists?
|
35
|
+
indexes = "SHOW INDEX FROM archived_#{table_name}"
|
36
|
+
indexes = connection.select_all(indexes).collect do |r|
|
37
|
+
r["Column_name"]
|
38
|
+
end
|
39
|
+
(archive_indexes - indexes).each do |index|
|
40
|
+
connection.add_index("archived_#{table_name}", index)
|
41
|
+
end
|
42
|
+
(indexes - archive_indexes).each do |index|
|
43
|
+
connection.remove_index("archived_#{table_name}", index)
|
44
|
+
end
|
31
45
|
end
|
32
46
|
end
|
33
47
|
|
34
48
|
def migrate_from_acts_as_paranoid
|
35
49
|
if column_names.include?('deleted_at')
|
36
|
-
|
37
|
-
|
50
|
+
if table_exists? && archive_table_exists?
|
51
|
+
condition = "deleted_at IS NOT NULL"
|
52
|
+
if self.count_by_sql("SELECT COUNT(*) FROM #{table_name} WHERE #{condition}") > 0
|
53
|
+
# Base::Destroy.copy_to_archive
|
54
|
+
copy_to_archive(condition, true)
|
55
|
+
end
|
56
|
+
end
|
38
57
|
end
|
39
58
|
end
|
40
59
|
end
|
data/rails/init.rb
CHANGED
@@ -2,3 +2,15 @@ require File.expand_path(File.dirname(__FILE__) + "/../lib/acts_as_archive")
|
|
2
2
|
|
3
3
|
ActiveRecord::Base.send(:include, ActsAsArchive::Base)
|
4
4
|
ActiveRecord::Migration.send(:include, ActsAsArchive::Migration)
|
5
|
+
|
6
|
+
module ActsAsArchive
|
7
|
+
def self.update
|
8
|
+
Object.subclasses_of(ActiveRecord::Base).each do |klass|
|
9
|
+
if klass.respond_to?(:acts_as_archive?) && klass.acts_as_archive?
|
10
|
+
klass.create_archive_table
|
11
|
+
klass.migrate_from_acts_as_paranoid
|
12
|
+
klass.create_archive_indexes
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -5,17 +5,12 @@ describe ActsAsArchive::Base::Destroy do
|
|
5
5
|
before(:all) do
|
6
6
|
establish_test_db
|
7
7
|
Article.create_archive_table
|
8
|
-
@connection = ActiveRecord::Base.connection
|
9
8
|
end
|
10
9
|
|
11
10
|
describe 'delete_all!' do
|
12
11
|
|
13
|
-
before(:
|
14
|
-
|
15
|
-
@connection.execute("TRUNCATE TABLE #{Article.table_name}")
|
16
|
-
5.times do |x|
|
17
|
-
@articles << Article.create(:title => "Title #{x}", :body => "Body #{x}")
|
18
|
-
end
|
12
|
+
before(:all) do
|
13
|
+
create_records
|
19
14
|
end
|
20
15
|
|
21
16
|
it "should really delete all records" do
|
@@ -28,16 +23,13 @@ describe ActsAsArchive::Base::Destroy do
|
|
28
23
|
|
29
24
|
describe 'delete_all' do
|
30
25
|
|
31
|
-
before(:
|
32
|
-
@articles =
|
33
|
-
5.times do |x|
|
34
|
-
@articles << Article.create(:title => "Title #{x}", :body => "Body #{x}")
|
35
|
-
end
|
26
|
+
before(:all) do
|
27
|
+
@articles = create_records
|
36
28
|
end
|
37
29
|
|
38
30
|
describe 'with conditions' do
|
39
31
|
|
40
|
-
before(:
|
32
|
+
before(:all) do
|
41
33
|
# Mini delete_all parameter test
|
42
34
|
Article.delete_all [ 'id = ?', @articles[0].id ]
|
43
35
|
Article.delete_all "id = #{@articles[1].id}"
|
@@ -59,7 +51,7 @@ describe ActsAsArchive::Base::Destroy do
|
|
59
51
|
|
60
52
|
describe 'without conditions' do
|
61
53
|
|
62
|
-
before(:
|
54
|
+
before(:all) do
|
63
55
|
Article.delete_all
|
64
56
|
end
|
65
57
|
|
@@ -82,11 +74,8 @@ describe ActsAsArchive::Base::Destroy do
|
|
82
74
|
|
83
75
|
describe d do
|
84
76
|
|
85
|
-
before(:
|
86
|
-
@articles =
|
87
|
-
5.times do |x|
|
88
|
-
@articles << Article.create(:title => "Title #{x}", :body => "Body #{x}")
|
89
|
-
end
|
77
|
+
before(:all) do
|
78
|
+
@articles = create_records
|
90
79
|
Article.find(@articles[0..1].collect(&:id)).each do |a|
|
91
80
|
a.send(d)
|
92
81
|
end
|
@@ -5,25 +5,17 @@ describe ActsAsArchive::Base::Restore do
|
|
5
5
|
before(:all) do
|
6
6
|
establish_test_db
|
7
7
|
Article.create_archive_table
|
8
|
-
@connection = ActiveRecord::Base.connection
|
9
8
|
end
|
10
9
|
|
11
10
|
describe 'restore_all' do
|
12
11
|
|
13
|
-
before(:
|
14
|
-
@articles =
|
15
|
-
@connection.execute("TRUNCATE TABLE #{Article.table_name}")
|
16
|
-
5.times do |x|
|
17
|
-
@connection.execute(%{
|
18
|
-
INSERT INTO archived_#{Article.table_name} (`id`, `title`, `body`) VALUES (#{x+1}, 'Title #{x}', 'Body #{x}')
|
19
|
-
})
|
20
|
-
@articles << Article::Archive.find(x+1)
|
21
|
-
end
|
12
|
+
before(:all) do
|
13
|
+
@articles = create_records(Article::Archive)
|
22
14
|
end
|
23
15
|
|
24
16
|
describe 'with conditions' do
|
25
17
|
|
26
|
-
before(:
|
18
|
+
before(:all) do
|
27
19
|
# Mini restore parameter test
|
28
20
|
Article.restore_all [ 'id = ?', @articles[0].id ]
|
29
21
|
Article.restore_all "id = #{@articles[1].id}"
|
@@ -45,7 +37,7 @@ describe ActsAsArchive::Base::Restore do
|
|
45
37
|
|
46
38
|
describe 'without conditions' do
|
47
39
|
|
48
|
-
before(:
|
40
|
+
before(:all) do
|
49
41
|
Article.restore_all
|
50
42
|
end
|
51
43
|
|
@@ -4,19 +4,18 @@ describe ActsAsArchive::Base::Table do
|
|
4
4
|
|
5
5
|
before(:all) do
|
6
6
|
establish_test_db
|
7
|
-
|
7
|
+
Article.create_archive_table
|
8
8
|
end
|
9
9
|
|
10
10
|
describe 'create_archive_table' do
|
11
11
|
|
12
12
|
before(:all) do
|
13
|
-
|
14
|
-
@
|
15
|
-
@archive_columns = @connection.columns("archived_articles").collect(&:name)
|
13
|
+
@article_columns = connection.columns("articles").collect(&:name)
|
14
|
+
@archive_columns = connection.columns("archived_articles").collect(&:name)
|
16
15
|
end
|
17
16
|
|
18
17
|
it "should create an archive table" do
|
19
|
-
|
18
|
+
connection.table_exists?("archived_articles").should == true
|
20
19
|
end
|
21
20
|
|
22
21
|
it "should create an archive table with the same structure as the original table" do
|
@@ -29,4 +28,47 @@ describe ActsAsArchive::Base::Table do
|
|
29
28
|
(@archive_columns - @article_columns).should == [ 'deleted_at' ]
|
30
29
|
end
|
31
30
|
end
|
31
|
+
|
32
|
+
describe 'create_archive_indexes' do
|
33
|
+
|
34
|
+
before(:all) do
|
35
|
+
Article.create_archive_indexes
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should create archive indexes" do
|
39
|
+
indexes.should == [ "id", "deleted_at" ]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should destroy archive indexes" do
|
43
|
+
Article.class_eval { acts_as_archive }
|
44
|
+
Article.create_archive_indexes
|
45
|
+
indexes.should == []
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'migrate_from_acts_as_paranoid' do
|
50
|
+
|
51
|
+
before(:all) do
|
52
|
+
connection.add_column(:articles, :deleted_at, :datetime)
|
53
|
+
Article.reset_column_information
|
54
|
+
end
|
55
|
+
|
56
|
+
before(:each) do
|
57
|
+
connection.execute("DELETE FROM #{Article::Archive.table_name}")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should move deleted records to the archive" do
|
61
|
+
create_records(Article, :deleted_at => Time.now)
|
62
|
+
Article.migrate_from_acts_as_paranoid
|
63
|
+
Article.count.should == 0
|
64
|
+
Article::Archive.count.should == 5
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should not move non-deleted records to the archive" do
|
68
|
+
create_records
|
69
|
+
Article.migrate_from_acts_as_paranoid
|
70
|
+
Article.count.should == 5
|
71
|
+
Article::Archive.count.should == 0
|
72
|
+
end
|
73
|
+
end
|
32
74
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe ActsAsArchive::Base do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
establish_test_db
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'acts_as_archive' do
|
10
|
+
|
11
|
+
it "should add self.acts_as_archive? to the model" do
|
12
|
+
Article.respond_to?(:acts_as_archive?).should == true
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should add self.archive_indexes to the model" do
|
16
|
+
Article.respond_to?(:archive_indexes).should == true
|
17
|
+
Article.archive_indexes.should == [ 'id', 'deleted_at' ]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should add Archive class to the model" do
|
21
|
+
defined?(Article::Archive).should == "constant"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -5,32 +5,33 @@ describe ActsAsArchive::Migration do
|
|
5
5
|
before(:each) do
|
6
6
|
establish_test_db
|
7
7
|
Article.create_archive_table
|
8
|
-
@connection = ActiveRecord::Base.connection
|
9
8
|
end
|
10
9
|
|
11
10
|
describe 'method_missing_with_archive' do
|
12
11
|
|
13
|
-
before(:each) do
|
14
|
-
@old_article_columns = @connection.columns("articles").collect(&:name)
|
15
|
-
@old_archive_columns = @connection.columns("archived_articles").collect(&:name)
|
16
|
-
ActiveRecord::Migrator.migrate("#{SPEC}/db/migrate")
|
17
|
-
@new_article_columns = @connection.columns("articles").collect(&:name)
|
18
|
-
@new_archive_columns = @connection.columns("archived_articles").collect(&:name)
|
19
|
-
end
|
20
|
-
|
21
12
|
it 'should migrate both tables up' do
|
13
|
+
migrate_up
|
22
14
|
(@new_article_columns - @old_article_columns).should == [ 'permalink' ]
|
23
15
|
(@new_archive_columns - @old_archive_columns).should == [ 'permalink' ]
|
24
16
|
end
|
25
17
|
|
26
18
|
it 'should migrate both tables down' do
|
19
|
+
migrate_up
|
27
20
|
@old_article_columns = @new_article_columns
|
28
21
|
@old_archive_columns = @new_archive_columns
|
29
22
|
ActiveRecord::Migrator.migrate("#{SPEC}/db/migrate", 0)
|
30
|
-
@new_article_columns =
|
31
|
-
@new_archive_columns =
|
23
|
+
@new_article_columns = columns("articles")
|
24
|
+
@new_archive_columns = columns("archived_articles")
|
32
25
|
(@old_article_columns - @new_article_columns).should == [ 'permalink' ]
|
33
26
|
(@old_archive_columns - @new_archive_columns).should == [ 'permalink' ]
|
34
27
|
end
|
28
|
+
|
29
|
+
it "should not touch the archive's deleted_at column" do
|
30
|
+
connection.add_column(:articles, :deleted_at, :datetime)
|
31
|
+
Article.reset_column_information
|
32
|
+
migrate_up("migrate_2")
|
33
|
+
(@old_article_columns - @new_article_columns).should == [ 'deleted_at' ]
|
34
|
+
(@old_archive_columns - @new_archive_columns).should == []
|
35
|
+
end
|
35
36
|
end
|
36
37
|
end
|
File without changes
|
data/spec/db/models/article.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
$TESTING=true
|
2
|
-
SPEC = File.dirname(__FILE__)
|
2
|
+
SPEC = File.expand_path(File.dirname(__FILE__))
|
3
3
|
|
4
4
|
require 'rubygems'
|
5
5
|
require 'active_record'
|
@@ -16,13 +16,44 @@ def article_match?(original, copy)
|
|
16
16
|
copy.id.should == original.id
|
17
17
|
copy.title.should == original.title
|
18
18
|
copy.body.should == original.body
|
19
|
-
copy.created_at.to_s.should == original.created_at.to_s
|
20
|
-
copy.updated_at.to_s.should == original.updated_at.to_s
|
21
19
|
if copy.respond_to?(:deleted_at)
|
22
20
|
copy.deleted_at.strftime('%j%H%M').should == Time.now.strftime('%j%H%M')
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
24
|
+
def columns(table)
|
25
|
+
connection.columns(table).collect(&:name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def connection
|
29
|
+
ActiveRecord::Base.connection
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_records(klass=Article, values={})
|
33
|
+
articles = []
|
34
|
+
table = klass.table_name
|
35
|
+
cols = columns(table)
|
36
|
+
connection.execute("DELETE FROM #{table}")
|
37
|
+
(1..5).collect do |x|
|
38
|
+
vals = cols.collect do |c|
|
39
|
+
if values.keys.include?(c.intern)
|
40
|
+
values[c.intern] ? "'#{values[c.intern]}'" : "NULL"
|
41
|
+
else
|
42
|
+
case c.intern
|
43
|
+
when :id; x
|
44
|
+
when :deleted_at; 'NULL'
|
45
|
+
else "'#{c.capitalize} #{x}'"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
connection.execute(%{
|
50
|
+
INSERT INTO #{table} (#{cols.collect { |c| "`#{c}`" }.join(', ')})
|
51
|
+
VALUES (#{vals.join(', ')})
|
52
|
+
})
|
53
|
+
klass.find(x)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
26
57
|
def debug(object)
|
27
58
|
puts "<pre>"
|
28
59
|
pp object
|
@@ -39,18 +70,31 @@ def establish_test_db
|
|
39
70
|
# Establish logger
|
40
71
|
logger_file = File.open("#{SPEC}/db/log/test.log", 'a')
|
41
72
|
logger_file.sync = true
|
42
|
-
@logger = Logger.new
|
73
|
+
@logger = Logger.new(logger_file)
|
43
74
|
ActiveRecord::Base.logger = @logger
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
ActiveRecord::Base.connection.create_table(:articles) do |t|
|
75
|
+
# The database should have only a simple articles table
|
76
|
+
connection.execute("DROP TABLE IF EXISTS articles")
|
77
|
+
connection.execute("DROP TABLE IF EXISTS archived_articles")
|
78
|
+
connection.execute("DROP TABLE IF EXISTS schema_migrations")
|
79
|
+
connection.create_table(:articles) do |t|
|
50
80
|
t.string :title
|
51
81
|
t.string :body
|
52
|
-
t.timestamps
|
53
82
|
end
|
54
|
-
# Load model
|
55
|
-
|
83
|
+
# Load the model
|
84
|
+
load "#{SPEC}/db/models/article.rb"
|
85
|
+
end
|
86
|
+
|
87
|
+
def indexes
|
88
|
+
query = "SHOW INDEX FROM archived_#{Article.table_name}"
|
89
|
+
connection.select_all(query).collect do |r|
|
90
|
+
r["Column_name"]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def migrate_up(directory='migrate')
|
95
|
+
@old_article_columns = columns("articles")
|
96
|
+
@old_archive_columns = columns("archived_articles")
|
97
|
+
ActiveRecord::Migrator.migrate("#{SPEC}/db/#{directory}")
|
98
|
+
@new_article_columns = columns("articles")
|
99
|
+
@new_archive_columns = columns("archived_articles")
|
56
100
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: winton-acts_as_archive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Winton Welsh
|
@@ -9,39 +9,54 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
13
|
-
default_executable:
|
12
|
+
date: 2009-04-25 00:00:00 -07:00
|
13
|
+
default_executable: acts_as_archive
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description:
|
16
|
+
description:
|
17
17
|
email: mail@wintoni.us
|
18
|
-
executables:
|
19
|
-
|
18
|
+
executables:
|
19
|
+
- acts_as_archive
|
20
20
|
extensions: []
|
21
21
|
|
22
|
-
extra_rdoc_files:
|
23
|
-
|
24
|
-
files:
|
25
|
-
- CHANGELOG.markdown
|
26
|
-
- MIT-LICENSE
|
22
|
+
extra_rdoc_files:
|
27
23
|
- README.markdown
|
28
|
-
|
24
|
+
files:
|
29
25
|
- acts_as_archive.gemspec
|
26
|
+
- bin
|
27
|
+
- bin/acts_as_archive
|
30
28
|
- init.rb
|
31
|
-
- lib
|
32
|
-
- lib/acts_as_archive
|
29
|
+
- lib
|
30
|
+
- lib/acts_as_archive
|
31
|
+
- lib/acts_as_archive/base
|
33
32
|
- lib/acts_as_archive/base/destroy.rb
|
34
33
|
- lib/acts_as_archive/base/restore.rb
|
35
34
|
- lib/acts_as_archive/base/table.rb
|
35
|
+
- lib/acts_as_archive/base.rb
|
36
36
|
- lib/acts_as_archive/migration.rb
|
37
|
+
- lib/acts_as_archive.rb
|
38
|
+
- MIT-LICENSE
|
39
|
+
- rails
|
37
40
|
- rails/init.rb
|
41
|
+
- Rakefile
|
42
|
+
- README.markdown
|
43
|
+
- spec
|
44
|
+
- spec/acts_as_archive
|
45
|
+
- spec/acts_as_archive/base
|
38
46
|
- spec/acts_as_archive/base/destroy_spec.rb
|
39
47
|
- spec/acts_as_archive/base/restore_spec.rb
|
40
48
|
- spec/acts_as_archive/base/table_spec.rb
|
49
|
+
- spec/acts_as_archive/base_spec.rb
|
41
50
|
- spec/acts_as_archive/migration_spec.rb
|
42
|
-
- spec/db
|
43
|
-
- spec/db/
|
51
|
+
- spec/db
|
52
|
+
- spec/db/config
|
53
|
+
- spec/db/config/database.yml
|
54
|
+
- spec/db/log
|
55
|
+
- spec/db/migrate
|
44
56
|
- spec/db/migrate/001_add_to_articles.rb
|
57
|
+
- spec/db/migrate_2
|
58
|
+
- spec/db/migrate_2/001_add_to_articles.rb
|
59
|
+
- spec/db/models
|
45
60
|
- spec/db/models/article.rb
|
46
61
|
- spec/spec.opts
|
47
62
|
- spec/spec_helper.rb
|
data/CHANGELOG.markdown
DELETED
data/spec/db/log/.gitignore
DELETED
File without changes
|