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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 36542ad6a5572ba8c8832cf1b1df0383516bb855
4
- data.tar.gz: 1ccb77a65a1d6feec34011ba5509862df2b3b430
3
+ metadata.gz: 72b1cd84872138d986c27917ddde80b4a6267da6
4
+ data.tar.gz: 3959aa006a2b9d4f732a3ecd83cb91bef4b15d72
5
5
  SHA512:
6
- metadata.gz: 6af1516855837c90b9bd954e8724ad7d9b8e9d4b0cd470df6e99f135208c8058f40c1334fa2743bf4fa7cd97d410049e7952564ded26128c1184979163ac244c
7
- data.tar.gz: 65f94c72d491fe8d1447b243422c9aaa3bc49a918435b02e84bdc8db0a7f4ea74a57e2ef33b124f193d1986550633a3423e2af554e21328da43ad7f726e3762a
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
- mattr_accessor :error_message_creator
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
@@ -4,7 +4,10 @@ module Objective
4
4
  module Errors
5
5
  class ErrorArray < Array
6
6
  def codes
7
- map { |e| e.try(:codes) }
7
+ map do |e|
8
+ next unless e.respond_to?(:codes)
9
+ e.codes
10
+ end
8
11
  end
9
12
 
10
13
  def message(parent_key = nil, _index = nil)
@@ -21,7 +21,7 @@ module Objective
21
21
  end
22
22
 
23
23
  def message_list(parent_key = nil, index = nil)
24
- Array.wrap(message(parent_key, index))
24
+ Objective::Helpers.wrap(message(parent_key, index))
25
25
  end
26
26
  end
27
27
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Objective
4
4
  module Errors
5
- class ErrorHash < HashWithIndifferentAccess
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 HashWithIndifferentAccess where the values are symbols. Eg:
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
- HashWithIndifferentAccess.new.tap do |hash|
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 HashWithIndifferentAccess where the values are messages. Eg:
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
- HashWithIndifferentAccess.new.tap do |hash|
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.titleize,
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 + 1).ordinalize
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
@@ -3,22 +3,17 @@
3
3
  module Objective
4
4
  class Filter
5
5
  def self.inherited(child_class)
6
- method_name = filter_name(child_class)
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(method_name) do |*args, &block|
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.present? ? errors : nil
38
+ result.errors = errors.empty? ? nil : errors
39
39
  result
40
40
  end
41
41
 
42
42
  def coerce(raw)
43
- return Array.wrap(raw) if options.wrap
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
- return datum if datum.blank?
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,7 +17,7 @@ module Objective
17
17
  end
18
18
 
19
19
  def respond_to_all?(coerced)
20
- Array.wrap(options[:methods]).map do |method|
20
+ Objective::Helpers.wrap(options[:methods]).map do |method|
21
21
  coerced.respond_to?(method)
22
22
  end.all?
23
23
  end
@@ -17,11 +17,15 @@ module Objective
17
17
  private
18
18
 
19
19
  def coerce(datum)
20
- return datum if datum.blank?
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 = HashWithIndifferentAccess.new
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.present? ? errors : nil
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
@@ -17,7 +17,10 @@ module Objective
17
17
  private
18
18
 
19
19
  def coerce(datum)
20
- return datum if datum.blank?
20
+ if datum.is_a?(String)
21
+ datum = datum.strip
22
+ return datum if datum.empty?
23
+ end
21
24
 
22
25
  datum_str = raw_to_string(datum)
23
26
  return datum unless datum_str
@@ -22,10 +22,10 @@ module Objective
22
22
  end
23
23
 
24
24
  def class_constant
25
- klass = options[:class]
26
- return key.to_s.camelize.constantize if klass.nil?
27
- return klass if klass.instance_of? Class
28
- klass.to_s.constantize
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 = HashWithIndifferentAccess.new
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.present? ? errors : nil
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.squish if options.squish
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
@@ -2,15 +2,16 @@
2
2
 
3
3
  module Objective
4
4
  module Unit
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- attr_reader :inputs, :raw_inputs, :built
9
- const_set('ALLOW', Objective::ALLOW)
10
- const_set('DENY', Objective::DENY)
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
- class_methods do
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.try(:root_filter).try(:dup) ||
24
- Objective::Filters::RootFilter.new
25
- end
26
-
27
- def build(*args)
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 build(*args)
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
- @built = true
56
- try('validate') if valid?
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 = key.to_s.split('.')
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({ 'name' => 'Fred' }, outcome.result)
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({ 'name' => '-nils-' }, outcome.result)
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({ 'name' => '-nils-' }, outcome.result)
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({ 'name' => '-invalid-' }, outcome.result)
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({ 'name' => '-empty-' }, outcome.result)
45
+ assert_equal({ name: '-empty-' }, outcome.result)
46
46
  assert_equal true, outcome.success
47
47
  end
48
48
  end
@@ -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({ 'name' => 'bob', 'email' => 'jon@jones.com', 'age' => 10, 'amount' => 22 }, outcome.inputs)
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({ 'name' => 'bob', 'email' => 'jon@jones.com', 'amount' => 22 }, outcome.inputs)
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({ 'name' => 'bob', 'email' => 'jon@jones.com', 'age' => 10, 'amount' => 22 }, outcome.inputs)
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({ 'name' => 'bob', 'email' => 'jon@jones.com', 'amount' => 22 }, outcome.inputs)
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
- 'str1' => :empty,
75
- 'str2' => :in,
76
- 'int1' => :integer,
77
- 'hash1' => { 'bool1' => :boolean, 'bool2' => :nils },
78
- 'arr1' => [:integer, nil, :integer]
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
- 'str1' => 'Str1 cannot be empty',
87
- 'str2' => 'Str2 is not an available option',
88
- 'int1' => 'Int1 must be an integer',
89
- 'hash1' => {
90
- 'bool1' => 'Bool1 must be a boolean',
91
- 'bool2' => 'Bool2 cannot be nil'
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
- 'arr1' => ['1st Arr1 must be an integer', nil, '3rd Arr1 must be an integer']
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
- 'Str1 cannot be empty',
102
- 'Str2 is not an available option',
103
- 'Int1 must be an integer',
104
- 'Bool1 must be a boolean',
105
- 'Bool2 cannot be nil',
106
- '1st Arr1 must be an integer',
107
- '3rd Arr1 must be an integer'
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
- { 'foo' => 'f', 'bar' => 3, 'baz' => true },
144
- { 'foo' => 'f', 'bar' => 3, 'baz' => nil },
145
- { 'foo' => 'f', 'baz' => nil }
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 ({ 'bar' => :nils }), result.errors[2].codes
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 Item cannot be empty'
175
- err_message_string = '3rd Item must be a string'
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 ({ 'foo' => 'bar' }), result.inputs
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 ({ 'foo' => 3.14 }), result.inputs
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 ({ 'foo' => '123' }), result.inputs
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 ({ 'foo' => sio }), result.inputs
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({ 'foo' => 'oof', 'bar' => nil }, result.inputs)
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({ 'foo' => 'oof', 'bar' => nil }, result.inputs)
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({ 'foo' => 'bar', 'bar' => '' }, result.inputs)
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({ 'foo' => 'bar', 'bar' => '' }, result.inputs)
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({ 'name' => 'John', 'email' => 'john@gmail.com', 'amount' => 5 }, outcome.inputs)
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({ 'name' => 'John', 'email' => 'john@gmail.com', 'amount' => 5 }, outcome.inputs)
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.build(name: 'JohnLong', email: 'john@gmail.com')
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.build(name: 'JohnTooLong', email: 'john@gmail.com')
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.build(name: 'JohnLong', email: 'xxxx')
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.build(name: 'JohnTooLong', email: 'xxxx')
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({ 'name' => 'John', 'email' => 'bob@jones.com', 'amount' => 5 }, outcome.inputs)
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({ 'name' => 'John', 'email' => 'john@gmail.com', 'amount' => 5 }, outcome.inputs)
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('people.bob', :is_a_bob)
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[:bob]
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 = { 'name' => 'Hello World', 'other' => 'Foo Bar Baz' }
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.3.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-01 00:00:00.000000000 Z
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
  - - ">="