permanent_records 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,6 @@
1
+ init.rb
2
+ uninstall.rb
3
+ rails/*
4
+ test/*
5
+ README
6
+ MIT-LICENSE
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,22 @@
1
+ PermanentRecords
2
+ ================
3
+
4
+ This plugin prevents any of your records from being destroyed casually.
5
+ Any model with a deleted_at datetime column will have that column set rather than being deleted.
6
+
7
+ Usage
8
+ =======
9
+
10
+ User.find(3).destroy # sets the 'deleted_at' attribute to Time.now and returns a frozen record
11
+ User.find(3).destroy(:force) # executes the real destroy method, the record will be removed from the database
12
+ User.delete_all # bye bye everything
13
+
14
+ There are also two named scopes provided for easily searching deleted and not deleted records:
15
+
16
+ User.send :with_deleted { User.find(:all) } # only returns deleted records.
17
+ User.send :with_not_deleted { User.find(:all) } # you guessed it.
18
+
19
+ These are named so as to work smoothly with other scoping plugins like scope_out.
20
+
21
+
22
+ Copyright (c) 2008 Jack Danger Canty of adPickles Inc., released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "permanent_records"
8
+ gem.summary = %Q{Soft-delete your ActiveRecord records}
9
+ gem.description = %Q{Rather than actually deleting data this just sets Record#deleted_at. Provides helpful scopes.}
10
+ gem.email = "gems@6brand.com"
11
+ gem.homepage = "http://github.com/JackDanger/permanent_records"
12
+ gem.authors = ["Jack Danger Canty"]
13
+ end
14
+ rescue LoadError
15
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
16
+ end
17
+
18
+ require 'rake/testtask'
19
+ task :test do
20
+ exec "ruby test/permanent_records_test.rb"
21
+ end
22
+
23
+ task :default => :test
24
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.2
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'permanent_records'
2
+
3
+ ActiveRecord::Base.send :include, PermanentRecords
data/install.rb ADDED
File without changes
@@ -0,0 +1,85 @@
1
+ module PermanentRecords
2
+ def self.included(base)
3
+ if base.respond_to?(:named_scope)
4
+ base.named_scope :deleted, :conditions => {:deleted_at => true}
5
+ base.named_scope :not_deleted, :conditions => { :deleted_at => nil }
6
+ else
7
+ base.extend LegacyScopes
8
+ end
9
+ base.send :include, InstanceMethods
10
+ base.define_callbacks :before_revive, :after_revive
11
+ base.alias_method_chain :destroy, :permanent_record_force
12
+ base.alias_method_chain :destroy_without_callbacks, :permanent_record
13
+ end
14
+
15
+ module LegacyScopes
16
+ def with_deleted
17
+ with_scope :find => {:conditions => "#{quoted_table_name}.deleted_at IS NOT NULL"} do
18
+ yield
19
+ end
20
+ end
21
+
22
+ def with_not_deleted
23
+ with_scope :find => {:conditions => "#{quoted_table_name}.deleted_at IS NULL"} do
24
+ yield
25
+ end
26
+ end
27
+
28
+ # this next bit is basically stolen from the scope_out plugin
29
+ [:deleted, :not_deleted].each do |name|
30
+ define_method "find_#{name}" do |*args|
31
+ send("with_#{name}") { find(*args) }
32
+ end
33
+
34
+ define_method "count_#{name}" do |*args|
35
+ send("with_#{name}") { count(*args) }
36
+ end
37
+
38
+ define_method "calculate_#{name}" do |*args|
39
+ send("with_#{name}") { calculate(*args) }
40
+ end
41
+
42
+ define_method "find_all_#{name}" do |*args|
43
+ send("with_#{name}") { find(:all, *args) }
44
+ end
45
+ end
46
+ end
47
+
48
+ module InstanceMethods
49
+
50
+ def is_permanent?
51
+ respond_to?(:deleted_at)
52
+ end
53
+
54
+ def deleted?
55
+ deleted_at if is_permanent?
56
+ end
57
+
58
+ def revive
59
+ run_callbacks :before_revive
60
+ set_deleted_at nil
61
+ run_callbacks :after_revive
62
+ self
63
+ end
64
+
65
+ def set_deleted_at(value)
66
+ return self unless is_permanent?
67
+ record = self.class.find(id)
68
+ record.update_attribute(:deleted_at, value)
69
+ @attributes, @attributes_cache = record.attributes, record.attributes
70
+ end
71
+
72
+ def destroy_with_permanent_record_force(force = nil)
73
+ @force_permanent_record_destroy = (:force == force)
74
+ destroy_without_permanent_record_force
75
+ end
76
+
77
+ def destroy_without_callbacks_with_permanent_record
78
+ return destroy_without_callbacks_without_permanent_record if @force_permanent_record_destroy || !is_permanent?
79
+ unless deleted? || new_record?
80
+ set_deleted_at Time.now
81
+ end
82
+ self
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,62 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{permanent_records}
8
+ s.version = "1.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jack Danger Canty"]
12
+ s.date = %q{2009-09-26}
13
+ s.description = %q{Rather than actually deleting data this just sets Record#deleted_at. Provides helpful scopes.}
14
+ s.email = %q{gems@6brand.com}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ "MIT-LICENSE",
21
+ "README",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "init.rb",
25
+ "install.rb",
26
+ "lib/permanent_records.rb",
27
+ "permanent_records.gemspec",
28
+ "test/database.yml",
29
+ "test/hole.rb",
30
+ "test/kitty.rb",
31
+ "test/mole.rb",
32
+ "test/muskrat.rb",
33
+ "test/permanent_records_test.rb",
34
+ "test/schema.rb",
35
+ "test/test_helper.rb",
36
+ "uninstall.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/JackDanger/permanent_records}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.5}
42
+ s.summary = %q{Soft-delete your ActiveRecord records}
43
+ s.test_files = [
44
+ "test/hole.rb",
45
+ "test/kitty.rb",
46
+ "test/mole.rb",
47
+ "test/muskrat.rb",
48
+ "test/permanent_records_test.rb",
49
+ "test/schema.rb",
50
+ "test/test_helper.rb"
51
+ ]
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
58
+ else
59
+ end
60
+ else
61
+ end
62
+ end
data/test/database.yml ADDED
@@ -0,0 +1,18 @@
1
+ sqlite:
2
+ :adapter: sqlite
3
+ :database: plugin.sqlite.db
4
+ sqlite3:
5
+ :adapter: sqlite3
6
+ :database: ":memory:"
7
+ postgresql:
8
+ :adapter: postgresql
9
+ :username: postgres
10
+ :password: postgres
11
+ :database: plugin_test
12
+ :min_messages: ERROR
13
+ mysql:
14
+ :adapter: mysql
15
+ :host: localhost
16
+ :username: rails
17
+ :password:
18
+ :database: plugin_test
data/test/hole.rb ADDED
@@ -0,0 +1,6 @@
1
+ class Hole < ActiveRecord::Base
2
+ # muskrats are permanent
3
+ has_many :muskrats, :dependent => :destroy
4
+ # moles are not permanent
5
+ has_many :moles, :dependent => :destroy
6
+ end
data/test/kitty.rb ADDED
@@ -0,0 +1,2 @@
1
+ class Kitty < ActiveRecord::Base
2
+ end
data/test/mole.rb ADDED
@@ -0,0 +1,3 @@
1
+ class Mole < ActiveRecord::Base
2
+ belongs_to :hole
3
+ end
data/test/muskrat.rb ADDED
@@ -0,0 +1,3 @@
1
+ class Muskrat < ActiveRecord::Base
2
+ belongs_to :hole
3
+ end
@@ -0,0 +1,109 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/test_helper")
2
+
3
+ %w(hole mole muskrat kitty).each do |a|
4
+ require File.expand_path(File.dirname(__FILE__) + "/" + a)
5
+ end
6
+
7
+ class PermanentRecordsTest < ActiveSupport::TestCase
8
+
9
+ def setup
10
+ super
11
+ Muskrat.delete_all
12
+ @active = Muskrat.create!(:name => 'Wakko')
13
+ @deleted = Muskrat.create!(:name => 'Yakko', :deleted_at => 4.days.ago)
14
+ @the_girl = Muskrat.create!(:name => 'Dot')
15
+ Kitty.delete_all
16
+ @kitty = Kitty.create!(:name => 'Meow Meow')
17
+ @hole = Hole.create(:number => 14)
18
+ @mole = @hole.muskrats.create(:name => "Steady Rat")
19
+ @mole = @hole.moles.create(:name => "Grabowski")
20
+ end
21
+
22
+ def teardown
23
+ setup
24
+ end
25
+
26
+ def test_destroy_should_return_the_record
27
+ muskrat = @active
28
+ assert_equal muskrat, muskrat.destroy
29
+ end
30
+
31
+ def test_revive_should_return_the_record
32
+ muskrat = @deleted
33
+ assert_equal muskrat, muskrat.destroy
34
+ end
35
+
36
+ def test_destroy_should_set_deleted_at_attribute
37
+ assert @active.destroy.deleted_at
38
+ end
39
+
40
+ def test_destroy_should_save_deleted_at_attribute
41
+ assert Muskrat.find(@active.destroy.id).deleted_at
42
+ end
43
+
44
+ def test_destroy_should_not_really_remove_the_record
45
+ assert Muskrat.find(@active.destroy.id)
46
+ end
47
+
48
+ def test_destroy_should_recognize_a_force_parameter
49
+ assert_raises(ActiveRecord::RecordNotFound) { @active.destroy(:force).reload }
50
+ end
51
+
52
+ def test_destroy_should_ignore_other_parameters
53
+ assert Muskrat.find(@active.destroy(:hula_dancer).id)
54
+ end
55
+
56
+ def test_revive_should_unfreeze_record
57
+ assert !@deleted.revive.frozen?
58
+ end
59
+
60
+ def test_revive_should_unset_deleted_at
61
+ assert !@deleted.revive.deleted_at
62
+ end
63
+
64
+ def test_revive_should_make_deleted_return_false
65
+ assert !@deleted.revive.deleted?
66
+ end
67
+
68
+ def test_deleted_returns_true_for_deleted_records
69
+ assert @deleted.deleted?
70
+ end
71
+
72
+ def test_destroy_returns_record_with_modified_attributes
73
+ assert @active.destroy.deleted?
74
+ end
75
+
76
+ def test_revive_and_destroy_should_be_chainable
77
+ assert @active.destroy.revive.destroy.destroy.revive.revive.destroy.deleted?
78
+ assert !@deleted.destroy.revive.revive.destroy.destroy.revive.deleted?
79
+ end
80
+
81
+ def test_with_deleted_limits_scope_to_deleted_records
82
+ assert Muskrat.deleted.all?(&:deleted?)
83
+ end
84
+
85
+ def test_with_not_deleted_limits_scope_to_not_deleted_records
86
+ assert !Muskrat.not_deleted.any?(&:deleted?)
87
+ end
88
+
89
+ def test_models_without_a_deleted_at_column_should_destroy_as_normal
90
+ assert_raises(ActiveRecord::RecordNotFound) {@kitty.destroy.reload}
91
+ end
92
+
93
+ def test_dependent_non_permanent_records_should_be_destroyed
94
+ assert @hole.is_permanent?
95
+ assert !@hole.moles.first.is_permanent?
96
+ assert_difference "Mole.count", -1 do
97
+ @hole.destroy
98
+ end
99
+ end
100
+
101
+ def test_dependent_permanent_records_should_be_marked_as_deleted
102
+ assert @hole.is_permanent?
103
+ assert @hole.muskrats.first.is_permanent?
104
+ assert_no_difference "Muskrat.count" do
105
+ @hole.destroy
106
+ end
107
+ assert @hole.muskrats.first.deleted?
108
+ end
109
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,23 @@
1
+ ActiveRecord::Schema.define(:version => 1) do
2
+
3
+ create_table :muskrats do |t|
4
+ t.column :name, :string
5
+ t.column :deleted_at, :datetime
6
+ t.references :hole
7
+ end
8
+
9
+ create_table :kitties do |t|
10
+ t.column :name, :string
11
+ end
12
+
13
+ create_table :holes do |t|
14
+ t.integer :number
15
+ t.datetime :deleted_at
16
+ end
17
+
18
+ create_table :moles do |t|
19
+ t.string :name
20
+ t.references :hole
21
+ end
22
+
23
+ end
@@ -0,0 +1,42 @@
1
+ # Include this file in your test by copying the following line to your test:
2
+ # require File.expand_path(File.dirname(__FILE__) + "/test_helper")
3
+
4
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
5
+ RAILS_ROOT = File.dirname(__FILE__)
6
+
7
+ require 'rubygems'
8
+ gem 'test-unit'
9
+ require 'test/unit'
10
+ require 'active_record'
11
+ require 'active_record/fixtures'
12
+ require "#{File.dirname(__FILE__)}/../init"
13
+
14
+ require File.expand_path(File.dirname(__FILE__) + "/muskrat")
15
+
16
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
17
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
18
+ ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite3'])
19
+
20
+ load(File.dirname(__FILE__) + "/schema.rb") if File.exist?(File.dirname(__FILE__) + "/schema.rb")
21
+
22
+ class ActiveSupport::TestCase #:nodoc:
23
+ include ActiveRecord::TestFixtures
24
+ # def create_fixtures(*table_names)
25
+ # if block_given?
26
+ # Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) { yield }
27
+ # else
28
+ # Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names)
29
+ # end
30
+ # end
31
+
32
+ self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
33
+ $LOAD_PATH.unshift(fixture_path)
34
+
35
+ # Turn off transactional fixtures if you're working with MyISAM tables in MySQL
36
+ self.use_transactional_fixtures = true
37
+
38
+ # Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
39
+ self.use_instantiated_fixtures = false
40
+
41
+ # Add more helper methods to be used by all tests here...
42
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: permanent_records
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Jack Danger Canty
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-26 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Rather than actually deleting data this just sets Record#deleted_at. Provides helpful scopes.
17
+ email: gems@6brand.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - .document
26
+ - MIT-LICENSE
27
+ - README
28
+ - Rakefile
29
+ - VERSION
30
+ - init.rb
31
+ - install.rb
32
+ - lib/permanent_records.rb
33
+ - permanent_records.gemspec
34
+ - test/database.yml
35
+ - test/hole.rb
36
+ - test/kitty.rb
37
+ - test/mole.rb
38
+ - test/muskrat.rb
39
+ - test/permanent_records_test.rb
40
+ - test/schema.rb
41
+ - test/test_helper.rb
42
+ - uninstall.rb
43
+ has_rdoc: true
44
+ homepage: http://github.com/JackDanger/permanent_records
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --charset=UTF-8
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.5
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Soft-delete your ActiveRecord records
71
+ test_files:
72
+ - test/hole.rb
73
+ - test/kitty.rb
74
+ - test/mole.rb
75
+ - test/muskrat.rb
76
+ - test/permanent_records_test.rb
77
+ - test/schema.rb
78
+ - test/test_helper.rb