mutations 0.5.2 → 0.5.3
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/lib/mutations/exception.rb +1 -1
- data/lib/mutations/hash_filter.rb +62 -21
- data/lib/mutations/version.rb +1 -1
- data/spec/hash_filter_spec.rb +41 -0
- data/spec/spec_helper.rb +1 -1
- metadata +3 -2
data/lib/mutations/exception.rb
CHANGED
@@ -2,17 +2,30 @@ 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.
|
5
7
|
}
|
6
8
|
|
9
|
+
attr_accessor :general_inputs # defaults to false
|
7
10
|
attr_accessor :optional_inputs
|
8
11
|
attr_accessor :required_inputs
|
9
12
|
|
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)
|
10
16
|
def initialize(opts = {}, &block)
|
11
17
|
super(opts)
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
16
29
|
|
17
30
|
if block_given?
|
18
31
|
instance_eval &block
|
@@ -27,16 +40,21 @@ module Mutations
|
|
27
40
|
@required_inputs.each_pair do |k, v|
|
28
41
|
dupped.required_inputs[k] = v
|
29
42
|
end
|
43
|
+
dupped.general_inputs = @general_inputs
|
30
44
|
dupped
|
31
45
|
end
|
32
46
|
|
33
47
|
def required(&block)
|
48
|
+
raise ArgumentError, "Can't use specific filters if you're filtering by key." if general_inputs
|
49
|
+
|
34
50
|
# TODO: raise if nesting is wrong
|
35
51
|
@current_inputs = @required_inputs
|
36
52
|
instance_eval &block
|
37
53
|
end
|
38
54
|
|
39
55
|
def optional(&block)
|
56
|
+
raise ArgumentError, "Can't use specific filters if you're filtering by key." if general_inputs
|
57
|
+
|
40
58
|
# TODO: raise if nesting is wrong
|
41
59
|
@current_inputs = @optional_inputs
|
42
60
|
instance_eval &block
|
@@ -64,6 +82,9 @@ module Mutations
|
|
64
82
|
end
|
65
83
|
|
66
84
|
def hash(name, options = {}, &block)
|
85
|
+
unless block_given?
|
86
|
+
options.reverse_merge!(key_class: String, value_class: String)
|
87
|
+
end
|
67
88
|
@current_inputs[name.to_sym] = HashFilter.new(options, &block)
|
68
89
|
end
|
69
90
|
|
@@ -97,26 +118,46 @@ module Mutations
|
|
97
118
|
errors = ErrorHash.new
|
98
119
|
filtered_data = HashWithIndifferentAccess.new
|
99
120
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
filtered_data[key] = sub_data
|
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)
|
114
134
|
else
|
115
|
-
|
116
|
-
|
135
|
+
errors[k_string] = ErrorAtom.new(k_string, :value_class)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
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)
|
151
|
+
|
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)
|
117
160
|
end
|
118
|
-
elsif is_required
|
119
|
-
errors[key] = ErrorAtom.new(key, :required)
|
120
161
|
end
|
121
162
|
end
|
122
163
|
end
|
data/lib/mutations/version.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe "Mutations::HashFilter" do
|
4
|
+
|
5
|
+
it "allows valid hashes" do
|
6
|
+
hf = Mutations::HashFilter.new do
|
7
|
+
string :foo
|
8
|
+
end
|
9
|
+
filtered, errors = hf.filter(foo: "bar")
|
10
|
+
assert_equal ({"foo" => "bar"}), filtered
|
11
|
+
assert_equal nil, errors
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'disallows non-hashes' do
|
15
|
+
hf = Mutations::HashFilter.new do
|
16
|
+
string :foo
|
17
|
+
end
|
18
|
+
filtered, errors = hf.filter("bar")
|
19
|
+
assert_equal :hash, errors
|
20
|
+
end
|
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
|
26
|
+
assert_equal nil, errors
|
27
|
+
end
|
28
|
+
|
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
|
33
|
+
end
|
34
|
+
|
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
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/spec_helper.rb
CHANGED
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.
|
4
|
+
version: 0.5.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -92,6 +92,7 @@ files:
|
|
92
92
|
- spec/command_spec.rb
|
93
93
|
- spec/default_spec.rb
|
94
94
|
- spec/errors_spec.rb
|
95
|
+
- spec/hash_filter_spec.rb
|
95
96
|
- spec/inheritance_spec.rb
|
96
97
|
- spec/integer_filter_spec.rb
|
97
98
|
- spec/model_filter_spec.rb
|