knight 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/.gitignore +1 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/Gemfile +7 -0
- data/Gemfile.dev +16 -0
- data/README.md +3 -1
- data/Rakefile +6 -1
- data/knight.gemspec +4 -1
- data/lib/knight.rb +18 -2
- data/lib/knight/error.rb +60 -0
- data/lib/knight/instance_methods.rb +69 -0
- data/lib/knight/result.rb +86 -0
- data/lib/knight/rule.rb +74 -0
- data/lib/knight/rule/exact_length.rb +63 -0
- data/lib/knight/rule/format.rb +62 -0
- data/lib/knight/rule/inclusion.rb +62 -0
- data/lib/knight/rule/maximum_length.rb +63 -0
- data/lib/knight/rule/minimum_length.rb +63 -0
- data/lib/knight/rule/presence.rb +37 -0
- data/lib/knight/rule/range_length.rb +64 -0
- data/lib/knight/validator.rb +91 -0
- data/lib/knight/version.rb +3 -1
- data/metrics/flog.yml +2 -0
- data/metrics/rubocop.yml +17 -0
- data/spec/integration/contextual_validator_spec.rb +41 -0
- data/spec/integration/knight_spec.rb +30 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/unit/knight/error/class_methods/new_spec.rb +15 -0
- data/spec/unit/knight/error/message_spec.rb +26 -0
- data/spec/unit/knight/instance_methods/class_methods/included_spec.rb +24 -0
- data/spec/unit/knight/instance_methods/class_methods/new_spec.rb +12 -0
- data/spec/unit/knight/instance_methods/class_methods/validator_spec.rb +13 -0
- data/spec/unit/knight/instance_methods/run_spec.rb +29 -0
- data/spec/unit/knight/result/class_methods/new_spec.rb +13 -0
- data/spec/unit/knight/result/errors_spec.rb +71 -0
- data/spec/unit/knight/result/valid_predicate_spec.rb +28 -0
- data/spec/unit/knight/rule/class_methods/new_spec.rb +38 -0
- data/spec/unit/knight/rule/error_spec.rb +29 -0
- data/spec/unit/knight/rule/exact_length/class_methods/new_spec.rb +27 -0
- data/spec/unit/knight/rule/exact_length/matches_predicate_spec.rb +19 -0
- data/spec/unit/knight/rule/exact_length/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/format/class_methods/new_spec.rb +26 -0
- data/spec/unit/knight/rule/format/matches_predicate_spec.rb +31 -0
- data/spec/unit/knight/rule/format/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/inclusion/class_methods/new_spec.rb +28 -0
- data/spec/unit/knight/rule/inclusion/matches_predicate_spec.rb +48 -0
- data/spec/unit/knight/rule/inclusion/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/maximum_length/class_methods/new_spec.rb +27 -0
- data/spec/unit/knight/rule/maximum_length/matches_predicate_spec.rb +21 -0
- data/spec/unit/knight/rule/maximum_length/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/minimum_length/class_methods/new_spec.rb +27 -0
- data/spec/unit/knight/rule/minimum_length/matches_predicate_spec.rb +21 -0
- data/spec/unit/knight/rule/minimum_length/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/presence/matches_predicate_spec.rb +27 -0
- data/spec/unit/knight/rule/range_length/class_methods/new_spec.rb +27 -0
- data/spec/unit/knight/rule/range_length/matches_predicate_spec.rb +19 -0
- data/spec/unit/knight/rule/range_length/to_hash_spec.rb +12 -0
- data/spec/unit/knight/rule/to_hash_spec.rb +13 -0
- data/spec/unit/knight/validator/add_spec.rb +29 -0
- data/spec/unit/knight/validator/class_methods/new_spec.rb +18 -0
- data/spec/unit/knight/validator/context_spec.rb +13 -0
- data/spec/unit/knight/validator/rules_spec.rb +29 -0
- data/spec/unit/knight/validator/run_spec.rb +26 -0
- metadata +138 -6
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::ExactLength, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, 3) }
|
9
|
+
let(:value) { 'abc' }
|
10
|
+
|
11
|
+
it { should be_true }
|
12
|
+
|
13
|
+
%w(ab abcdef).each do |value|
|
14
|
+
context "with value: #{value.inspect}" do
|
15
|
+
let(:value) { value }
|
16
|
+
it { should be_false }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::ExactLength, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, 3) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, length: 3 }) }
|
12
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Format, '.new' do
|
6
|
+
let(:attribute) { :foo }
|
7
|
+
let(:regexp) { /abc/ }
|
8
|
+
let(:options) { { message: 'message' } }
|
9
|
+
|
10
|
+
context 'with options' do
|
11
|
+
subject { described_class.new(attribute, regexp, options) }
|
12
|
+
|
13
|
+
it { should be_instance_of(described_class) }
|
14
|
+
its(:attribute_name) { should eql(attribute) }
|
15
|
+
its(:regexp) { should eql(regexp) }
|
16
|
+
its(:options) { should eql(options) }
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with no options' do
|
20
|
+
subject { described_class.new(attribute, regexp) }
|
21
|
+
|
22
|
+
it { should be_instance_of(described_class) }
|
23
|
+
its(:options) { should be_empty }
|
24
|
+
its(:message) { should eql('%{attribute} has an invalid format') }
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Format, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, /abc/) }
|
9
|
+
|
10
|
+
%w(
|
11
|
+
abcxxx
|
12
|
+
xxxabc
|
13
|
+
xxxabcxxx
|
14
|
+
).each do |value|
|
15
|
+
context "with value: #{value.inspect}" do
|
16
|
+
let(:value) { value }
|
17
|
+
it { should be_true }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
%w(
|
22
|
+
bcxxx
|
23
|
+
xxxac
|
24
|
+
xxxabxxx
|
25
|
+
).each do |value|
|
26
|
+
context "with value: #{value.inspect}" do
|
27
|
+
let(:value) { value }
|
28
|
+
it { should be_false }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Format, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, /abc/) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, format: /abc/ }) }
|
12
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Inclusion, '.new' do
|
6
|
+
subject { described_class.new(attribute, within) }
|
7
|
+
|
8
|
+
let(:attribute) { :foo }
|
9
|
+
let(:within) { 3..5 }
|
10
|
+
let(:options) { { message: 'message' } }
|
11
|
+
|
12
|
+
context 'with options' do
|
13
|
+
subject { described_class.new(attribute, within, options) }
|
14
|
+
|
15
|
+
it { should be_instance_of(described_class) }
|
16
|
+
its(:attribute_name) { should eql(attribute) }
|
17
|
+
its(:within) { should eql(within) }
|
18
|
+
its(:options) { should eql(options) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with no options' do
|
22
|
+
subject { described_class.new(attribute, within) }
|
23
|
+
|
24
|
+
it { should be_instance_of(described_class) }
|
25
|
+
its(:options) { should be_empty }
|
26
|
+
its(:message) { should eql('%{attribute} is not included in the list') }
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Inclusion, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, within) }
|
9
|
+
|
10
|
+
context 'Array' do
|
11
|
+
let(:within) { [1, 2, 3] }
|
12
|
+
|
13
|
+
describe 'matched' do
|
14
|
+
let(:value) { 5 }
|
15
|
+
it { should be_false }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'not matched' do
|
19
|
+
let(:value) { 3 }
|
20
|
+
it { should be_true }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'Range' do
|
25
|
+
let(:within) { 1..3 }
|
26
|
+
|
27
|
+
describe 'matched' do
|
28
|
+
let(:value) { 5 }
|
29
|
+
it { should be_false }
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'not matched' do
|
33
|
+
let(:value) { 2 }
|
34
|
+
it { should be_true }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'cover? vs include?' do
|
39
|
+
let(:within) { double('within') }
|
40
|
+
let(:value) { 5 }
|
41
|
+
|
42
|
+
it 'send cover?' do
|
43
|
+
within.stub(:kind_of?).and_return(true)
|
44
|
+
within.should_receive(:cover?).with(value).and_return(false)
|
45
|
+
should be_false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Inclusion, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, [2, 4]) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, within: [2, 4] }) }
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MaximumLength, '.new' do
|
6
|
+
|
7
|
+
let(:attribute) { :foo }
|
8
|
+
let(:maximum) { 3 }
|
9
|
+
let(:options) { { message: 'message' } }
|
10
|
+
|
11
|
+
context 'with options' do
|
12
|
+
subject { described_class.new(attribute, maximum, options) }
|
13
|
+
|
14
|
+
it { should be_instance_of(described_class) }
|
15
|
+
its(:attribute_name) { should eql(attribute) }
|
16
|
+
its(:maximum) { should eql(maximum) }
|
17
|
+
its(:options) { should eql(options) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with no options' do
|
21
|
+
subject { described_class.new(attribute, maximum) }
|
22
|
+
|
23
|
+
it { should be_instance_of(described_class) }
|
24
|
+
its(:options) { should be_empty }
|
25
|
+
its(:message) { should eql('%{attribute} is too long') }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MaximumLength, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, 3) }
|
9
|
+
|
10
|
+
%w(ab abc).each do |value|
|
11
|
+
context "with value: #{value.inspect}" do
|
12
|
+
let(:value) { value }
|
13
|
+
it { should be_true }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'longer' do
|
18
|
+
let(:value) { 'abcd' }
|
19
|
+
it { should be_false }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MaximumLength, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, 20) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, maximum: 20 }) }
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MinimumLength, '.new' do
|
6
|
+
|
7
|
+
let(:attribute) { :foo }
|
8
|
+
let(:minimum) { 3 }
|
9
|
+
let(:options) { { message: 'message' } }
|
10
|
+
|
11
|
+
context 'with options' do
|
12
|
+
subject { described_class.new(attribute, minimum, options) }
|
13
|
+
|
14
|
+
it { should be_instance_of(described_class) }
|
15
|
+
its(:attribute_name) { should eql(attribute) }
|
16
|
+
its(:minimum) { should eql(minimum) }
|
17
|
+
its(:options) { should eql(options) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with no options' do
|
21
|
+
subject { described_class.new(attribute, minimum) }
|
22
|
+
|
23
|
+
it { should be_instance_of(described_class) }
|
24
|
+
its(:options) { should be_empty }
|
25
|
+
its(:message) { should eql('%{attribute} is too short') }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MinimumLength, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, 3) }
|
9
|
+
|
10
|
+
%w(abc abcd).each do |value|
|
11
|
+
context "with value: #{value.inspect}" do
|
12
|
+
let(:value) { value }
|
13
|
+
it { should be_true }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'shorter' do
|
18
|
+
let(:value) { 'ab' }
|
19
|
+
it { should be_false }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::MinimumLength, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, 4) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, minimum: 4 }) }
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::Presence, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo) }
|
9
|
+
|
10
|
+
[
|
11
|
+
nil,
|
12
|
+
'',
|
13
|
+
{},
|
14
|
+
[],
|
15
|
+
Set.new,
|
16
|
+
].each do |value|
|
17
|
+
context "with value: #{value.inspect}" do
|
18
|
+
let(:value) { value }
|
19
|
+
it { should be_false }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when the value is a string' do
|
24
|
+
let(:value) { 'bar' }
|
25
|
+
it { should be_true }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::RangeLength, '.new' do
|
6
|
+
|
7
|
+
let(:attribute) { :foo }
|
8
|
+
let(:range) { 3..4 }
|
9
|
+
let(:options) { { message: 'message' } }
|
10
|
+
|
11
|
+
context 'with options' do
|
12
|
+
subject { described_class.new(attribute, range, options) }
|
13
|
+
|
14
|
+
it { should be_instance_of(described_class) }
|
15
|
+
its(:attribute_name) { should eql(attribute) }
|
16
|
+
its(:range) { should eql(range) }
|
17
|
+
its(:options) { should eql(options) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with no options' do
|
21
|
+
subject { described_class.new(attribute, range) }
|
22
|
+
|
23
|
+
it { should be_instance_of(described_class) }
|
24
|
+
its(:options) { should be_empty }
|
25
|
+
its(:message) { should eql('%{attribute} has an invalid length') }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::RangeLength, '#matches?' do
|
6
|
+
subject { rule.matches?(value) }
|
7
|
+
|
8
|
+
let(:rule) { described_class.new(:foo, 3..5) }
|
9
|
+
let(:value) { 'abc' }
|
10
|
+
|
11
|
+
it { should be_true }
|
12
|
+
|
13
|
+
%w(ab abcdef).each do |value|
|
14
|
+
context "with value: #{value.inspect}" do
|
15
|
+
let(:value) { value }
|
16
|
+
it { should be_false }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule::RangeLength, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:object) { described_class.new(:foo, (4...6)) }
|
9
|
+
|
10
|
+
it { should be_frozen }
|
11
|
+
it { should eql({ attribute: :foo, minimum: 4, maximum: 5 }) }
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Rule, '#to_hash' do
|
6
|
+
subject { object.to_hash }
|
7
|
+
|
8
|
+
let(:described_class) { Class.new(Rule) }
|
9
|
+
let(:object) { described_class.new(:foo) }
|
10
|
+
|
11
|
+
it { should be_frozen }
|
12
|
+
it { should eql({ attribute: :foo }) }
|
13
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Validator, '#add' do
|
6
|
+
subject { validator.rules(context) }
|
7
|
+
|
8
|
+
let(:validator) { described_class.new(rule1) }
|
9
|
+
let(:rule1) { Rule::ExactLength.new(:username, 10) }
|
10
|
+
let(:rule2) { Rule::Presence.new(:username) }
|
11
|
+
|
12
|
+
before do
|
13
|
+
validator.add(rule2, :register)
|
14
|
+
validator.add(rule2)
|
15
|
+
validator.add(nil)
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'default_context' do
|
19
|
+
let(:context) { :default }
|
20
|
+
specify { expect(subject.size).to eql(2) }
|
21
|
+
specify { expect(subject).to eql(Set.new([rule1, rule2])) }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'register' do
|
25
|
+
let(:context) { :register }
|
26
|
+
specify { expect(subject.size).to eql(1) }
|
27
|
+
specify { expect(subject).to eql(Set.new([rule2])) }
|
28
|
+
end
|
29
|
+
end
|