winton-acts_as_archive 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|