mutations 0.5.11 → 0.5.12
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/CHANGELOG.md +22 -0
- data/Gemfile.lock +1 -1
- data/lib/mutations.rb +2 -0
- data/lib/mutations/array_filter.rb +8 -1
- data/lib/mutations/command.rb +10 -11
- data/lib/mutations/duck_filter.rb +25 -0
- data/lib/mutations/file_filter.rb +32 -0
- data/lib/mutations/hash_filter.rb +8 -1
- data/lib/mutations/integer_filter.rb +6 -2
- data/lib/mutations/version.rb +1 -1
- data/spec/array_filter_spec.rb +18 -0
- data/spec/command_spec.rb +18 -0
- data/spec/duck_filter_spec.rb +49 -0
- data/spec/file_filter_spec.rb +91 -0
- data/spec/hash_filter_spec.rb +21 -1
- data/spec/inheritance_spec.rb +1 -1
- data/spec/integer_filter_spec.rb +15 -1
- metadata +7 -2
data/CHANGELOG.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
0.5.12
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Added a duck filter: ```duck :lengthy, methods: :length``` to ensure all values respond_to? :length [#14]
|
5
|
+
- Added a file filter: ```file :data``` to ensure the data is a File-like object [#15]
|
6
|
+
- Allow raw_inputs to be used as method inside of execute to access the original data passed in. (@tomtaylor)
|
7
|
+
- integer filter now allows the ```in``` option. Eg: ```integer :http_code, in: (200, 404, 401)``` (/via @tomtaylor)
|
8
|
+
- Added a changelog. [#10]
|
9
|
+
|
10
|
+
0.5.11
|
11
|
+
-----------
|
12
|
+
|
13
|
+
- Float filter (@aq1018)
|
14
|
+
- Clean up public API + code (@blambeau)
|
15
|
+
- Model filters should lazily resolve their classes so that mocks can be used (@edwinv)
|
16
|
+
- Filtered inputs should be included in the Outcome
|
17
|
+
- Fix typos (@frodsan)
|
18
|
+
|
19
|
+
0.5.10 and earlier
|
20
|
+
-----------
|
21
|
+
|
22
|
+
- Initial versions
|
data/Gemfile.lock
CHANGED
data/lib/mutations.rb
CHANGED
@@ -10,6 +10,8 @@ require 'mutations/string_filter'
|
|
10
10
|
require 'mutations/integer_filter'
|
11
11
|
require 'mutations/float_filter'
|
12
12
|
require 'mutations/boolean_filter'
|
13
|
+
require 'mutations/duck_filter'
|
14
|
+
require 'mutations/file_filter'
|
13
15
|
require 'mutations/model_filter'
|
14
16
|
require 'mutations/array_filter'
|
15
17
|
require 'mutations/hash_filter'
|
@@ -34,6 +34,14 @@ module Mutations
|
|
34
34
|
def boolean(options = {})
|
35
35
|
@element_filter = BooleanFilter.new(options)
|
36
36
|
end
|
37
|
+
|
38
|
+
def duck(options = {})
|
39
|
+
@element_filter = DuckFilter.new(options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def file(options = {})
|
43
|
+
@element_filter = FileFilter.new(options)
|
44
|
+
end
|
37
45
|
|
38
46
|
def hash(options = {}, &block)
|
39
47
|
@element_filter = HashFilter.new(options, &block)
|
@@ -87,7 +95,6 @@ module Mutations
|
|
87
95
|
|
88
96
|
# Returns [filtered, errors]
|
89
97
|
def filter_element(data)
|
90
|
-
|
91
98
|
if @element_filter
|
92
99
|
data, el_errors = @element_filter.filter(data)
|
93
100
|
return [data, el_errors] if el_errors
|
data/lib/mutations/command.rb
CHANGED
@@ -6,15 +6,15 @@ module Mutations
|
|
6
6
|
keys = self.input_filters.send("#{meth}_keys")
|
7
7
|
keys.each do |key|
|
8
8
|
define_method(key) do
|
9
|
-
@
|
9
|
+
@inputs[key]
|
10
10
|
end
|
11
11
|
|
12
12
|
define_method("#{key}_present?") do
|
13
|
-
@
|
13
|
+
@inputs.has_key?(key)
|
14
14
|
end
|
15
15
|
|
16
16
|
define_method("#{key}=") do |v|
|
17
|
-
@
|
17
|
+
@inputs[key] = v
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -55,11 +55,12 @@ module Mutations
|
|
55
55
|
|
56
56
|
# Instance methods
|
57
57
|
def initialize(*args)
|
58
|
-
@
|
58
|
+
@raw_inputs = args.each_with_object({}.with_indifferent_access) do |arg, h|
|
59
59
|
raise ArgumentError.new("All arguments must be hashes") unless arg.is_a?(Hash)
|
60
60
|
h.merge!(arg)
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
|
+
@inputs, @errors = self.input_filters.filter(@raw_inputs)
|
63
64
|
end
|
64
65
|
|
65
66
|
def input_filters
|
@@ -88,13 +89,14 @@ module Mutations
|
|
88
89
|
validation_outcome
|
89
90
|
end
|
90
91
|
|
91
|
-
# Runs input thru the filter and sets @filtered_input and @errors
|
92
92
|
def validation_outcome(result = nil)
|
93
|
-
Outcome.new(!has_errors?, has_errors? ? nil : result, @errors, @
|
93
|
+
Outcome.new(!has_errors?, has_errors? ? nil : result, @errors, @inputs)
|
94
94
|
end
|
95
95
|
|
96
96
|
protected
|
97
97
|
|
98
|
+
attr_reader :inputs, :raw_inputs
|
99
|
+
|
98
100
|
def execute
|
99
101
|
# Meant to be overridden
|
100
102
|
end
|
@@ -121,8 +123,5 @@ module Mutations
|
|
121
123
|
@errors.merge!(hash)
|
122
124
|
end
|
123
125
|
|
124
|
-
def inputs
|
125
|
-
@filtered_input
|
126
|
-
end
|
127
126
|
end
|
128
|
-
end
|
127
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Mutations
|
2
|
+
class DuckFilter < InputFilter
|
3
|
+
@default_options = {
|
4
|
+
nils: false, # true allows an explicit nil to be valid. Overrides any other options
|
5
|
+
methods: nil # The object needs to respond to each of the symbols in this array.
|
6
|
+
}
|
7
|
+
|
8
|
+
def filter(data)
|
9
|
+
|
10
|
+
# Handle nil case
|
11
|
+
if data.nil?
|
12
|
+
return [nil, nil] if options[:nils]
|
13
|
+
return [nil, :nils]
|
14
|
+
end
|
15
|
+
|
16
|
+
# Ensure the data responds to each of the methods
|
17
|
+
Array(options[:methods]).each do |method|
|
18
|
+
return [data, :duck] unless data.respond_to?(method)
|
19
|
+
end
|
20
|
+
|
21
|
+
# We win, it's valid!
|
22
|
+
[data, nil]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Mutations
|
2
|
+
class FileFilter < InputFilter
|
3
|
+
@default_options = {
|
4
|
+
nils: false, # true allows an explicit nil to be valid. Overrides any other options
|
5
|
+
upload: false, # if true, also checks the file is has original_filename and content_type methods.
|
6
|
+
size: nil # An integer value like 1_000_000 limits the size of the file to 1M bytes
|
7
|
+
}
|
8
|
+
|
9
|
+
def filter(data)
|
10
|
+
|
11
|
+
# Handle nil case
|
12
|
+
if data.nil?
|
13
|
+
return [nil, nil] if options[:nils]
|
14
|
+
return [nil, :nils]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Ensure the data responds to each of the methods
|
18
|
+
methods = [:read, :size]
|
19
|
+
methods.concat([:original_filename, :content_type]) if options[:upload]
|
20
|
+
methods.each do |method|
|
21
|
+
return [data, :file] unless data.respond_to?(method)
|
22
|
+
end
|
23
|
+
|
24
|
+
if options[:size].is_a?(Fixnum)
|
25
|
+
return [data, :size] if data.size > options[:size]
|
26
|
+
end
|
27
|
+
|
28
|
+
# We win, it's valid!
|
29
|
+
[data, nil]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -64,12 +64,19 @@ module Mutations
|
|
64
64
|
def boolean(name, options = {})
|
65
65
|
@current_inputs[name.to_sym] = BooleanFilter.new(options)
|
66
66
|
end
|
67
|
+
|
68
|
+
def duck(name, options = {})
|
69
|
+
@current_inputs[name.to_sym] = DuckFilter.new(options)
|
70
|
+
end
|
71
|
+
|
72
|
+
def file(name, options = {})
|
73
|
+
@current_inputs[name.to_sym] = FileFilter.new(options)
|
74
|
+
end
|
67
75
|
|
68
76
|
def hash(name, options = {}, &block)
|
69
77
|
@current_inputs[name.to_sym] = HashFilter.new(options, &block)
|
70
78
|
end
|
71
79
|
|
72
|
-
# Advanced types
|
73
80
|
def model(name, options = {})
|
74
81
|
name_sym = name.to_sym
|
75
82
|
@current_inputs[name_sym] = ModelFilter.new(name_sym, options)
|
@@ -3,7 +3,8 @@ module Mutations
|
|
3
3
|
@default_options = {
|
4
4
|
nils: false, # true allows an explicit nil to be valid. Overrides any other options
|
5
5
|
min: nil, # lowest value, inclusive
|
6
|
-
max: nil
|
6
|
+
max: nil, # highest value, inclusive
|
7
|
+
in: nil # Can be an array like %w(3 4 5)
|
7
8
|
}
|
8
9
|
|
9
10
|
def filter(data)
|
@@ -26,8 +27,11 @@ module Mutations
|
|
26
27
|
return [data, :min] if options[:min] && data < options[:min]
|
27
28
|
return [data, :max] if options[:max] && data > options[:max]
|
28
29
|
|
30
|
+
# Ensure it matches `in`
|
31
|
+
return [data, :in] if options[:in] && !options[:in].include?(data)
|
32
|
+
|
29
33
|
# We win, it's valid!
|
30
34
|
[data, nil]
|
31
35
|
end
|
32
36
|
end
|
33
|
-
end
|
37
|
+
end
|
data/lib/mutations/version.rb
CHANGED
data/spec/array_filter_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'spec_helper'
|
2
|
+
require 'stringio'
|
2
3
|
|
3
4
|
describe "Mutations::ArrayFilter" do
|
4
5
|
|
@@ -91,6 +92,23 @@ describe "Mutations::ArrayFilter" do
|
|
91
92
|
assert_equal [5.0,6.0,1.0,"bob"], filtered
|
92
93
|
assert_equal [nil, nil, :min, :float], errors.symbolic
|
93
94
|
end
|
95
|
+
|
96
|
+
it "lets you pass ducks in arrays" do
|
97
|
+
f = Mutations::ArrayFilter.new(:arr) { duck(methods: :length) }
|
98
|
+
|
99
|
+
filtered, errors = f.filter(["hi", [1], true])
|
100
|
+
assert_equal ["hi", [1], true], filtered
|
101
|
+
assert_equal [nil, nil, :duck], errors.symbolic
|
102
|
+
end
|
103
|
+
|
104
|
+
it "lets you pass files in arrays" do
|
105
|
+
sio = StringIO.new("bob")
|
106
|
+
f = Mutations::ArrayFilter.new(:arr) { file }
|
107
|
+
|
108
|
+
filtered, errors = f.filter([sio, "bob"])
|
109
|
+
assert_equal [sio, "bob"], filtered
|
110
|
+
assert_equal [nil, :file], errors.symbolic
|
111
|
+
end
|
94
112
|
|
95
113
|
it "lets you pass booleans in arrays" do
|
96
114
|
f = Mutations::ArrayFilter.new(:arr) { boolean }
|
data/spec/command_spec.rb
CHANGED
@@ -201,4 +201,22 @@ describe "Command" do
|
|
201
201
|
end
|
202
202
|
end
|
203
203
|
|
204
|
+
describe "RawInputsCommand" do
|
205
|
+
class RawInputsCommand < Mutations::Command
|
206
|
+
|
207
|
+
required do
|
208
|
+
string :name
|
209
|
+
end
|
210
|
+
|
211
|
+
def execute
|
212
|
+
return raw_inputs
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should return the raw input data" do
|
217
|
+
input = { "name" => "Hello World", "other" => "Foo Bar Baz" }
|
218
|
+
assert_equal input, RawInputsCommand.run!(input)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
204
222
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe "Mutations::DuckFilter" do
|
4
|
+
|
5
|
+
it "allows objects that respond to a single specified method" do
|
6
|
+
f = Mutations::DuckFilter.new(methods: [:length])
|
7
|
+
filtered, errors = f.filter("test")
|
8
|
+
assert_equal "test", filtered
|
9
|
+
assert_equal nil, errors
|
10
|
+
|
11
|
+
filtered, errors = f.filter([1, 2])
|
12
|
+
assert_equal [1, 2], filtered
|
13
|
+
assert_equal nil, errors
|
14
|
+
end
|
15
|
+
|
16
|
+
it "doesn't allow objects that respond to a single specified method" do
|
17
|
+
f = Mutations::DuckFilter.new(methods: [:length])
|
18
|
+
filtered, errors = f.filter(true)
|
19
|
+
assert_equal true, filtered
|
20
|
+
assert_equal :duck, errors
|
21
|
+
|
22
|
+
filtered, errors = f.filter(12)
|
23
|
+
assert_equal 12, filtered
|
24
|
+
assert_equal :duck, errors
|
25
|
+
end
|
26
|
+
|
27
|
+
it "considers nil to be invalid" do
|
28
|
+
f = Mutations::DuckFilter.new(nils: false)
|
29
|
+
filtered, errors = f.filter(nil)
|
30
|
+
assert_equal nil, filtered
|
31
|
+
assert_equal :nils, errors
|
32
|
+
end
|
33
|
+
|
34
|
+
it "considers nil to be valid" do
|
35
|
+
f = Mutations::DuckFilter.new(nils: true)
|
36
|
+
filtered, errors = f.filter(nil)
|
37
|
+
assert_equal nil, filtered
|
38
|
+
assert_equal nil, errors
|
39
|
+
end
|
40
|
+
|
41
|
+
it "Allows anything if no methods are specified" do
|
42
|
+
f = Mutations::DuckFilter.new
|
43
|
+
[true, "hi", 1, [1, 2, 3]].each do |v|
|
44
|
+
filtered, errors = f.filter(v)
|
45
|
+
assert_equal v, filtered
|
46
|
+
assert_equal nil, errors
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
describe "Mutations::FileFilter" do
|
6
|
+
|
7
|
+
class UploadedStringIO < StringIO
|
8
|
+
attr_accessor :content_type, :original_filename
|
9
|
+
end
|
10
|
+
|
11
|
+
it "allows files - file class" do
|
12
|
+
file = File.new("README.md")
|
13
|
+
f = Mutations::FileFilter.new
|
14
|
+
filtered, errors = f.filter(file)
|
15
|
+
assert_equal file, filtered
|
16
|
+
assert_equal nil, errors
|
17
|
+
end
|
18
|
+
|
19
|
+
it "allows files - stringio class" do
|
20
|
+
file = StringIO.new("bob")
|
21
|
+
f = Mutations::FileFilter.new
|
22
|
+
filtered, errors = f.filter(file)
|
23
|
+
assert_equal file, filtered
|
24
|
+
assert_equal nil, errors
|
25
|
+
end
|
26
|
+
|
27
|
+
it "allows files - tempfile" do
|
28
|
+
file = Tempfile.new("bob")
|
29
|
+
f = Mutations::FileFilter.new
|
30
|
+
filtered, errors = f.filter(file)
|
31
|
+
assert_equal file, filtered
|
32
|
+
assert_equal nil, errors
|
33
|
+
end
|
34
|
+
|
35
|
+
it "doesn't allow non-files" do
|
36
|
+
f = Mutations::FileFilter.new
|
37
|
+
filtered, errors = f.filter("string")
|
38
|
+
assert_equal "string", filtered
|
39
|
+
assert_equal :file, errors
|
40
|
+
|
41
|
+
filtered, errors = f.filter(12)
|
42
|
+
assert_equal 12, filtered
|
43
|
+
assert_equal :file, errors
|
44
|
+
end
|
45
|
+
|
46
|
+
it "considers nil to be invalid" do
|
47
|
+
f = Mutations::FileFilter.new(nils: false)
|
48
|
+
filtered, errors = f.filter(nil)
|
49
|
+
assert_equal nil, filtered
|
50
|
+
assert_equal :nils, errors
|
51
|
+
end
|
52
|
+
|
53
|
+
it "considers nil to be valid" do
|
54
|
+
f = Mutations::FileFilter.new(nils: true)
|
55
|
+
filtered, errors = f.filter(nil)
|
56
|
+
assert_equal nil, filtered
|
57
|
+
assert_equal nil, errors
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should allow small files" do
|
61
|
+
file = StringIO.new("bob")
|
62
|
+
f = Mutations::FileFilter.new(size: 4)
|
63
|
+
filtered, errors = f.filter(file)
|
64
|
+
assert_equal file, filtered
|
65
|
+
assert_equal nil, errors
|
66
|
+
end
|
67
|
+
|
68
|
+
it "shouldn't allow big files" do
|
69
|
+
file = StringIO.new("bob")
|
70
|
+
f = Mutations::FileFilter.new(size: 2)
|
71
|
+
filtered, errors = f.filter(file)
|
72
|
+
assert_equal file, filtered
|
73
|
+
assert_equal :size, errors
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should require extra methods if uploaded file: accept" do
|
77
|
+
file = UploadedStringIO.new("bob")
|
78
|
+
f = Mutations::FileFilter.new(upload: true)
|
79
|
+
filtered, errors = f.filter(file)
|
80
|
+
assert_equal file, filtered
|
81
|
+
assert_equal nil, errors
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should require extra methods if uploaded file: deny" do
|
85
|
+
file = StringIO.new("bob")
|
86
|
+
f = Mutations::FileFilter.new(upload: true)
|
87
|
+
filtered, errors = f.filter(file)
|
88
|
+
assert_equal file, filtered
|
89
|
+
assert_equal :file, errors
|
90
|
+
end
|
91
|
+
end
|
data/spec/hash_filter_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'spec_helper'
|
2
|
+
require 'stringio'
|
2
3
|
|
3
4
|
describe "Mutations::HashFilter" do
|
4
5
|
|
@@ -28,7 +29,7 @@ describe "Mutations::HashFilter" do
|
|
28
29
|
assert_equal nil, errors
|
29
30
|
end
|
30
31
|
|
31
|
-
it "
|
32
|
+
it "allows floats in hashes" do
|
32
33
|
hf = Mutations::HashFilter.new do
|
33
34
|
float :foo
|
34
35
|
end
|
@@ -36,6 +37,25 @@ describe "Mutations::HashFilter" do
|
|
36
37
|
assert_equal ({"foo" => 3.14}), filtered
|
37
38
|
assert_equal nil, errors
|
38
39
|
end
|
40
|
+
|
41
|
+
it "allows ducks in hashes" do
|
42
|
+
hf = Mutations::HashFilter.new do
|
43
|
+
duck :foo, methods: [:length]
|
44
|
+
end
|
45
|
+
filtered, errors = hf.filter(foo: "123")
|
46
|
+
assert_equal ({"foo" => "123"}), filtered
|
47
|
+
assert_equal nil, errors
|
48
|
+
end
|
49
|
+
|
50
|
+
it "allows files in hashes" do
|
51
|
+
sio = StringIO.new("bob")
|
52
|
+
hf = Mutations::HashFilter.new do
|
53
|
+
file :foo
|
54
|
+
end
|
55
|
+
filtered, errors = hf.filter(foo: sio)
|
56
|
+
assert_equal ({"foo" => sio}), filtered
|
57
|
+
assert_equal nil, errors
|
58
|
+
end
|
39
59
|
|
40
60
|
it "doesn't allow wildcards in hashes" do
|
41
61
|
hf = Mutations::HashFilter.new do
|
data/spec/inheritance_spec.rb
CHANGED
data/spec/integer_filter_spec.rb
CHANGED
@@ -73,4 +73,18 @@ describe "Mutations::IntegerFilter" do
|
|
73
73
|
assert_equal nil, errors
|
74
74
|
end
|
75
75
|
|
76
|
-
|
76
|
+
it "considers not matching numbers to be invalid" do
|
77
|
+
f = Mutations::IntegerFilter.new(in: [3, 4, 5])
|
78
|
+
filtered, errors = f.filter(6)
|
79
|
+
assert_equal 6, filtered
|
80
|
+
assert_equal :in, errors
|
81
|
+
end
|
82
|
+
|
83
|
+
it "considers matching numbers to be valid" do
|
84
|
+
f = Mutations::IntegerFilter.new(in: [3, 4, 5])
|
85
|
+
filtered, errors = f.filter(3)
|
86
|
+
assert_equal 3, filtered
|
87
|
+
assert_nil errors
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
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.12
|
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: 2013-03-
|
12
|
+
date: 2013-03-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -68,6 +68,7 @@ extra_rdoc_files: []
|
|
68
68
|
files:
|
69
69
|
- .gitignore
|
70
70
|
- .travis
|
71
|
+
- CHANGELOG.md
|
71
72
|
- Gemfile
|
72
73
|
- Gemfile.lock
|
73
74
|
- MIT-LICENSE
|
@@ -78,8 +79,10 @@ files:
|
|
78
79
|
- lib/mutations/array_filter.rb
|
79
80
|
- lib/mutations/boolean_filter.rb
|
80
81
|
- lib/mutations/command.rb
|
82
|
+
- lib/mutations/duck_filter.rb
|
81
83
|
- lib/mutations/errors.rb
|
82
84
|
- lib/mutations/exception.rb
|
85
|
+
- lib/mutations/file_filter.rb
|
83
86
|
- lib/mutations/float_filter.rb
|
84
87
|
- lib/mutations/hash_filter.rb
|
85
88
|
- lib/mutations/input_filter.rb
|
@@ -93,7 +96,9 @@ files:
|
|
93
96
|
- spec/boolean_filter_spec.rb
|
94
97
|
- spec/command_spec.rb
|
95
98
|
- spec/default_spec.rb
|
99
|
+
- spec/duck_filter_spec.rb
|
96
100
|
- spec/errors_spec.rb
|
101
|
+
- spec/file_filter_spec.rb
|
97
102
|
- spec/float_filter_spec.rb
|
98
103
|
- spec/hash_filter_spec.rb
|
99
104
|
- spec/inheritance_spec.rb
|