objective 0.3.0 → 0.4.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.
- checksums.yaml +4 -4
- data/lib/objective.rb +10 -12
- data/lib/objective/errors/error_array.rb +4 -1
- data/lib/objective/errors/error_atom.rb +1 -1
- data/lib/objective/errors/error_hash.rb +5 -5
- data/lib/objective/errors/error_message_creator.rb +20 -2
- data/lib/objective/filter.rb +4 -9
- data/lib/objective/filters/array_filter.rb +2 -2
- data/lib/objective/filters/decimal_filter.rb +5 -2
- data/lib/objective/filters/duck_filter.rb +1 -1
- data/lib/objective/filters/float_filter.rb +5 -1
- data/lib/objective/filters/hash_filter.rb +2 -6
- data/lib/objective/filters/integer_filter.rb +4 -1
- data/lib/objective/filters/model_filter.rb +4 -4
- data/lib/objective/filters/root_filter.rb +2 -2
- data/lib/objective/filters/string_filter.rb +1 -1
- data/lib/objective/helpers.rb +43 -0
- data/lib/objective/unit.rb +21 -36
- data/test/default_test.rb +5 -5
- data/test/inheritance_test.rb +4 -4
- data/test/objective/errors/errors_test.rb +19 -24
- data/test/objective/filters/array_filter_test.rb +6 -6
- data/test/objective/filters/hash_filter_test.rb +4 -4
- data/test/objective/filters/model_filter_test.rb +8 -0
- data/test/objective/filters/root_filter_test.rb +4 -4
- data/test/unit_test.rb +11 -18
- metadata +5 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72b1cd84872138d986c27917ddde80b4a6267da6
|
4
|
+
data.tar.gz: 3959aa006a2b9d4f732a3ecd83cb91bef4b15d72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b6b54295d84ad221cdba86531ea945255881e4a636429b1311aa952da8f52996b495f51ef9c709284b02bac8279e8e4a3f70d926ca1cb9d8fb4b235501e55c6
|
7
|
+
data.tar.gz: b09ee8a3750bf3294c85f60df26a06d868650357cbf8eeed712216d9b2c078522c52b2a44e275550d2eff1bcba6df3d432e215c98c07a13e026db43ef017ae87
|
data/lib/objective.rb
CHANGED
@@ -6,20 +6,11 @@ require 'time'
|
|
6
6
|
require 'bigdecimal'
|
7
7
|
require 'bigdecimal/util'
|
8
8
|
|
9
|
-
require 'active_support/concern'
|
10
|
-
require 'active_support/core_ext/module/attribute_accessors'
|
11
|
-
require 'active_support/core_ext/object/try'
|
12
|
-
require 'active_support/core_ext/object/blank'
|
13
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
14
|
-
require 'active_support/core_ext/hash/deep_merge'
|
15
|
-
require 'active_support/core_ext/array/wrap'
|
16
|
-
require 'active_support/core_ext/string/filters'
|
17
|
-
require 'active_support/core_ext/string/inflections'
|
18
|
-
require 'active_support/core_ext/integer/inflections'
|
19
|
-
|
20
9
|
require 'objective/allow'
|
21
10
|
require 'objective/deny'
|
22
11
|
|
12
|
+
require 'objective/helpers'
|
13
|
+
|
23
14
|
require 'objective/errors/error_atom'
|
24
15
|
require 'objective/errors/error_hash'
|
25
16
|
require 'objective/errors/error_array'
|
@@ -46,6 +37,13 @@ require 'objective/unit'
|
|
46
37
|
require 'objective/outcome'
|
47
38
|
|
48
39
|
module Objective
|
49
|
-
|
40
|
+
def self.error_message_creator
|
41
|
+
@@error_message_creator
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.error_message_creator=(obj)
|
45
|
+
@@error_message_creator = obj
|
46
|
+
end
|
47
|
+
|
50
48
|
self.error_message_creator = Errors::ErrorMessageCreator.new
|
51
49
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Objective
|
4
4
|
module Errors
|
5
|
-
class ErrorHash <
|
5
|
+
class ErrorHash < Hash
|
6
6
|
# objective.errors is an ErrorHash instance like this:
|
7
7
|
# {
|
8
8
|
# email: ErrorAtom(:matches),
|
@@ -13,7 +13,7 @@ module Objective
|
|
13
13
|
# }
|
14
14
|
# }
|
15
15
|
|
16
|
-
# Returns a nested
|
16
|
+
# Returns a nested Hash where the values are symbols. Eg:
|
17
17
|
# {
|
18
18
|
# email: :matches,
|
19
19
|
# name: :too_weird,
|
@@ -23,14 +23,14 @@ module Objective
|
|
23
23
|
# }
|
24
24
|
# }
|
25
25
|
def codes
|
26
|
-
|
26
|
+
{}.tap do |hash|
|
27
27
|
each do |k, v|
|
28
28
|
hash[k] = v.codes
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
# Returns a nested
|
33
|
+
# Returns a nested Hash where the values are messages. Eg:
|
34
34
|
# {
|
35
35
|
# email: "isn't in the right format",
|
36
36
|
# name: "is too weird",
|
@@ -40,7 +40,7 @@ module Objective
|
|
40
40
|
# }
|
41
41
|
# }
|
42
42
|
def message(_parent_key = nil, _index = nil)
|
43
|
-
|
43
|
+
{}.tap do |hash|
|
44
44
|
each do |k, v|
|
45
45
|
hash[k] = v.message(k)
|
46
46
|
end
|
@@ -28,7 +28,7 @@ module Objective
|
|
28
28
|
def message(atom, parent_key, index)
|
29
29
|
[
|
30
30
|
index_ordinal(index),
|
31
|
-
(atom.key || parent_key || 'item').to_s
|
31
|
+
(atom.key || parent_key || 'item').to_s,
|
32
32
|
MESSAGES[atom.codes]
|
33
33
|
]
|
34
34
|
.compact
|
@@ -37,7 +37,25 @@ module Objective
|
|
37
37
|
|
38
38
|
def index_ordinal(index)
|
39
39
|
return if index.nil?
|
40
|
-
(index
|
40
|
+
ordinalize_index(index)
|
41
|
+
end
|
42
|
+
|
43
|
+
def ordinalize_index(index)
|
44
|
+
number = index + 1
|
45
|
+
|
46
|
+
ordinal =
|
47
|
+
if (11..13).cover?(number % 100)
|
48
|
+
'th'
|
49
|
+
else
|
50
|
+
case number % 10
|
51
|
+
when 1 then 'st'
|
52
|
+
when 2 then 'nd'
|
53
|
+
when 3 then 'rd'
|
54
|
+
else 'th'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
"#{number}#{ordinal}"
|
41
59
|
end
|
42
60
|
end
|
43
61
|
end
|
data/lib/objective/filter.rb
CHANGED
@@ -3,22 +3,17 @@
|
|
3
3
|
module Objective
|
4
4
|
class Filter
|
5
5
|
def self.inherited(child_class)
|
6
|
-
|
6
|
+
filter_match = child_class.name.match(/\AObjective::Filters::(.*)Filter\z/)
|
7
|
+
raise "invalid class name for filter: #{child_class.name}" unless filter_match
|
8
|
+
filter_name = filter_match[1].gsub(/(.)([A-Z])/, '\1_\2').downcase
|
7
9
|
|
8
|
-
define_method(
|
10
|
+
define_method(filter_name) do |*args, &block|
|
9
11
|
args.unshift(nil) if args[0].is_a?(Hash)
|
10
12
|
new_filter = child_class.new(*args, &block)
|
11
13
|
sub_filters.push(new_filter)
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
|
-
def self.filter_name(klass = self)
|
16
|
-
filter_match = klass.name.match(/\AObjective::Filters::(.*)Filter\z/)
|
17
|
-
filter_name = filter_match ? filter_match[1].try(:underscore) : nil
|
18
|
-
raise 'filename error in filters folder' unless filter_name
|
19
|
-
filter_name
|
20
|
-
end
|
21
|
-
|
22
17
|
attr_reader :key
|
23
18
|
attr_reader :sub_filters
|
24
19
|
|
@@ -35,12 +35,12 @@ module Objective
|
|
35
35
|
end
|
36
36
|
|
37
37
|
result.inputs = inputs
|
38
|
-
result.errors = errors.
|
38
|
+
result.errors = errors.empty? ? nil : errors
|
39
39
|
result
|
40
40
|
end
|
41
41
|
|
42
42
|
def coerce(raw)
|
43
|
-
return
|
43
|
+
return Objective::Helpers.wrap(raw) if options.wrap
|
44
44
|
raw
|
45
45
|
end
|
46
46
|
|
@@ -16,13 +16,16 @@ module Objective
|
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
-
# TODO: the Rational class should be coerced - it requires a precision argument
|
20
19
|
def coerce(datum)
|
21
|
-
|
20
|
+
if datum.is_a?(String)
|
21
|
+
datum = datum.strip
|
22
|
+
return datum if datum.empty?
|
23
|
+
end
|
22
24
|
|
23
25
|
return datum.to_d if datum.is_a?(Integer) || datum.is_a?(Float)
|
24
26
|
|
25
27
|
return datum unless datum.is_a?(String)
|
28
|
+
datum = datum.strip
|
26
29
|
return datum if options.decimal_mark != '.' && !options.delimiter.include?('.') && datum.include?('.')
|
27
30
|
|
28
31
|
clean_str = datum.tr(options.delimiter, '').tr(options.decimal_mark, '.')
|
@@ -17,11 +17,15 @@ module Objective
|
|
17
17
|
private
|
18
18
|
|
19
19
|
def coerce(datum)
|
20
|
-
|
20
|
+
if datum.is_a?(String)
|
21
|
+
datum = datum.strip
|
22
|
+
return datum if datum.empty?
|
23
|
+
end
|
21
24
|
|
22
25
|
return datum.to_f if datum.is_a?(Integer) || datum.is_a?(BigDecimal)
|
23
26
|
|
24
27
|
return datum unless datum.is_a?(String)
|
28
|
+
datum = datum.strip
|
25
29
|
return datum if options.decimal_mark != '.' && !options.delimiter.include?('.') && datum.include?('.')
|
26
30
|
|
27
31
|
clean_str = datum.tr(options.delimiter, '').tr(options.decimal_mark, '.')
|
@@ -14,7 +14,7 @@ module Objective
|
|
14
14
|
return result if result.errors || result.inputs.nil?
|
15
15
|
|
16
16
|
errors = Objective::Errors::ErrorHash.new
|
17
|
-
inputs =
|
17
|
+
inputs = {}
|
18
18
|
|
19
19
|
data = result.coerced
|
20
20
|
sub_filters_hash.each_pair do |key, key_filter|
|
@@ -32,14 +32,10 @@ module Objective
|
|
32
32
|
end
|
33
33
|
|
34
34
|
result.inputs = inputs
|
35
|
-
result.errors = errors.
|
35
|
+
result.errors = errors.empty? ? nil : errors
|
36
36
|
result
|
37
37
|
end
|
38
38
|
|
39
|
-
def coerce(raw)
|
40
|
-
raw.try(:with_indifferent_access)
|
41
|
-
end
|
42
|
-
|
43
39
|
def coerce_error(coerced)
|
44
40
|
return :hash unless coerced.is_a?(Hash)
|
45
41
|
end
|
@@ -22,10 +22,10 @@ module Objective
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def class_constant
|
25
|
-
|
26
|
-
|
27
|
-
return
|
28
|
-
|
25
|
+
class_name = options[:class] || key.to_s.split('_').collect(&:capitalize).join
|
26
|
+
|
27
|
+
return class_name if class_name.instance_of? Class
|
28
|
+
Objective::Helpers.constantize(class_name.to_s)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -18,7 +18,7 @@ module Objective
|
|
18
18
|
result.raw = raw
|
19
19
|
result.coerced = coerce(raw)
|
20
20
|
|
21
|
-
inputs =
|
21
|
+
inputs = {}
|
22
22
|
errors = Objective::Errors::ErrorHash.new
|
23
23
|
|
24
24
|
data = result.coerced
|
@@ -37,7 +37,7 @@ module Objective
|
|
37
37
|
end
|
38
38
|
|
39
39
|
result.inputs = inputs
|
40
|
-
result.errors = errors.
|
40
|
+
result.errors = errors.empty? ? nil : errors
|
41
41
|
result
|
42
42
|
end
|
43
43
|
|
@@ -20,7 +20,7 @@ module Objective
|
|
20
20
|
def coerce(raw)
|
21
21
|
return raw unless raw.is_a?(String) || coercable?(raw)
|
22
22
|
tmp = raw.is_a?(BigDecimal) ? raw.to_s(options.decimal_format) : raw.to_s
|
23
|
-
tmp = tmp.
|
23
|
+
tmp = tmp.gsub(/[[:space:]]+/, ' ').strip if options.squish
|
24
24
|
tmp
|
25
25
|
end
|
26
26
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Objective
|
4
|
+
module Helpers
|
5
|
+
# copied from activesupport
|
6
|
+
# https://github.com/rails/rails/blob/v5.1.1/activesupport/lib/active_support/core_ext/array/wrap.rb
|
7
|
+
def self.wrap(obj)
|
8
|
+
if obj.nil?
|
9
|
+
[]
|
10
|
+
elsif obj.respond_to?(:to_ary)
|
11
|
+
obj.to_ary || [obj]
|
12
|
+
else
|
13
|
+
[obj]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# copied from activesupport
|
18
|
+
# https://github.com/rails/rails/blob/v5.1.1/activesupport/lib/active_support/inflector/methods.rb
|
19
|
+
def self.constantize(camel_cased_word)
|
20
|
+
names = camel_cased_word.split('::'.freeze)
|
21
|
+
Object.const_get(camel_cased_word) if names.empty?
|
22
|
+
names.shift if names.size > 1 && names.first.empty?
|
23
|
+
|
24
|
+
names.inject(Object) do |constant, name|
|
25
|
+
if constant == Object
|
26
|
+
constant.const_get(name)
|
27
|
+
else
|
28
|
+
candidate = constant.const_get(name)
|
29
|
+
next candidate if constant.const_defined?(name, false)
|
30
|
+
next candidate unless Object.const_defined?(name)
|
31
|
+
|
32
|
+
constant = constant.ancestors.inject(constant) do |const, ancestor|
|
33
|
+
break const if ancestor == Object
|
34
|
+
break ancestor if ancestor.const_defined?(name, false)
|
35
|
+
const
|
36
|
+
end
|
37
|
+
|
38
|
+
constant.const_get(name, false)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/objective/unit.rb
CHANGED
@@ -2,15 +2,16 @@
|
|
2
2
|
|
3
3
|
module Objective
|
4
4
|
module Unit
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
base.class_eval do
|
8
|
+
attr_reader :inputs, :raw_inputs
|
9
|
+
const_set('ALLOW', Objective::ALLOW)
|
10
|
+
const_set('DENY', Objective::DENY)
|
11
|
+
end
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
+
module ClassMethods
|
14
15
|
def filter(&block)
|
15
16
|
root_filter.filter(&block)
|
16
17
|
root_filter.keys.each do |key|
|
@@ -20,18 +21,11 @@ module Objective
|
|
20
21
|
|
21
22
|
def root_filter
|
22
23
|
@root_filter ||=
|
23
|
-
superclass.
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
new.build(*args)
|
29
|
-
end
|
30
|
-
|
31
|
-
def build!(*args)
|
32
|
-
outcome = build(*args)
|
33
|
-
return outcome.result if outcome.success
|
34
|
-
raise Objective::ValidationError, outcome.errors
|
24
|
+
if superclass.respond_to?(:root_filter)
|
25
|
+
superclass.root_filter.dup
|
26
|
+
else
|
27
|
+
Objective::Filters::RootFilter.new
|
28
|
+
end
|
35
29
|
end
|
36
30
|
|
37
31
|
def run(*args)
|
@@ -47,27 +41,14 @@ module Objective
|
|
47
41
|
|
48
42
|
# INSTANCE METHODS
|
49
43
|
|
50
|
-
def
|
44
|
+
def run(*args)
|
51
45
|
filter_result = self.class.root_filter.feed(*args)
|
52
46
|
@raw_inputs = filter_result.coerced
|
53
47
|
@inputs = filter_result.inputs
|
54
48
|
@errors = filter_result.errors
|
55
|
-
|
56
|
-
|
57
|
-
outcome
|
58
|
-
end
|
49
|
+
validate if respond_to?(:validate) && valid?
|
50
|
+
result = valid? && respond_to?(:execute) ? execute : nil
|
59
51
|
|
60
|
-
def run(*args)
|
61
|
-
build(*args) unless built
|
62
|
-
result = valid? ? try('execute') : nil
|
63
|
-
outcome(result)
|
64
|
-
end
|
65
|
-
|
66
|
-
def valid?
|
67
|
-
@errors.nil?
|
68
|
-
end
|
69
|
-
|
70
|
-
def outcome(result = nil)
|
71
52
|
Objective::Outcome.new(
|
72
53
|
success: valid?,
|
73
54
|
result: result,
|
@@ -76,6 +57,10 @@ module Objective
|
|
76
57
|
)
|
77
58
|
end
|
78
59
|
|
60
|
+
def valid?
|
61
|
+
@errors.nil?
|
62
|
+
end
|
63
|
+
|
79
64
|
protected
|
80
65
|
|
81
66
|
def add_error(key, kind, message = nil)
|
@@ -83,7 +68,7 @@ module Objective
|
|
83
68
|
|
84
69
|
@errors ||= Objective::Errors::ErrorHash.new
|
85
70
|
@errors.tap do |root_error_hash|
|
86
|
-
path =
|
71
|
+
path = Objective::Helpers.wrap(key)
|
87
72
|
last = path.pop
|
88
73
|
|
89
74
|
inner = path.inject(root_error_hash) do |current_error_hash, path_key|
|
data/test/default_test.rb
CHANGED
@@ -19,30 +19,30 @@ describe 'Objective - defaults' do
|
|
19
19
|
it 'should use a valid value passed to it' do
|
20
20
|
outcome = DefaultUnit.run(name: 'Fred')
|
21
21
|
assert_equal true, outcome.success
|
22
|
-
assert_equal({
|
22
|
+
assert_equal({ name: 'Fred' }, outcome.result)
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'should use a nils option default value if no value is passed' do
|
26
26
|
outcome = DefaultUnit.run
|
27
|
-
assert_equal({
|
27
|
+
assert_equal({ name: '-nils-' }, outcome.result)
|
28
28
|
assert_equal true, outcome.success
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'should use a nils option default value if nil is passed' do
|
32
32
|
outcome = DefaultUnit.run(name: nil)
|
33
|
-
assert_equal({
|
33
|
+
assert_equal({ name: '-nils-' }, outcome.result)
|
34
34
|
assert_equal true, outcome.success
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'should use the invalid option default if an invalid value is passed' do
|
38
38
|
outcome = DefaultUnit.run(name: /regex/)
|
39
|
-
assert_equal({
|
39
|
+
assert_equal({ name: '-invalid-' }, outcome.result)
|
40
40
|
assert_equal true, outcome.success
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'should use the empty option default if an empty value is passed' do
|
44
44
|
outcome = DefaultUnit.run(name: ' ')
|
45
|
-
assert_equal({
|
45
|
+
assert_equal({ name: '-empty-' }, outcome.result)
|
46
46
|
assert_equal true, outcome.success
|
47
47
|
end
|
48
48
|
end
|
data/test/inheritance_test.rb
CHANGED
@@ -16,22 +16,22 @@ describe 'Objective - inheritance' do
|
|
16
16
|
it 'should filter with inherited unit' do
|
17
17
|
outcome = SimpleInherited.run(name: 'bob', email: 'jon@jones.com', age: 10, amount: 22)
|
18
18
|
assert outcome.success
|
19
|
-
assert_equal({
|
19
|
+
assert_equal({ name: 'bob', email: 'jon@jones.com', age: 10, amount: 22 }, outcome.inputs)
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'should filter with original unit' do
|
23
23
|
outcome = SimpleUnit.run(name: 'bob', email: 'jon@jones.com', age: 10, amount: 22)
|
24
24
|
assert outcome.success
|
25
|
-
assert_equal({
|
25
|
+
assert_equal({ name: 'bob', email: 'jon@jones.com', amount: 22 }, outcome.inputs)
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'shouldnt collide' do
|
29
29
|
outcome = SimpleInherited.run(name: 'bob', email: 'jon@jones.com', age: 10, amount: 22)
|
30
30
|
assert outcome.success
|
31
|
-
assert_equal({
|
31
|
+
assert_equal({ name: 'bob', email: 'jon@jones.com', age: 10, amount: 22 }, outcome.inputs)
|
32
32
|
|
33
33
|
outcome = SimpleUnit.run(name: 'bob', email: 'jon@jones.com', age: 10, amount: 22)
|
34
34
|
assert outcome.success
|
35
|
-
assert_equal({
|
35
|
+
assert_equal({ name: 'bob', email: 'jon@jones.com', amount: 22 }, outcome.inputs)
|
36
36
|
end
|
37
37
|
end
|
@@ -57,11 +57,6 @@ describe 'Objective - errors' do
|
|
57
57
|
assert o.errors[:arr1][2].is_a?(Objective::Errors::ErrorAtom)
|
58
58
|
end
|
59
59
|
|
60
|
-
it 'titleizes keys' do
|
61
|
-
atom = Objective::Errors::ErrorAtom.new(:newsletter_subscription, :boolean)
|
62
|
-
assert_equal 'Newsletter Subscription must be a boolean', atom.message
|
63
|
-
end
|
64
|
-
|
65
60
|
describe 'Bunch o errors' do
|
66
61
|
before do
|
67
62
|
@outcome = GivesErrors.run(
|
@@ -71,11 +66,11 @@ describe 'Objective - errors' do
|
|
71
66
|
|
72
67
|
it 'gives coded errors' do
|
73
68
|
expected = {
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
69
|
+
str1: :empty,
|
70
|
+
str2: :in,
|
71
|
+
int1: :integer,
|
72
|
+
hash1: { bool1: :boolean, bool2: :nils },
|
73
|
+
arr1: [:integer, nil, :integer]
|
79
74
|
}
|
80
75
|
|
81
76
|
assert_equal expected, @outcome.errors.codes
|
@@ -83,14 +78,14 @@ describe 'Objective - errors' do
|
|
83
78
|
|
84
79
|
it 'gives messages' do
|
85
80
|
expected = {
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
81
|
+
str1: 'str1 cannot be empty',
|
82
|
+
str2: 'str2 is not an available option',
|
83
|
+
int1: 'int1 must be an integer',
|
84
|
+
hash1: {
|
85
|
+
bool1: 'bool1 must be a boolean',
|
86
|
+
bool2: 'bool2 cannot be nil'
|
92
87
|
},
|
93
|
-
|
88
|
+
arr1: ['1st arr1 must be an integer', nil, '3rd arr1 must be an integer']
|
94
89
|
}
|
95
90
|
|
96
91
|
assert_equal expected, @outcome.errors.message
|
@@ -98,13 +93,13 @@ describe 'Objective - errors' do
|
|
98
93
|
|
99
94
|
it 'can flatten those messages' do
|
100
95
|
expected = [
|
101
|
-
'
|
102
|
-
'
|
103
|
-
'
|
104
|
-
'
|
105
|
-
'
|
106
|
-
'1st
|
107
|
-
'3rd
|
96
|
+
'str1 cannot be empty',
|
97
|
+
'str2 is not an available option',
|
98
|
+
'int1 must be an integer',
|
99
|
+
'bool1 must be a boolean',
|
100
|
+
'bool2 cannot be nil',
|
101
|
+
'1st arr1 must be an integer',
|
102
|
+
'3rd arr1 must be an integer'
|
108
103
|
]
|
109
104
|
|
110
105
|
assert_equal expected, @outcome.errors.message_list
|
@@ -140,15 +140,15 @@ describe 'Objective::Filters::ArrayFilter' do
|
|
140
140
|
]
|
141
141
|
)
|
142
142
|
expected_result = [
|
143
|
-
{
|
144
|
-
{
|
145
|
-
{
|
143
|
+
{ foo: 'f', bar: 3, baz: true },
|
144
|
+
{ foo: 'f', bar: 3, baz: nil },
|
145
|
+
{ foo: 'f', baz: nil }
|
146
146
|
]
|
147
147
|
|
148
148
|
assert_equal expected_result, result.inputs
|
149
149
|
assert_nil result.errors[0]
|
150
150
|
assert_nil result.errors[1]
|
151
|
-
assert_equal
|
151
|
+
assert_equal({ bar: :nils }, result.errors[2].codes)
|
152
152
|
end
|
153
153
|
|
154
154
|
it 'lets you pass arrays of arrays' do
|
@@ -171,8 +171,8 @@ describe 'Objective::Filters::ArrayFilter' do
|
|
171
171
|
end
|
172
172
|
|
173
173
|
result = f.feed([['h', 'e', {}], ['l'], [], ['']])
|
174
|
-
err_message_empty = '1st
|
175
|
-
err_message_string = '3rd
|
174
|
+
err_message_empty = '1st item cannot be empty'
|
175
|
+
err_message_string = '3rd item must be a string'
|
176
176
|
|
177
177
|
assert_equal [[nil, nil, :string], nil, nil, [:empty]], result.errors.codes
|
178
178
|
assert_equal [[nil, nil, err_message_string], nil, nil, [err_message_empty]], result.errors.message
|
@@ -10,7 +10,7 @@ describe 'Objective::Filters::HashFilter' do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
result = hf.feed(foo: 'bar')
|
13
|
-
assert_equal ({
|
13
|
+
assert_equal ({ foo: 'bar' }), result.inputs
|
14
14
|
assert_nil result.errors
|
15
15
|
end
|
16
16
|
|
@@ -29,7 +29,7 @@ describe 'Objective::Filters::HashFilter' do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
result = hf.feed(foo: 3.14)
|
32
|
-
assert_equal ({
|
32
|
+
assert_equal ({ foo: 3.14 }), result.inputs
|
33
33
|
assert_nil result.errors
|
34
34
|
end
|
35
35
|
|
@@ -39,7 +39,7 @@ describe 'Objective::Filters::HashFilter' do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
result = hf.feed(foo: '123')
|
42
|
-
assert_equal ({
|
42
|
+
assert_equal ({ foo: '123' }), result.inputs
|
43
43
|
assert_nil result.errors
|
44
44
|
end
|
45
45
|
|
@@ -60,7 +60,7 @@ describe 'Objective::Filters::HashFilter' do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
result = hf.feed(foo: sio)
|
63
|
-
assert_equal ({
|
63
|
+
assert_equal ({ foo: sio }), result.inputs
|
64
64
|
assert_nil result.errors
|
65
65
|
end
|
66
66
|
end
|
@@ -24,6 +24,14 @@ describe 'Objective::Filters::ModelFilter' do
|
|
24
24
|
assert_nil result.errors
|
25
25
|
end
|
26
26
|
|
27
|
+
it 'allows class option' do
|
28
|
+
f = Objective::Filters::ModelFilter.new(:my_model, class: 'SimpleModel')
|
29
|
+
m = SimpleModel.new
|
30
|
+
result = f.feed(m)
|
31
|
+
assert_equal m, result.inputs
|
32
|
+
assert_nil result.errors
|
33
|
+
end
|
34
|
+
|
27
35
|
it 'raises an exception during filtering if constantization fails' do
|
28
36
|
f = Objective::Filters::ModelFilter.new(:non_existent_class)
|
29
37
|
|
@@ -51,7 +51,7 @@ describe 'Objective::Filters::RootFilter' do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
result = f.feed(foo: 'oof', bar: nil)
|
54
|
-
assert_equal({
|
54
|
+
assert_equal({ foo: 'oof', bar: nil }, result.inputs)
|
55
55
|
assert_nil result.errors
|
56
56
|
end
|
57
57
|
|
@@ -64,7 +64,7 @@ describe 'Objective::Filters::RootFilter' do
|
|
64
64
|
end
|
65
65
|
|
66
66
|
result = f.feed(foo: 'oof')
|
67
|
-
assert_equal({
|
67
|
+
assert_equal({ foo: 'oof', bar: nil }, result.inputs)
|
68
68
|
assert_nil result.errors
|
69
69
|
end
|
70
70
|
end
|
@@ -79,7 +79,7 @@ describe 'Objective::Filters::RootFilter' do
|
|
79
79
|
end
|
80
80
|
|
81
81
|
result = f.feed(foo: 'bar', bar: '')
|
82
|
-
assert_equal({
|
82
|
+
assert_equal({ foo: 'bar', bar: '' }, result.inputs)
|
83
83
|
assert_nil result.errors
|
84
84
|
end
|
85
85
|
|
@@ -92,7 +92,7 @@ describe 'Objective::Filters::RootFilter' do
|
|
92
92
|
end
|
93
93
|
|
94
94
|
result = f.feed(foo: 'bar', bar: '')
|
95
|
-
assert_equal({
|
95
|
+
assert_equal({ foo: 'bar', bar: '' }, result.inputs)
|
96
96
|
assert_nil result.errors
|
97
97
|
end
|
98
98
|
end
|
data/test/unit_test.rb
CHANGED
@@ -9,7 +9,7 @@ describe 'Unit' do
|
|
9
9
|
outcome = SimpleUnit.run(name: 'John', email: 'john@gmail.com', amount: 5)
|
10
10
|
|
11
11
|
assert outcome.success
|
12
|
-
assert_equal({
|
12
|
+
assert_equal({ name: 'John', email: 'john@gmail.com', amount: 5 }, outcome.inputs)
|
13
13
|
assert_nil outcome.errors
|
14
14
|
end
|
15
15
|
|
@@ -17,7 +17,7 @@ describe 'Unit' do
|
|
17
17
|
outcome = SimpleUnit.run(name: 'John', email: 'john@gmail.com', amount: 5, buggers: true)
|
18
18
|
|
19
19
|
assert outcome.success
|
20
|
-
assert_equal({
|
20
|
+
assert_equal({ name: 'John', email: 'john@gmail.com', amount: 5 }, outcome.inputs)
|
21
21
|
assert_nil outcome.errors
|
22
22
|
end
|
23
23
|
|
@@ -40,18 +40,18 @@ describe 'Unit' do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should do standalone validation' do
|
43
|
-
outcome = SimpleUnit.
|
43
|
+
outcome = SimpleUnit.run(name: 'JohnLong', email: 'john@gmail.com')
|
44
44
|
assert outcome.success
|
45
45
|
assert_nil outcome.errors
|
46
46
|
|
47
|
-
outcome = SimpleUnit.
|
47
|
+
outcome = SimpleUnit.run(name: 'JohnTooLong', email: 'john@gmail.com')
|
48
48
|
assert !outcome.success
|
49
49
|
assert_nil outcome.result
|
50
50
|
assert_equal :max, outcome.errors.codes[:name]
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'should execute a custom validate method' do
|
54
|
-
outcome = SimpleUnit.
|
54
|
+
outcome = SimpleUnit.run(name: 'JohnLong', email: 'xxxx')
|
55
55
|
|
56
56
|
assert !outcome.success
|
57
57
|
assert_equal :invalid, outcome.errors.codes[:email]
|
@@ -66,7 +66,7 @@ describe 'Unit' do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'should execute custom validate method only if regular validations succeed' do
|
69
|
-
outcome = SimpleUnit.
|
69
|
+
outcome = SimpleUnit.run(name: 'JohnTooLong', email: 'xxxx')
|
70
70
|
|
71
71
|
assert !outcome.success
|
72
72
|
assert_equal :max, outcome.errors.codes[:name]
|
@@ -77,14 +77,7 @@ describe 'Unit' do
|
|
77
77
|
outcome = SimpleUnit.run({ name: 'John', email: 'john@gmail.com' }, email: 'bob@jones.com', amount: 5)
|
78
78
|
|
79
79
|
assert outcome.success
|
80
|
-
assert_equal({
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'should merge hashes indifferently' do
|
84
|
-
outcome = SimpleUnit.run({ name: 'John', email: 'john@gmail.com' }, 'email' => 'bob@jones.com', 'amount' => 5)
|
85
|
-
|
86
|
-
assert outcome.success
|
87
|
-
assert_equal({ 'name' => 'John', 'email' => 'bob@jones.com', 'amount' => 5 }, outcome.inputs)
|
80
|
+
assert_equal({ name: 'John', email: 'bob@jones.com', amount: 5 }, outcome.inputs)
|
88
81
|
end
|
89
82
|
|
90
83
|
it 'shouldn\'t accept non-hashes' do
|
@@ -107,7 +100,7 @@ describe 'Unit' do
|
|
107
100
|
|
108
101
|
it 'should return the filtered inputs in the outcome' do
|
109
102
|
outcome = SimpleUnit.run(name: ' John ', email: 'john@gmail.com', amount: '5')
|
110
|
-
assert_equal({
|
103
|
+
assert_equal({ name: 'John', email: 'john@gmail.com', amount: 5 }, outcome.inputs)
|
111
104
|
end
|
112
105
|
end
|
113
106
|
|
@@ -183,7 +176,7 @@ describe 'Unit' do
|
|
183
176
|
end
|
184
177
|
|
185
178
|
def execute
|
186
|
-
add_error('
|
179
|
+
add_error([:people, 'bob'], :is_a_bob)
|
187
180
|
1
|
188
181
|
end
|
189
182
|
end
|
@@ -193,7 +186,7 @@ describe 'Unit' do
|
|
193
186
|
|
194
187
|
assert !outcome.success
|
195
188
|
assert 1, outcome.result
|
196
|
-
assert :is_a_bob, outcome.errors[:people].codes[
|
189
|
+
assert :is_a_bob, outcome.errors[:people].codes['bob']
|
197
190
|
end
|
198
191
|
end
|
199
192
|
|
@@ -238,7 +231,7 @@ describe 'Unit' do
|
|
238
231
|
end
|
239
232
|
|
240
233
|
it 'should return the raw input data' do
|
241
|
-
input = {
|
234
|
+
input = { name: 'Hello World', other: 'Foo Bar Baz' }
|
242
235
|
assert_equal OpenStruct.new(input), RawInputsUnit.run!(input)
|
243
236
|
end
|
244
237
|
end
|
metadata
CHANGED
@@ -1,35 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: objective
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dallin Crane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 4.1.0
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '6.0'
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 4.1.0
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '6.0'
|
33
13
|
- !ruby/object:Gem::Dependency
|
34
14
|
name: byebug
|
35
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,6 +81,7 @@ files:
|
|
101
81
|
- lib/objective/filters/root_filter.rb
|
102
82
|
- lib/objective/filters/string_filter.rb
|
103
83
|
- lib/objective/filters/time_filter.rb
|
84
|
+
- lib/objective/helpers.rb
|
104
85
|
- lib/objective/outcome.rb
|
105
86
|
- lib/objective/unit.rb
|
106
87
|
- test/default_test.rb
|
@@ -133,9 +114,9 @@ require_paths:
|
|
133
114
|
- lib
|
134
115
|
required_ruby_version: !ruby/object:Gem::Requirement
|
135
116
|
requirements:
|
136
|
-
- - "
|
117
|
+
- - "~>"
|
137
118
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
119
|
+
version: '2.0'
|
139
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
121
|
requirements:
|
141
122
|
- - ">="
|