prevent_destroy_if_any 0.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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +46 -0
- data/Rakefile +6 -0
- data/lib/prevent_destroy_if_any/version.rb +3 -0
- data/lib/prevent_destroy_if_any.rb +24 -0
- data/prevent_destroy_if_any.gemspec +27 -0
- data/spec/prevent_destroy_if_any_spec.rb +50 -0
- data/spec/spec_helper.rb +60 -0
- metadata +130 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
prevent_destroy_if_any
|
2
|
+
===
|
3
|
+
|
4
|
+
This plugin adds ActiveRecord models a way to prevent destroy if specified `has_many`, `has_one` and/or `belongs_to` associations are present. This is achieved by adding a `before_destroy` callback that aborts the destroy and adds a base error on the instance when detecting associations.
|
5
|
+
|
6
|
+
It's inspired from [this stackoverflow answer](http://stackoverflow.com/questions/4054112/how-do-i-prevent-deletion-of-parent-if-it-has-child-records/4054170#4054170) and was created to factorize this solution when you need it for various models in an application.
|
7
|
+
|
8
|
+
It has been tested only with ActiveRecord 3.
|
9
|
+
|
10
|
+
Installation
|
11
|
+
---
|
12
|
+
|
13
|
+
`gem install prevent_destroy_if_any`
|
14
|
+
|
15
|
+
If you use Bundler, edit your `Gemfile` to add `gem 'prevent_destroy_if_any'`.
|
16
|
+
|
17
|
+
|
18
|
+
Example usage
|
19
|
+
---
|
20
|
+
|
21
|
+
A Person model for which you want to prevent destroy when it has an associated user, projects or public profile. Destroy will work if it has associated logs.
|
22
|
+
|
23
|
+
class Person < ActiveRecord::Base
|
24
|
+
belongs_to :user
|
25
|
+
has_many :projects
|
26
|
+
has_one :public_profile
|
27
|
+
has_many :logs
|
28
|
+
|
29
|
+
prevent_destroy_if_any :user, :projects, :public_profile
|
30
|
+
end
|
31
|
+
|
32
|
+
Then in Rails you can write your PeopleController destroy action like this:
|
33
|
+
|
34
|
+
def destroy
|
35
|
+
person = Person.find params[:id]
|
36
|
+
if person.destroy
|
37
|
+
redirect_to people_url, :notice => "Person successfully deleted"
|
38
|
+
else
|
39
|
+
redirect_to person, :alert => person.errors.full_messages.join
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
License
|
44
|
+
---
|
45
|
+
|
46
|
+
Copyright © 2011 Florent Guilleux, released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "prevent_destroy_if_any/version"
|
2
|
+
|
3
|
+
class ActiveRecord::Base
|
4
|
+
def self.prevent_destroy_if_any(*association_names)
|
5
|
+
before_destroy do |model|
|
6
|
+
associations_present = []
|
7
|
+
|
8
|
+
association_names.each do |association_name|
|
9
|
+
association = model.send association_name
|
10
|
+
if association.class == Array
|
11
|
+
associations_present << association_name if association.any?
|
12
|
+
else
|
13
|
+
associations_present << association_name if association
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
if associations_present.any?
|
18
|
+
errors.add :base, "Cannot delete #{model.class.model_name.human.downcase} while #{associations_present.join ', '} exist"
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "prevent_destroy_if_any/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "prevent_destroy_if_any"
|
7
|
+
s.version = PreventDestroyIfAny::VERSION
|
8
|
+
s.authors = ["Florent Guilleux"]
|
9
|
+
s.email = ["florent2@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/Florent2/prevent_destroy_if_any"
|
11
|
+
s.summary = %q{ActiveRecord plugin to prevent destroy when associations are present}
|
12
|
+
s.description = %q{ActiveRecord plugin to prevent destroy when associations are present}
|
13
|
+
|
14
|
+
s.rubyforge_project = "prevent_destroy_if_any"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency "activerecord", '>= 3.0.0'
|
22
|
+
s.add_development_dependency "bundler", '>= 1.0.0'
|
23
|
+
s.add_development_dependency "rspec", '>= 0'
|
24
|
+
s.add_development_dependency "database_cleaner", '>= 0'
|
25
|
+
s.add_development_dependency "sqlite3-ruby", '>= 0'
|
26
|
+
s.add_development_dependency "rake", '>= 0'
|
27
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "prevent_destroy_if_any" do
|
4
|
+
|
5
|
+
let(:person) { Person.create! }
|
6
|
+
|
7
|
+
context "when there are associated records" do
|
8
|
+
|
9
|
+
it "destroy preventing works for has_many association" do
|
10
|
+
person.projects.create
|
11
|
+
person.destroy
|
12
|
+
person.destroyed?.should be_false
|
13
|
+
end
|
14
|
+
|
15
|
+
it "destroy preventing works for has_one association" do
|
16
|
+
person.create_public_profile
|
17
|
+
person.destroy
|
18
|
+
person.destroyed?.should be_false
|
19
|
+
end
|
20
|
+
|
21
|
+
it "destroy preventing works for belongs_ association" do
|
22
|
+
person.create_user
|
23
|
+
person.destroy
|
24
|
+
person.destroyed?.should be_false
|
25
|
+
end
|
26
|
+
|
27
|
+
it "adds an error message" do
|
28
|
+
person.projects.create
|
29
|
+
person.create_public_profile
|
30
|
+
person.destroy
|
31
|
+
person.errors[:base].first.should == "Cannot delete person while projects, public_profile exist"
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
it "does not prevent the destroy if the association is not listed as preventing the destroy" do
|
36
|
+
person.logs.create
|
37
|
+
person.destroy
|
38
|
+
person.destroyed?.should be_true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when there is no associated records" do
|
43
|
+
|
44
|
+
it "does not prevent the destroy" do
|
45
|
+
person.destroy
|
46
|
+
person.destroyed?.should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
$:.unshift File.expand_path('..', __FILE__)
|
2
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "bundler"
|
6
|
+
require "rspec"
|
7
|
+
require "active_record"
|
8
|
+
require "database_cleaner"
|
9
|
+
|
10
|
+
require "prevent_destroy_if_any"
|
11
|
+
|
12
|
+
ActiveRecord::Base.configurations = { 'test' => { :adapter => 'sqlite3', :database => ':memory:' } }
|
13
|
+
ActiveRecord::Base.establish_connection('test')
|
14
|
+
|
15
|
+
class Person < ActiveRecord::Base
|
16
|
+
belongs_to :user
|
17
|
+
has_many :projects
|
18
|
+
has_one :public_profile
|
19
|
+
has_many :logs
|
20
|
+
|
21
|
+
prevent_destroy_if_any :user, :projects, :public_profile
|
22
|
+
end
|
23
|
+
|
24
|
+
class User < ActiveRecord::Base
|
25
|
+
has_one :person
|
26
|
+
end
|
27
|
+
|
28
|
+
class Project < ActiveRecord::Base
|
29
|
+
belongs_to :person
|
30
|
+
end
|
31
|
+
|
32
|
+
class PublicProfile < ActiveRecord::Base
|
33
|
+
belongs_to :person
|
34
|
+
end
|
35
|
+
|
36
|
+
class Log < ActiveRecord::Base
|
37
|
+
belongs_to :person
|
38
|
+
end
|
39
|
+
|
40
|
+
ActiveRecord::Base.silence do
|
41
|
+
ActiveRecord::Migration.verbose = false
|
42
|
+
ActiveRecord::Schema.define :version => 0 do
|
43
|
+
create_table(:people) { |t| t.string :name; t.integer :user_id }
|
44
|
+
create_table(:users) { |t| t.string :uid }
|
45
|
+
create_table(:projects) { |t| t.string :name; t.integer :person_id }
|
46
|
+
create_table(:public_profiles) { |t| t.string :name; t.integer :person_id }
|
47
|
+
create_table(:logs) { |t| t.string :message; t.integer :person_id }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
RSpec.configure do |config|
|
52
|
+
config.before(:suite) do
|
53
|
+
DatabaseCleaner.strategy = :truncation
|
54
|
+
DatabaseCleaner.clean
|
55
|
+
end
|
56
|
+
|
57
|
+
config.after(:each) do
|
58
|
+
DatabaseCleaner.clean
|
59
|
+
end
|
60
|
+
end
|
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: prevent_destroy_if_any
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Florent Guilleux
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-07 00:00:00.000000000 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
17
|
+
requirement: &2157972440 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2157972440
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: bundler
|
28
|
+
requirement: &2157971360 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *2157971360
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
requirement: &2157970640 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2157970640
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: database_cleaner
|
50
|
+
requirement: &2157969820 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *2157969820
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: sqlite3-ruby
|
61
|
+
requirement: &2157968200 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *2157968200
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rake
|
72
|
+
requirement: &2157709680 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *2157709680
|
81
|
+
description: ActiveRecord plugin to prevent destroy when associations are present
|
82
|
+
email:
|
83
|
+
- florent2@gmail.com
|
84
|
+
executables: []
|
85
|
+
extensions: []
|
86
|
+
extra_rdoc_files: []
|
87
|
+
files:
|
88
|
+
- .gitignore
|
89
|
+
- Gemfile
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- lib/prevent_destroy_if_any.rb
|
93
|
+
- lib/prevent_destroy_if_any/version.rb
|
94
|
+
- prevent_destroy_if_any.gemspec
|
95
|
+
- spec/prevent_destroy_if_any_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
has_rdoc: true
|
98
|
+
homepage: https://github.com/Florent2/prevent_destroy_if_any
|
99
|
+
licenses: []
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
hash: 3762508194909461440
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
segments:
|
120
|
+
- 0
|
121
|
+
hash: 3762508194909461440
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project: prevent_destroy_if_any
|
124
|
+
rubygems_version: 1.6.2
|
125
|
+
signing_key:
|
126
|
+
specification_version: 3
|
127
|
+
summary: ActiveRecord plugin to prevent destroy when associations are present
|
128
|
+
test_files:
|
129
|
+
- spec/prevent_destroy_if_any_spec.rb
|
130
|
+
- spec/spec_helper.rb
|