protective 0.1.0
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/.document +5 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +35 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +28 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/lib/protective.rb +61 -0
- data/rails/init.rb +1 -0
- data/test/database.yml +3 -0
- data/test/helper.rb +26 -0
- data/test/protective_test.rb +51 -0
- data/test/schema.rb +10 -0
- metadata +169 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
gem "activerecord"
|
7
|
+
|
8
|
+
# Add dependencies to develop your gem here.
|
9
|
+
# Include everything needed to run rake, tests, features, etc.
|
10
|
+
group :development do
|
11
|
+
gem "bundler", "~> 1.0.0"
|
12
|
+
gem "jeweler", "~> 1.5.2"
|
13
|
+
gem "rcov", ">= 0"
|
14
|
+
gem "sqlite3"
|
15
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.0.3)
|
5
|
+
activesupport (= 3.0.3)
|
6
|
+
builder (~> 2.1.2)
|
7
|
+
i18n (~> 0.4)
|
8
|
+
activerecord (3.0.3)
|
9
|
+
activemodel (= 3.0.3)
|
10
|
+
activesupport (= 3.0.3)
|
11
|
+
arel (~> 2.0.2)
|
12
|
+
tzinfo (~> 0.3.23)
|
13
|
+
activesupport (3.0.3)
|
14
|
+
arel (2.0.7)
|
15
|
+
builder (2.1.2)
|
16
|
+
git (1.2.5)
|
17
|
+
i18n (0.5.0)
|
18
|
+
jeweler (1.5.2)
|
19
|
+
bundler (~> 1.0.0)
|
20
|
+
git (>= 1.2.5)
|
21
|
+
rake
|
22
|
+
rake (0.8.7)
|
23
|
+
rcov (0.9.9)
|
24
|
+
sqlite3 (1.3.3)
|
25
|
+
tzinfo (0.3.24)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
activerecord
|
32
|
+
bundler (~> 1.0.0)
|
33
|
+
jeweler (~> 1.5.2)
|
34
|
+
rcov
|
35
|
+
sqlite3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Pascal Zumkehr
|
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.rdoc
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
= protective
|
2
|
+
|
3
|
+
In your ActiveRecord models, you used to protect the instances from being destroyed as follows:
|
4
|
+
|
5
|
+
before_destroy :protect_if_has_attachments
|
6
|
+
|
7
|
+
def protect_if_has_attachments
|
8
|
+
unless attachments.empty?
|
9
|
+
errors.add(:base, "Record has attachments and cannot be destroyed")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
With +protective+, this is reduced to:
|
14
|
+
|
15
|
+
protect_if :attachments, "Record has attachments and cannot be destroyed"
|
16
|
+
|
17
|
+
Of course, you may pass the name of any defined method. If its result evaluates to +present?+, the record is not going to be destroyed. No exception is thrown, but a message is added to the +errors+ object of your model. This may then be used further on.
|
18
|
+
|
19
|
+
To use protective, simply add it to your +Gemfile+:
|
20
|
+
|
21
|
+
gem 'protective'
|
22
|
+
|
23
|
+
|
24
|
+
== Copyright
|
25
|
+
|
26
|
+
Copyright (c) 2011 Pascal Zumkehr. See LICENSE.txt for
|
27
|
+
further details.
|
28
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "protective"
|
16
|
+
gem.homepage = "http://github.com/codez/protective"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{Protect records from being destroyed in a declarative way}
|
19
|
+
gem.description = %Q{Protect records from being destroyed in a declarative way. Simply add 'protect_if :dont_delete, "Record is marked as not deletable"' to your ActiveRecord model. Your record will no be destroyed and the given message is added to the errors object.}
|
20
|
+
gem.email = "spam@codez.ch"
|
21
|
+
gem.authors = ["Pascal Zumkehr"]
|
22
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
+
gem.add_runtime_dependency 'activerecord'
|
25
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
Rake::TestTask.new(:test) do |test|
|
31
|
+
test.libs << 'lib' << 'test'
|
32
|
+
test.pattern = 'test/**/*_test.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'rcov/rcovtask'
|
37
|
+
Rcov::RcovTask.new do |test|
|
38
|
+
test.libs << 'test'
|
39
|
+
test.pattern = 'test/**/*_test.rb'
|
40
|
+
test.verbose = true
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "protective #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('LICENSE*')
|
53
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/protective.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
# Protect active records from being destroyed in a declarative way.
|
4
|
+
module Protective
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.send :extend, ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Protects a record from being destroyed if the passed method
|
12
|
+
# evaluates to #present? upon destruction. If a messag is given,
|
13
|
+
# it is added to the corresponding #errors object.
|
14
|
+
def protect_if(method, message = nil)
|
15
|
+
unless self < InstanceMethods
|
16
|
+
class_attribute :protect_if_methods
|
17
|
+
self.protect_if_methods = {}
|
18
|
+
|
19
|
+
before_destroy :destruction_allowed?
|
20
|
+
send :include, InstanceMethods
|
21
|
+
end
|
22
|
+
|
23
|
+
protect_if_methods[method] = message
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module InstanceMethods
|
28
|
+
|
29
|
+
# Returns true if this record cannot be destroyed.
|
30
|
+
def protected?
|
31
|
+
protect_if_methods.keys.any? do |method|
|
32
|
+
!protect_method_allows_destruction(method)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns true if this record may be destroyed or
|
37
|
+
# adds possible error messages to the #errors object otherwise.
|
38
|
+
def destruction_allowed?
|
39
|
+
protect_if_methods.all? do |method, message|
|
40
|
+
unless allowed = protect_method_allows_destruction(method)
|
41
|
+
errors.add(:base, message) if message
|
42
|
+
end
|
43
|
+
allowed
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def protect_method_allows_destruction(method)
|
50
|
+
value = send(method)
|
51
|
+
if value.respond_to?(:empty?) # ar *_many association
|
52
|
+
value.empty?
|
53
|
+
else
|
54
|
+
value.blank?
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
ActiveRecord::Base.send :include, Protective
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'protective'
|
data/test/database.yml
ADDED
data/test/helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
14
|
+
require 'protective'
|
15
|
+
|
16
|
+
|
17
|
+
def load_schema
|
18
|
+
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
19
|
+
|
20
|
+
ActiveRecord::Base.establish_connection(config['sqlite3'])
|
21
|
+
load(File.dirname(__FILE__) + "/schema.rb")
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
class Test::Unit::TestCase
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class ProtectiveTest < Test::Unit::TestCase
|
4
|
+
load_schema
|
5
|
+
|
6
|
+
class Subject < ActiveRecord::Base
|
7
|
+
has_many :attachments
|
8
|
+
|
9
|
+
protect_if :attachments, "Still has attachments"
|
10
|
+
protect_if :marked
|
11
|
+
end
|
12
|
+
|
13
|
+
class Attachment < ActiveRecord::Base
|
14
|
+
belongs_to :subjects
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_setup
|
18
|
+
assert_equal [], Subject.all
|
19
|
+
assert_equal 2, Subject.protect_if_methods.size
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_empty_subject_may_be_destroyed
|
23
|
+
s = Subject.create! :name => 'test'
|
24
|
+
assert !s.protected?
|
25
|
+
assert s.destroy
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_marked_subject_may_not_be_destroyed
|
29
|
+
s = Subject.create! :name => 'test', :marked => true
|
30
|
+
assert s.protected?
|
31
|
+
assert !s.destroy
|
32
|
+
assert_equal 0, s.errors.count
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_subject_may_not_be_destroyed_with_attachements
|
36
|
+
s = Subject.create! :name => 'test'
|
37
|
+
s.attachments.create! :name => 'att'
|
38
|
+
assert s.attachments.respond_to?(:empty?)
|
39
|
+
assert_equal 1, s.attachments.count
|
40
|
+
assert s.protected?
|
41
|
+
assert !s.destroy
|
42
|
+
assert_equal ["Still has attachments"], s.errors[:base]
|
43
|
+
assert !s.destruction_allowed?
|
44
|
+
end
|
45
|
+
|
46
|
+
def teardown
|
47
|
+
Subject.delete_all
|
48
|
+
Attachment.delete_all
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/test/schema.rb
ADDED
metadata
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: protective
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Pascal Zumkehr
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-02-07 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 3
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
name: activerecord
|
33
|
+
prerelease: false
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
hash: 23
|
42
|
+
segments:
|
43
|
+
- 1
|
44
|
+
- 0
|
45
|
+
- 0
|
46
|
+
version: 1.0.0
|
47
|
+
type: :development
|
48
|
+
name: bundler
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 7
|
58
|
+
segments:
|
59
|
+
- 1
|
60
|
+
- 5
|
61
|
+
- 2
|
62
|
+
version: 1.5.2
|
63
|
+
type: :development
|
64
|
+
name: jeweler
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
type: :development
|
78
|
+
name: rcov
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
type: :development
|
92
|
+
name: sqlite3
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: *id005
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
hash: 3
|
102
|
+
segments:
|
103
|
+
- 0
|
104
|
+
version: "0"
|
105
|
+
type: :runtime
|
106
|
+
name: activerecord
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: *id006
|
109
|
+
description: Protect records from being destroyed in a declarative way. Simply add 'protect_if :dont_delete, "Record is marked as not deletable"' to your ActiveRecord model. Your record will no be destroyed and the given message is added to the errors object.
|
110
|
+
email: spam@codez.ch
|
111
|
+
executables: []
|
112
|
+
|
113
|
+
extensions: []
|
114
|
+
|
115
|
+
extra_rdoc_files:
|
116
|
+
- LICENSE.txt
|
117
|
+
- README.rdoc
|
118
|
+
files:
|
119
|
+
- .document
|
120
|
+
- Gemfile
|
121
|
+
- Gemfile.lock
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.rdoc
|
124
|
+
- Rakefile
|
125
|
+
- VERSION
|
126
|
+
- lib/protective.rb
|
127
|
+
- rails/init.rb
|
128
|
+
- test/database.yml
|
129
|
+
- test/helper.rb
|
130
|
+
- test/protective_test.rb
|
131
|
+
- test/schema.rb
|
132
|
+
has_rdoc: true
|
133
|
+
homepage: http://github.com/codez/protective
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
hash: 3
|
147
|
+
segments:
|
148
|
+
- 0
|
149
|
+
version: "0"
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
hash: 3
|
156
|
+
segments:
|
157
|
+
- 0
|
158
|
+
version: "0"
|
159
|
+
requirements: []
|
160
|
+
|
161
|
+
rubyforge_project:
|
162
|
+
rubygems_version: 1.3.7
|
163
|
+
signing_key:
|
164
|
+
specification_version: 3
|
165
|
+
summary: Protect records from being destroyed in a declarative way
|
166
|
+
test_files:
|
167
|
+
- test/helper.rb
|
168
|
+
- test/protective_test.rb
|
169
|
+
- test/schema.rb
|