ball_gag 0.0.1 → 0.0.2
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/Gemfile.lock +1 -1
- data/Readme.md +12 -5
- data/lib/ball_gag.rb +2 -0
- data/lib/ball_gag/bowling_ball.rb +36 -0
- data/lib/ball_gag/cloak.rb +74 -0
- data/lib/ball_gag/gag.rb +11 -7
- data/lib/ball_gag/validations.rb +23 -3
- data/lib/ball_gag/version.rb +1 -1
- data/spec/bowling_ball_spec.rb +16 -0
- data/spec/cloak_spec.rb +133 -0
- data/spec/gag_spec.rb +2 -0
- data/spec/validations_spec.rb +32 -19
- metadata +10 -4
data/Gemfile.lock
CHANGED
data/Readme.md
CHANGED
@@ -24,7 +24,7 @@ end
|
|
24
24
|
Post.new('That was some damn good watermelon').body_gagged?
|
25
25
|
# true
|
26
26
|
|
27
|
-
Post.new('That was some fine watermelon
|
27
|
+
Post.new('That was some fine watermelon').body_gagged?
|
28
28
|
# false
|
29
29
|
````
|
30
30
|
|
@@ -40,12 +40,20 @@ Now a <tt>NotGaggedValidator</tt> is available which you can use like this.
|
|
40
40
|
````ruby
|
41
41
|
class Post < ActiveRecord::Base
|
42
42
|
include BallGag
|
43
|
-
gag
|
43
|
+
gag(:body) { |body| !/damn/.match body }
|
44
44
|
|
45
45
|
validates :body, :not_gagged => true
|
46
46
|
end
|
47
47
|
````
|
48
48
|
|
49
|
+
````ruby
|
50
|
+
Post.new(body: 'That was some damn good watermelon').valid?
|
51
|
+
# false
|
52
|
+
|
53
|
+
Post.new(body: 'That was some fine watermelon').valid?
|
54
|
+
# true
|
55
|
+
````
|
56
|
+
|
49
57
|
## Engines / Global configuration
|
50
58
|
Each gagged attribute can be provided its own block to call when checking acceptability, or a global engine can be provided. Set a global engine like this.
|
51
59
|
|
@@ -102,10 +110,9 @@ class ModerationServiceEngine
|
|
102
110
|
return call(options[:attr] => fields, options)
|
103
111
|
end
|
104
112
|
|
105
|
-
gag_options = options
|
113
|
+
gag_options, instance = options.values_at(:options, :instance)
|
106
114
|
|
107
|
-
sender = gag_options[:sender].
|
108
|
-
bind(instance).call
|
115
|
+
sender = gag_options[:sender].bind(instance).call
|
109
116
|
|
110
117
|
response = new(*MyApp::ApplicationConfig.moderation_service_credentials).
|
111
118
|
get('/moderate', query: { fields: fields, user: sender })
|
data/lib/ball_gag.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
module BowlingBall
|
2
|
+
class << self
|
3
|
+
def included base
|
4
|
+
base.send(:include, BallGag)
|
5
|
+
end
|
6
|
+
|
7
|
+
def engine
|
8
|
+
BallGag.engine
|
9
|
+
end
|
10
|
+
|
11
|
+
def engine= engine
|
12
|
+
BallGag.engine = engine
|
13
|
+
end
|
14
|
+
|
15
|
+
def verb
|
16
|
+
BallGag.verb
|
17
|
+
end
|
18
|
+
|
19
|
+
def verb= verb
|
20
|
+
BallGag.verb= verb
|
21
|
+
end
|
22
|
+
|
23
|
+
def preterite
|
24
|
+
BallGag.preterite
|
25
|
+
end
|
26
|
+
|
27
|
+
def preterite= preterite
|
28
|
+
BallGag.preterite = preterite
|
29
|
+
end
|
30
|
+
|
31
|
+
def negative_preterite= preterite
|
32
|
+
BallGag.negative_preterite = preterite
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module BallGag
|
2
|
+
module Cloak
|
3
|
+
def verb
|
4
|
+
@verb || 'gag'
|
5
|
+
end
|
6
|
+
|
7
|
+
def verb= verb
|
8
|
+
old_verb = @verb
|
9
|
+
@verb = verb
|
10
|
+
|
11
|
+
BallGag::ClassMethods.instance_eval do
|
12
|
+
if verb
|
13
|
+
define_method verb do |*args|
|
14
|
+
gag *args
|
15
|
+
end
|
16
|
+
elsif old_verb
|
17
|
+
remove_method old_verb
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def preterite
|
23
|
+
@preterite || 'gagged'
|
24
|
+
end
|
25
|
+
|
26
|
+
def preterite= preterite
|
27
|
+
set_preterite preterite
|
28
|
+
@preterite_negative = false
|
29
|
+
end
|
30
|
+
|
31
|
+
def negative_preterite= preterite
|
32
|
+
set_preterite preterite
|
33
|
+
@preterite_negative = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def preterite_negative?
|
37
|
+
@preterite_negative
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def set_preterite preterite
|
42
|
+
undefine_old_preterite_validators @preterite
|
43
|
+
define_preterite_validators preterite
|
44
|
+
|
45
|
+
@preterite = preterite
|
46
|
+
end
|
47
|
+
|
48
|
+
def define_preterite_validators preterite
|
49
|
+
return unless preterite
|
50
|
+
|
51
|
+
Kernel.const_set(validator_name(preterite), Class.new(GaggedValidator))
|
52
|
+
Kernel.const_set(not_validator_name(preterite), Class.new(NotGaggedValidator))
|
53
|
+
end
|
54
|
+
|
55
|
+
def undefine_old_preterite_validators preterite
|
56
|
+
return unless preterite
|
57
|
+
|
58
|
+
Kernel.send(:remove_const, validator_name(preterite))
|
59
|
+
Kernel.send(:remove_const, not_validator_name(preterite))
|
60
|
+
end
|
61
|
+
|
62
|
+
def validator_name preterite
|
63
|
+
"#{preterite.to_s.capitalize}Validator"
|
64
|
+
end
|
65
|
+
|
66
|
+
def not_validator_name preterite
|
67
|
+
"Not#{validator_name(preterite)}"
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
extend Cloak
|
73
|
+
end
|
74
|
+
|
data/lib/ball_gag/gag.rb
CHANGED
@@ -64,19 +64,16 @@ module BallGag
|
|
64
64
|
if 1 == arity
|
65
65
|
fn = lambda { |it, attr| callable.call(output.call(it, attr)) }
|
66
66
|
else
|
67
|
-
options = {}
|
68
67
|
fn = lambda do |it, attr|
|
69
68
|
callable.call(output.call(it, attr),
|
70
69
|
{ options: gag_options,
|
71
70
|
instance: it,
|
72
71
|
attr: attr,
|
73
72
|
single: one_attribute
|
74
|
-
}
|
75
|
-
)
|
73
|
+
})
|
76
74
|
end
|
77
75
|
end
|
78
76
|
|
79
|
-
|
80
77
|
attributes.each do |attr|
|
81
78
|
@gagged_attributes_methods.send(:define_method,
|
82
79
|
gagged_attribute_negative_interpellation_name(attr)) do
|
@@ -112,16 +109,23 @@ module BallGag
|
|
112
109
|
end
|
113
110
|
|
114
111
|
def gagged_attribute_interpellation_name attribute
|
115
|
-
|
112
|
+
gagged_attribute_preterite_interpellation_name(
|
113
|
+
attribute, !BallGag.preterite_negative?)
|
116
114
|
end
|
117
115
|
|
118
116
|
def gagged_attribute_negative_interpellation_name attribute
|
119
|
-
|
117
|
+
gagged_attribute_preterite_interpellation_name(
|
118
|
+
attribute, BallGag.preterite_negative?)
|
119
|
+
end
|
120
|
+
|
121
|
+
def gagged_attribute_preterite_interpellation_name attribute, negative
|
122
|
+
negative ?
|
123
|
+
"#{attribute}_#{BallGag.preterite}?" :
|
124
|
+
"#{attribute}_not_#{BallGag.preterite}?"
|
120
125
|
end
|
121
126
|
|
122
127
|
def undefine_gagged_attributes_methods
|
123
128
|
@gagged_attributes.keys.each do |attribute|
|
124
|
-
|
125
129
|
@gagged_attributes_methods.send(:remove_method,
|
126
130
|
gagged_attribute_interpellation_name(attribute))
|
127
131
|
|
data/lib/ball_gag/validations.rb
CHANGED
@@ -1,8 +1,28 @@
|
|
1
|
-
class
|
1
|
+
class GaggedValidator < ActiveModel::EachValidator
|
2
2
|
def validate_each object, attribute, value
|
3
|
-
|
4
|
-
object.errors[attribute] << (options[:message] ||
|
3
|
+
unless object.method(condition_method_name(attribute)).call
|
4
|
+
object.errors[attribute] << (options[:message] || default_message)
|
5
5
|
end
|
6
6
|
end
|
7
|
+
|
8
|
+
private
|
9
|
+
def condition_method_name attribute
|
10
|
+
"#{attribute}_#{BallGag.preterite}?"
|
11
|
+
end
|
12
|
+
|
13
|
+
def default_message
|
14
|
+
"is not #{BallGag.preterite}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class NotGaggedValidator < GaggedValidator
|
19
|
+
private
|
20
|
+
def condition_method_name attribute
|
21
|
+
"#{attribute}_not_#{BallGag.preterite}?"
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_message
|
25
|
+
"is #{BallGag.preterite}"
|
26
|
+
end
|
7
27
|
end
|
8
28
|
|
data/lib/ball_gag/version.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BowlingBall do
|
4
|
+
after { Kernel.send(:remove_const, :BowlingBallIncluder) }
|
5
|
+
|
6
|
+
context 'when included' do
|
7
|
+
it 'should include BallGag' do
|
8
|
+
class Kernel::BowlingBallIncluder
|
9
|
+
include BowlingBall
|
10
|
+
end
|
11
|
+
|
12
|
+
BowlingBallIncluder.included_modules.should include BallGag
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
data/spec/cloak_spec.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'BallGag cloaking' do
|
4
|
+
before do
|
5
|
+
ExampleModel.clear_gagged_attributes
|
6
|
+
ExampleActiveModel.reset_callbacks :validate
|
7
|
+
ExampleActiveModel.clear_gagged_attributes
|
8
|
+
BallGag.verb = nil
|
9
|
+
BallGag.preterite = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
ExampleModel.clear_gagged_attributes
|
14
|
+
ExampleActiveModel.clear_gagged_attributes
|
15
|
+
BallGag.verb = nil
|
16
|
+
BallGag.preterite = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have default verb' do
|
20
|
+
BallGag.verb.should eq 'gag'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should accept new verb' do
|
24
|
+
BallGag.verb = 'censor'
|
25
|
+
BallGag.verb.should eq 'censor'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should provide verb as class method' do
|
29
|
+
BallGag.verb = 'censor'
|
30
|
+
ExampleModel.should respond_to :censor
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should gag attribute when custom verb is used' do
|
34
|
+
BallGag.verb = 'censor'
|
35
|
+
ExampleModel.censor :words
|
36
|
+
ExampleModel.gagged_attributes.should include :words
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should remove custom verb method when verb is cleared' do
|
40
|
+
BallGag.verb = 'censor'
|
41
|
+
BallGag.verb = nil
|
42
|
+
ExampleModel.should_not respond_to :censor
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should have preterite' do
|
46
|
+
BallGag.preterite.should eq 'gagged'
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should accept new preterite' do
|
50
|
+
BallGag.preterite = 'censored'
|
51
|
+
BallGag.preterite.should eq 'censored'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should define #{attribute}_#{preterite}? method on instance' do
|
55
|
+
BallGag.preterite = 'censored'
|
56
|
+
ExampleModel.gag :words
|
57
|
+
ExampleModel.new.should respond_to :words_censored?
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should define #{attribute}_not_#{preterite}? method on instance' do
|
61
|
+
BallGag.preterite = 'censored'
|
62
|
+
ExampleModel.gag :words
|
63
|
+
ExampleModel.new.should respond_to :words_not_censored?
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should have non-negative preterite' do
|
67
|
+
BallGag.preterite_negative?.should be_false
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should accept negative preterite' do
|
71
|
+
BallGag.negative_preterite = 'acceptable'
|
72
|
+
BallGag.preterite_negative?.should be_true
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when preterite is negative' do
|
76
|
+
it 'should invert meaning of #{attribute}_#{preterite}?' do
|
77
|
+
BallGag.negative_preterite = 'acceptable'
|
78
|
+
ExampleModel.gag(:words) { |words| true }
|
79
|
+
ExampleModel.new.words_acceptable?.should be_true
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should invert meaning of #{attribute}_not_#{preterite}?' do
|
83
|
+
BallGag.negative_preterite = 'acceptable'
|
84
|
+
ExampleModel.gag(:words) { |words| true }
|
85
|
+
ExampleModel.new.words_not_acceptable?.should be_false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'validators' do
|
90
|
+
specify 'custom preterite should create validator' do
|
91
|
+
BallGag.preterite = 'censored'
|
92
|
+
ExampleActiveModel.gag(:words) { |words| true }
|
93
|
+
ExampleActiveModel.validates :words, censored: true
|
94
|
+
instance = ExampleActiveModel.new
|
95
|
+
instance.valid?
|
96
|
+
instance.errors[:words].should include 'is not censored'
|
97
|
+
end
|
98
|
+
|
99
|
+
specify 'custom preterite should create Not validator' do
|
100
|
+
BallGag.preterite = 'censored'
|
101
|
+
ExampleActiveModel.gag(:words) { |words| false }
|
102
|
+
ExampleActiveModel.validates :words, not_censored: true
|
103
|
+
instance = ExampleActiveModel.new
|
104
|
+
instance.valid?
|
105
|
+
instance.errors[:words].should include 'is censored'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe BowlingBall do
|
110
|
+
it 'should set verb' do
|
111
|
+
BowlingBall.verb = 'censor'
|
112
|
+
BallGag.verb.should eq 'censor'
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should set preterite' do
|
116
|
+
BowlingBall.preterite = 'censored'
|
117
|
+
BallGag.preterite.should eq 'censored'
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should set negative preterite' do
|
121
|
+
BowlingBall.negative_preterite = 'acceptable'
|
122
|
+
BallGag.preterite.should eq 'acceptable'
|
123
|
+
BallGag.preterite_negative?.should be_true
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should set engine' do
|
127
|
+
mock_engine = mock('engine')
|
128
|
+
BowlingBall.engine = mock_engine
|
129
|
+
BallGag.engine.should eq mock_engine
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
data/spec/gag_spec.rb
CHANGED
data/spec/validations_spec.rb
CHANGED
@@ -3,31 +3,44 @@ require 'spec_helper'
|
|
3
3
|
describe 'ActiveModel::Validations integration' do
|
4
4
|
before do
|
5
5
|
ExampleActiveModel.reset_callbacks :validate
|
6
|
+
ExampleActiveModel.clear_gagged_attributes
|
6
7
|
end
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
describe NotGaggedValidator do
|
10
|
+
it 'should call #{attribute}_gagged?' do
|
11
|
+
ExampleActiveModel.validates :words, not_gagged: true
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
instance = ExampleActiveModel.new
|
14
|
+
instance.should_receive(:words_not_gagged?)
|
15
|
+
instance.valid?
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should add default error message' do
|
19
|
+
ExampleActiveModel.validates :words, not_gagged: true
|
20
|
+
instance = ExampleActiveModel.new
|
21
|
+
instance.stub!(words_not_gagged?: false)
|
22
|
+
instance.valid?
|
23
|
+
instance.errors[:words].should include 'is gagged'
|
24
|
+
end
|
15
25
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
it 'should respect custom error message' do
|
27
|
+
ExampleActiveModel.validates :words,
|
28
|
+
not_gagged: { message: 'is not acceptable' }
|
29
|
+
instance = ExampleActiveModel.new
|
30
|
+
instance.stub!(words_not_gagged?: false)
|
31
|
+
instance.valid?
|
32
|
+
instance.errors[:words].should include 'is not acceptable'
|
33
|
+
end
|
22
34
|
end
|
23
35
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
36
|
+
describe GaggedValidator do
|
37
|
+
it 'should add default error message' do
|
38
|
+
ExampleActiveModel.validates :words, gagged: true
|
39
|
+
instance = ExampleActiveModel.new
|
40
|
+
instance.stub!(words_gagged?: false)
|
41
|
+
instance.valid?
|
42
|
+
instance.errors[:words].should include 'is not gagged'
|
43
|
+
end
|
31
44
|
end
|
32
45
|
end
|
33
46
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ball_gag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70299098639740 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70299098639740
|
25
25
|
description: Validate user input using pluggable back-ends
|
26
26
|
email:
|
27
27
|
- duncan@dweebd.com
|
@@ -38,11 +38,15 @@ files:
|
|
38
38
|
- Readme.md
|
39
39
|
- ball_gag.gemspec
|
40
40
|
- lib/ball_gag.rb
|
41
|
+
- lib/ball_gag/bowling_ball.rb
|
42
|
+
- lib/ball_gag/cloak.rb
|
41
43
|
- lib/ball_gag/engine.rb
|
42
44
|
- lib/ball_gag/errors.rb
|
43
45
|
- lib/ball_gag/gag.rb
|
44
46
|
- lib/ball_gag/validations.rb
|
45
47
|
- lib/ball_gag/version.rb
|
48
|
+
- spec/bowling_ball_spec.rb
|
49
|
+
- spec/cloak_spec.rb
|
46
50
|
- spec/engine_spec.rb
|
47
51
|
- spec/gag_spec.rb
|
48
52
|
- spec/spec_helper.rb
|
@@ -73,6 +77,8 @@ signing_key:
|
|
73
77
|
specification_version: 3
|
74
78
|
summary: Pluggable User-Content Validation
|
75
79
|
test_files:
|
80
|
+
- spec/bowling_ball_spec.rb
|
81
|
+
- spec/cloak_spec.rb
|
76
82
|
- spec/engine_spec.rb
|
77
83
|
- spec/gag_spec.rb
|
78
84
|
- spec/spec_helper.rb
|