mutations 0.5.3 → 0.5.4

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.
@@ -2,30 +2,17 @@ module Mutations
2
2
  class HashFilter < InputFilter
3
3
  @default_options = {
4
4
  nils: false, # true allows an explicit nil to be valid. Overrides any other options
5
- key_class: nil, # Can be a string or Class. If present, all keys must be of this class. Note that this field can't be set if a block is passed.
6
- value_class: nil # Can be a string or Class. If present, all values must be of this class. Note that this field can't be set if a block is passed.
7
5
  }
8
6
 
9
- attr_accessor :general_inputs # defaults to false
10
7
  attr_accessor :optional_inputs
11
8
  attr_accessor :required_inputs
12
9
 
13
- # There's two types of Hash filters:
14
- # - those that accept specific inputs (eg, the hash needs to have an email key with a string value matching %r{...})
15
- # - those that accept general hashes (eg, the hash needs to have String keys and values, but can have any such k/v's)
16
10
  def initialize(opts = {}, &block)
17
11
  super(opts)
18
12
 
19
- raise ArgumentError, "Can't use key_class/value_class with a block." if block_given? && (options[:key_class] || options[:value_class])
20
-
21
- if options[:key_class] || options[:value_class]
22
- @general_inputs = true
23
- else
24
- @general_inputs = false
25
- @optional_inputs = {}
26
- @required_inputs = {}
27
- @current_inputs = @required_inputs
28
- end
13
+ @optional_inputs = {}
14
+ @required_inputs = {}
15
+ @current_inputs = @required_inputs
29
16
 
30
17
  if block_given?
31
18
  instance_eval &block
@@ -40,21 +27,16 @@ module Mutations
40
27
  @required_inputs.each_pair do |k, v|
41
28
  dupped.required_inputs[k] = v
42
29
  end
43
- dupped.general_inputs = @general_inputs
44
30
  dupped
45
31
  end
46
32
 
47
33
  def required(&block)
48
- raise ArgumentError, "Can't use specific filters if you're filtering by key." if general_inputs
49
-
50
34
  # TODO: raise if nesting is wrong
51
35
  @current_inputs = @required_inputs
52
36
  instance_eval &block
53
37
  end
54
38
 
55
39
  def optional(&block)
56
- raise ArgumentError, "Can't use specific filters if you're filtering by key." if general_inputs
57
-
58
40
  # TODO: raise if nesting is wrong
59
41
  @current_inputs = @optional_inputs
60
42
  instance_eval &block
@@ -82,9 +64,6 @@ module Mutations
82
64
  end
83
65
 
84
66
  def hash(name, options = {}, &block)
85
- unless block_given?
86
- options.reverse_merge!(key_class: String, value_class: String)
87
- end
88
67
  @current_inputs[name.to_sym] = HashFilter.new(options, &block)
89
68
  end
90
69
 
@@ -117,47 +96,50 @@ module Mutations
117
96
 
118
97
  errors = ErrorHash.new
119
98
  filtered_data = HashWithIndifferentAccess.new
99
+ wildcard_filterer = nil
120
100
 
121
- if @general_inputs
122
- key_class_const = options[:key_class] || raise
123
- key_class_const = key_class_const.constantize if key_class_const.is_a?(String)
124
-
125
- value_class_const = options[:value_class] || raise
126
- value_class_const = value_class_const.constantize if value_class_const.is_a?(String)
127
- data.each_pair do |k, v|
128
- if k.is_a?(key_class_const) && v.is_a?(value_class_const)
129
- filtered_data[k] = v
130
- else
131
- k_string = k.to_s
132
- if !k.is_a?(key_class_const)
133
- errors[k_string] = ErrorAtom.new(k_string, :key_class)
101
+ [[@required_inputs, true], [@optional_inputs, false]].each do |(inputs, is_required)|
102
+ inputs.each_pair do |key, filterer|
103
+
104
+ # If we are doing wildcards, then record so and move on
105
+ if key == :*
106
+ wildcard_filterer = filterer
107
+ next
108
+ end
109
+
110
+ data_element = data[key]
111
+ default_used = false
112
+ if !data.has_key?(key) && filterer.has_default?
113
+ data_element = filterer.default
114
+ default_used = true
115
+ end
116
+
117
+ if data.has_key?(key) || default_used
118
+ sub_data, sub_error = filterer.filter(data_element)
119
+
120
+ if sub_error.nil?
121
+ filtered_data[key] = sub_data
134
122
  else
135
- errors[k_string] = ErrorAtom.new(k_string, :value_class)
123
+ sub_error = ErrorAtom.new(key, sub_error) if sub_error.is_a?(Symbol)
124
+ errors[key] = sub_error
136
125
  end
126
+ elsif is_required
127
+ errors[key] = ErrorAtom.new(key, :required)
137
128
  end
138
129
  end
139
- else
140
- [[@required_inputs, true], [@optional_inputs, false]].each do |(inputs, is_required)|
141
- inputs.each_pair do |key, filterer|
142
- data_element = data[key]
143
- default_used = false
144
- if !data.has_key?(key) && filterer.has_default?
145
- data_element = filterer.default
146
- default_used = true
147
- end
148
-
149
- if data.has_key?(key) || default_used
150
- sub_data, sub_error = filterer.filter(data_element)
130
+ end
151
131
 
152
- if sub_error.nil?
153
- filtered_data[key] = sub_data
154
- else
155
- sub_error = ErrorAtom.new(key, sub_error) if sub_error.is_a?(Symbol)
156
- errors[key] = sub_error
157
- end
158
- elsif is_required
159
- errors[key] = ErrorAtom.new(key, :required)
160
- end
132
+ if wildcard_filterer
133
+ filtered_keys = data.keys - filtered_data.keys
134
+
135
+ filtered_keys.each do |key|
136
+ data_element = data[key]
137
+ sub_data, sub_error = wildcard_filterer.filter(data_element)
138
+ if sub_error.nil?
139
+ filtered_data[key] = sub_data
140
+ else
141
+ sub_error = ErrorAtom.new(key, sub_error) if sub_error.is_a?(Symbol)
142
+ errors[key] = sub_error
161
143
  end
162
144
  end
163
145
  end
@@ -1,3 +1,3 @@
1
1
  module Mutations
2
- VERSION = "0.5.3"
2
+ VERSION = "0.5.4"
3
3
  end
@@ -19,23 +19,31 @@ describe "Mutations::HashFilter" do
19
19
  assert_equal :hash, errors
20
20
  end
21
21
 
22
- it 'allows general hashes' do
23
- hf = Mutations::HashFilter.new(key_class: String, value_class: Symbol)
24
- filtered, errors = hf.filter("f1" => :v1, "f2" => :v2)
25
- assert_equal ({"f1" => :v1, "f2" => :v2}), filtered
22
+ it "allows wildcards in hashes" do
23
+ hf = Mutations::HashFilter.new do
24
+ string :*
25
+ end
26
+ filtered, errors = hf.filter(foo: "bar", baz: "ban")
27
+ assert_equal ({"foo" => "bar", "baz" => "ban"}), filtered
26
28
  assert_equal nil, errors
27
29
  end
28
30
 
29
- it 'doesnt allows invalid general hashes (wrong value type)' do
30
- hf = Mutations::HashFilter.new(key_class: String, value_class: Symbol)
31
- filtered, errors = hf.filter("f1" => "v1", "f2" => :v2)
32
- assert_equal ({"f1" => :value_class}), errors.symbolic
31
+ it "doesn't allow wildcards in hashes" do
32
+ hf = Mutations::HashFilter.new do
33
+ string :*
34
+ end
35
+ filtered, errors = hf.filter(foo: nil)
36
+ assert_equal ({"foo" => :nils}), errors.symbolic
33
37
  end
34
38
 
35
- it 'doesnt allows invalid general hashes (wrong key type)' do
36
- hf = Mutations::HashFilter.new(key_class: Fixnum, value_class: Symbol)
37
- filtered, errors = hf.filter("f1" => :v1)
38
- assert_equal ({"f1" => :key_class}), errors.symbolic
39
+ it "allows a mix of specific keys and then wildcards" do
40
+ hf = Mutations::HashFilter.new do
41
+ string :foo
42
+ integer :*
43
+ end
44
+ filtered, errors = hf.filter(foo: "bar", baz: "4")
45
+ assert_equal ({"foo" => "bar", "baz" => 4}), filtered
46
+ assert_equal nil, errors
39
47
  end
40
48
 
41
49
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'minitest/unit'
2
- #require 'minitest/pride'
3
2
  require 'minitest/autorun'
4
3
  require 'pp'
5
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: