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.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
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
@@ -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
@@ -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.
@@ -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
+
@@ -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
@@ -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
@@ -0,0 +1 @@
1
+ require 'protective'
@@ -0,0 +1,3 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: test/protective_plugin.sqlite3.db
@@ -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
@@ -0,0 +1,10 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :subjects, :force => true do |t|
3
+ t.string :name
4
+ t.boolean :marked
5
+ end
6
+ create_table :attachments, :force => true do |t|
7
+ t.string :name
8
+ t.integer :subject_id
9
+ end
10
+ end
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