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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ball_gag (0.0.1)
4
+ ball_gag (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
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.').body_gagged?
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 :body { |body| !/damn/.match body }
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[: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 })
@@ -2,6 +2,8 @@ require 'ball_gag/version'
2
2
  require 'ball_gag/gag'
3
3
  require 'ball_gag/engine'
4
4
  require 'ball_gag/errors'
5
+ require 'ball_gag/cloak'
6
+ require 'ball_gag/bowling_ball'
5
7
 
6
8
  begin
7
9
  require 'ball_gag/validations'
@@ -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
+
@@ -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
- "#{attribute}_gagged?"
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
- "#{attribute}_not_gagged?"
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
 
@@ -1,8 +1,28 @@
1
- class NotGaggedValidator < ActiveModel::EachValidator
1
+ class GaggedValidator < ActiveModel::EachValidator
2
2
  def validate_each object, attribute, value
3
- if object.method("#{attribute}_gagged?").call
4
- object.errors[attribute] << (options[:message] || 'is gagged')
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
 
@@ -1,4 +1,4 @@
1
1
  module BallGag
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
4
4
 
@@ -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
+
@@ -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
+
@@ -3,6 +3,8 @@ require 'spec_helper'
3
3
  describe ExampleModel do
4
4
  before do
5
5
  BallGag.engine = nil
6
+ BallGag.verb = nil
7
+ BallGag.preterite = nil
6
8
  ExampleModel.clear_gagged_attributes
7
9
  end
8
10
 
@@ -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
- it 'should call #{attribute}_gagged?' do
9
- ExampleActiveModel.validates :words, not_gagged: true
9
+ describe NotGaggedValidator do
10
+ it 'should call #{attribute}_gagged?' do
11
+ ExampleActiveModel.validates :words, not_gagged: true
10
12
 
11
- instance = ExampleActiveModel.new
12
- instance.should_receive(:words_gagged?)
13
- instance.valid?
14
- end
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
- it 'should add default error message' do
17
- ExampleActiveModel.validates :words, not_gagged: true
18
- instance = ExampleActiveModel.new
19
- instance.stub!(words_gagged?: true)
20
- instance.valid?
21
- instance.errors[:words].should include 'is gagged'
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
- it 'should respect custom error message' do
25
- ExampleActiveModel.validates :words,
26
- not_gagged: { message: 'is not acceptable' }
27
- instance = ExampleActiveModel.new
28
- instance.stub!(words_gagged?: true)
29
- instance.valid?
30
- instance.errors[:words].should include 'is not acceptable'
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.1
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-07 00:00:00.000000000 Z
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: &70285274103000 !ruby/object:Gem::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: *70285274103000
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