active_interaction 0.5.0 → 0.6.1
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/CHANGELOG.md +27 -3
- data/README.md +8 -6
- data/lib/active_interaction.rb +5 -3
- data/lib/active_interaction/active_model.rb +29 -0
- data/lib/active_interaction/base.rb +82 -116
- data/lib/active_interaction/errors.rb +79 -5
- data/lib/active_interaction/filter.rb +195 -21
- data/lib/active_interaction/filters.rb +26 -0
- data/lib/active_interaction/filters/array_filter.rb +22 -25
- data/lib/active_interaction/filters/boolean_filter.rb +12 -12
- data/lib/active_interaction/filters/date_filter.rb +32 -5
- data/lib/active_interaction/filters/date_time_filter.rb +34 -7
- data/lib/active_interaction/filters/file_filter.rb +12 -9
- data/lib/active_interaction/filters/float_filter.rb +13 -11
- data/lib/active_interaction/filters/hash_filter.rb +36 -17
- data/lib/active_interaction/filters/integer_filter.rb +13 -11
- data/lib/active_interaction/filters/model_filter.rb +15 -15
- data/lib/active_interaction/filters/string_filter.rb +19 -8
- data/lib/active_interaction/filters/symbol_filter.rb +29 -0
- data/lib/active_interaction/filters/time_filter.rb +38 -16
- data/lib/active_interaction/method_missing.rb +18 -0
- data/lib/active_interaction/overload_hash.rb +1 -0
- data/lib/active_interaction/validation.rb +19 -0
- data/lib/active_interaction/version.rb +1 -1
- data/spec/active_interaction/active_model_spec.rb +33 -0
- data/spec/active_interaction/base_spec.rb +54 -48
- data/spec/active_interaction/errors_spec.rb +99 -0
- data/spec/active_interaction/filter_spec.rb +12 -20
- data/spec/active_interaction/filters/array_filter_spec.rb +50 -28
- data/spec/active_interaction/filters/boolean_filter_spec.rb +15 -15
- data/spec/active_interaction/filters/date_filter_spec.rb +30 -18
- data/spec/active_interaction/filters/date_time_filter_spec.rb +31 -19
- data/spec/active_interaction/filters/file_filter_spec.rb +7 -7
- data/spec/active_interaction/filters/float_filter_spec.rb +13 -11
- data/spec/active_interaction/filters/hash_filter_spec.rb +38 -29
- data/spec/active_interaction/filters/integer_filter_spec.rb +18 -8
- data/spec/active_interaction/filters/model_filter_spec.rb +24 -20
- data/spec/active_interaction/filters/string_filter_spec.rb +14 -8
- data/spec/active_interaction/filters/symbol_filter_spec.rb +24 -0
- data/spec/active_interaction/filters/time_filter_spec.rb +33 -69
- data/spec/active_interaction/filters_spec.rb +21 -0
- data/spec/active_interaction/i18n_spec.rb +0 -15
- data/spec/active_interaction/integration/array_interaction_spec.rb +2 -22
- data/spec/active_interaction/integration/hash_interaction_spec.rb +5 -25
- data/spec/active_interaction/integration/symbol_interaction_spec.rb +5 -0
- data/spec/active_interaction/method_missing_spec.rb +69 -0
- data/spec/active_interaction/validation_spec.rb +55 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/filters.rb +168 -14
- data/spec/support/interactions.rb +11 -13
- metadata +31 -13
- data/lib/active_interaction/filter_method.rb +0 -13
- data/lib/active_interaction/filter_methods.rb +0 -26
- data/lib/active_interaction/filters/abstract_date_time_filter.rb +0 -25
- data/spec/active_interaction/filter_method_spec.rb +0 -43
- data/spec/active_interaction/filter_methods_spec.rb +0 -30
@@ -5,8 +5,8 @@ module ActiveInteraction
|
|
5
5
|
# unless the format option is given, in which case they will be processed
|
6
6
|
# with `strptime`.
|
7
7
|
#
|
8
|
-
# @macro
|
9
|
-
# @option options [String] :format
|
8
|
+
# @macro filter_method_params
|
9
|
+
# @option options [String] :format parse strings using this format string
|
10
10
|
#
|
11
11
|
# @example
|
12
12
|
# date :birthday
|
@@ -14,13 +14,40 @@ module ActiveInteraction
|
|
14
14
|
# @example
|
15
15
|
# date :birthday, format: '%Y-%m-%d'
|
16
16
|
#
|
17
|
+
# @since 0.1.0
|
18
|
+
#
|
17
19
|
# @method self.date(*attributes, options = {})
|
18
20
|
end
|
19
21
|
|
20
22
|
# @private
|
21
|
-
class DateFilter <
|
22
|
-
def
|
23
|
-
|
23
|
+
class DateFilter < Filter
|
24
|
+
def cast(value)
|
25
|
+
case value
|
26
|
+
when Date
|
27
|
+
value
|
28
|
+
when String
|
29
|
+
begin
|
30
|
+
if has_format?
|
31
|
+
Date.strptime(value, format)
|
32
|
+
else
|
33
|
+
Date.parse(value)
|
34
|
+
end
|
35
|
+
rescue ArgumentError
|
36
|
+
super
|
37
|
+
end
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def has_format?
|
46
|
+
options.has_key?(:format)
|
47
|
+
end
|
48
|
+
|
49
|
+
def format
|
50
|
+
options.fetch(:format)
|
24
51
|
end
|
25
52
|
end
|
26
53
|
end
|
@@ -5,22 +5,49 @@ module ActiveInteraction
|
|
5
5
|
# unless the format option is given, in which case they will be processed
|
6
6
|
# with `strptime`.
|
7
7
|
#
|
8
|
-
# @macro
|
9
|
-
# @option options [String] :format
|
8
|
+
# @macro filter_method_params
|
9
|
+
# @option options [String] :format parse strings using this format string
|
10
10
|
#
|
11
11
|
# @example
|
12
|
-
#
|
12
|
+
# date :start_date
|
13
13
|
#
|
14
14
|
# @example
|
15
|
-
#
|
15
|
+
# date :start_date, format: '%Y-%m-%dT%H:%M:%S%:z'
|
16
|
+
#
|
17
|
+
# @since 0.1.0
|
16
18
|
#
|
17
19
|
# @method self.date_time(*attributes, options = {})
|
18
20
|
end
|
19
21
|
|
20
22
|
# @private
|
21
|
-
class DateTimeFilter <
|
22
|
-
def
|
23
|
-
|
23
|
+
class DateTimeFilter < Filter
|
24
|
+
def cast(value)
|
25
|
+
case value
|
26
|
+
when DateTime
|
27
|
+
value
|
28
|
+
when String
|
29
|
+
begin
|
30
|
+
if has_format?
|
31
|
+
DateTime.strptime(value, format)
|
32
|
+
else
|
33
|
+
DateTime.parse(value)
|
34
|
+
end
|
35
|
+
rescue ArgumentError
|
36
|
+
super
|
37
|
+
end
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def has_format?
|
46
|
+
options.has_key?(:format)
|
47
|
+
end
|
48
|
+
|
49
|
+
def format
|
50
|
+
options.fetch(:format)
|
24
51
|
end
|
25
52
|
end
|
26
53
|
end
|
@@ -1,38 +1,41 @@
|
|
1
1
|
module ActiveInteraction
|
2
2
|
class Base
|
3
3
|
# Creates accessors for the attributes and ensures that values passed to
|
4
|
-
# the attributes are Files or
|
4
|
+
# the attributes are Files or Tempfiles. It will also extract a file from
|
5
5
|
# any object with a `tempfile` method. This is useful when passing in
|
6
6
|
# Rails params that include a file upload.
|
7
7
|
#
|
8
|
-
# @macro
|
8
|
+
# @macro filter_method_params
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
# file :image
|
12
12
|
#
|
13
|
+
# @since 0.1.0
|
14
|
+
#
|
13
15
|
# @method self.file(*attributes, options = {})
|
14
16
|
end
|
15
17
|
|
16
18
|
# @private
|
17
19
|
class FileFilter < Filter
|
18
|
-
def
|
20
|
+
def cast(value)
|
19
21
|
value = extract_file(value)
|
20
22
|
|
21
23
|
case value
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
when File, Tempfile
|
25
|
+
value
|
26
|
+
else
|
27
|
+
super
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
29
|
-
|
31
|
+
private
|
32
|
+
|
33
|
+
def extract_file(value)
|
30
34
|
if value.respond_to?(:tempfile)
|
31
35
|
value.tempfile
|
32
36
|
else
|
33
37
|
value
|
34
38
|
end
|
35
39
|
end
|
36
|
-
private_class_method :extract_file
|
37
40
|
end
|
38
41
|
end
|
@@ -4,28 +4,30 @@ module ActiveInteraction
|
|
4
4
|
# the attributes are Floats. Integer and String values are converted into
|
5
5
|
# Floats.
|
6
6
|
#
|
7
|
-
# @macro
|
7
|
+
# @macro filter_method_params
|
8
8
|
#
|
9
9
|
# @example
|
10
10
|
# float :amount
|
11
11
|
#
|
12
|
+
# @since 0.1.0
|
13
|
+
#
|
12
14
|
# @method self.float(*attributes, options = {})
|
13
15
|
end
|
14
16
|
|
15
17
|
# @private
|
16
18
|
class FloatFilter < Filter
|
17
|
-
def
|
19
|
+
def cast(value)
|
18
20
|
case value
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
super
|
26
|
-
end
|
27
|
-
else
|
21
|
+
when Numeric
|
22
|
+
value.to_f
|
23
|
+
when String
|
24
|
+
begin
|
25
|
+
Float(value)
|
26
|
+
rescue ArgumentError
|
28
27
|
super
|
28
|
+
end
|
29
|
+
else
|
30
|
+
super
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
@@ -3,8 +3,9 @@ module ActiveInteraction
|
|
3
3
|
# Creates accessors for the attributes and ensures that values passed to
|
4
4
|
# the attributes are Hashes.
|
5
5
|
#
|
6
|
-
# @macro
|
7
|
-
# @param block [Proc]
|
6
|
+
# @macro filter_method_params
|
7
|
+
# @param block [Proc] filter methods to apply for select keys
|
8
|
+
# @option options [Boolean] :strip (true) strip unknown keys
|
8
9
|
#
|
9
10
|
# @example
|
10
11
|
# hash :order
|
@@ -17,33 +18,51 @@ module ActiveInteraction
|
|
17
18
|
# boolean :delivered
|
18
19
|
# end
|
19
20
|
#
|
21
|
+
# @since 0.1.0
|
22
|
+
#
|
20
23
|
# @method self.hash(*attributes, options = {}, &block)
|
21
24
|
end
|
22
25
|
|
23
26
|
# @private
|
24
27
|
class HashFilter < Filter
|
25
|
-
|
28
|
+
include MethodMissing
|
29
|
+
|
30
|
+
def cast(value)
|
26
31
|
case value
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
32
|
+
when Hash
|
33
|
+
value = value.symbolize_keys
|
34
|
+
filters.reduce(strip? ? {} : value) do |h, f|
|
35
|
+
k = f.name
|
36
|
+
h[k] = f.clean(value[k])
|
37
|
+
h
|
38
|
+
end
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def default
|
45
|
+
if options[:default].is_a?(Hash) && !options[:default].empty?
|
46
|
+
raise InvalidDefaultError, "#{name}: #{options[:default].inspect}"
|
31
47
|
end
|
48
|
+
|
49
|
+
super
|
32
50
|
end
|
33
51
|
|
34
|
-
def
|
35
|
-
|
52
|
+
def method_missing(*args, &block)
|
53
|
+
super do |klass, names, options|
|
54
|
+
raise InvalidFilterError, 'no name' if names.empty?
|
36
55
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
prepare(key, hash[key], method.options, &method.block)
|
56
|
+
names.each do |name|
|
57
|
+
filters.add(klass.new(name, options, &block))
|
58
|
+
end
|
41
59
|
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
42
63
|
|
43
|
-
|
44
|
-
|
45
|
-
raise InvalidNestedValue
|
64
|
+
def strip?
|
65
|
+
options.fetch(:strip, true)
|
46
66
|
end
|
47
|
-
private_class_method :convert_values
|
48
67
|
end
|
49
68
|
end
|
@@ -3,28 +3,30 @@ module ActiveInteraction
|
|
3
3
|
# Creates accessors for the attributes and ensures that values passed to
|
4
4
|
# the attributes are Integers. String values are converted into Integers.
|
5
5
|
#
|
6
|
-
# @macro
|
6
|
+
# @macro filter_method_params
|
7
7
|
#
|
8
8
|
# @example
|
9
9
|
# integer :quantity
|
10
10
|
#
|
11
|
+
# @since 0.1.0
|
12
|
+
#
|
11
13
|
# @method self.integer(*attributes, options = {})
|
12
14
|
end
|
13
15
|
|
14
16
|
# @private
|
15
17
|
class IntegerFilter < Filter
|
16
|
-
def
|
18
|
+
def cast(value)
|
17
19
|
case value
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
super
|
25
|
-
end
|
26
|
-
else
|
20
|
+
when Numeric
|
21
|
+
value.to_i
|
22
|
+
when String
|
23
|
+
begin
|
24
|
+
Integer(value)
|
25
|
+
rescue ArgumentError
|
27
26
|
super
|
27
|
+
end
|
28
|
+
else
|
29
|
+
super
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
@@ -3,7 +3,7 @@ module ActiveInteraction
|
|
3
3
|
# Creates accessors for the attributes and ensures that values passed to
|
4
4
|
# the attributes are the correct class.
|
5
5
|
#
|
6
|
-
# @macro
|
6
|
+
# @macro filter_method_params
|
7
7
|
# @option options [Class, String, Symbol] :class (use the attribute name)
|
8
8
|
# Class name used to ensure the value.
|
9
9
|
#
|
@@ -13,29 +13,29 @@ module ActiveInteraction
|
|
13
13
|
# @example Ensures that the class is `User`
|
14
14
|
# model :account, class: User
|
15
15
|
#
|
16
|
+
# @since 0.1.0
|
17
|
+
#
|
16
18
|
# @method self.model(*attributes, options = {})
|
17
19
|
end
|
18
20
|
|
19
21
|
# @private
|
20
22
|
class ModelFilter < Filter
|
21
|
-
def
|
22
|
-
key_class = constantize(options.fetch(:class, key))
|
23
|
-
|
23
|
+
def cast(value)
|
24
24
|
case value
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
when klass
|
26
|
+
value
|
27
|
+
else
|
28
|
+
super
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
private
|
33
|
+
|
34
|
+
def klass
|
35
|
+
klass_name = options.fetch(:class, name).to_s.classify
|
36
|
+
klass_name.constantize
|
37
|
+
rescue NameError
|
38
|
+
raise InvalidClassError, klass_name.inspect
|
38
39
|
end
|
39
|
-
private_class_method :constantize
|
40
40
|
end
|
41
41
|
end
|
@@ -3,25 +3,36 @@ module ActiveInteraction
|
|
3
3
|
# Creates accessors for the attributes and ensures that values passed to
|
4
4
|
# the attributes are Strings.
|
5
5
|
#
|
6
|
-
# @macro
|
7
|
-
# @option options [Boolean] :strip (true)
|
8
|
-
# whitespace
|
6
|
+
# @macro filter_method_params
|
7
|
+
# @option options [Boolean] :strip (true) strip leading and trailing
|
8
|
+
# whitespace
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
# string :first_name
|
12
12
|
#
|
13
|
+
# @example
|
14
|
+
# string :first_name, strip: false
|
15
|
+
#
|
16
|
+
# @since 0.1.0
|
17
|
+
#
|
13
18
|
# @method self.string(*attributes, options = {})
|
14
19
|
end
|
15
20
|
|
16
21
|
# @private
|
17
22
|
class StringFilter < Filter
|
18
|
-
def
|
23
|
+
def cast(value)
|
19
24
|
case value
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
when String
|
26
|
+
strip? ? value.strip : value
|
27
|
+
else
|
28
|
+
super
|
24
29
|
end
|
25
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def strip?
|
35
|
+
options.fetch(:strip, true)
|
36
|
+
end
|
26
37
|
end
|
27
38
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActiveInteraction
|
2
|
+
class Base
|
3
|
+
# Creates accessors for the attributes and ensures that values passed to
|
4
|
+
# the attributes are Symbols. Strings will be converted to Symbols.
|
5
|
+
#
|
6
|
+
# @macro filter_method_params
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# symbol :condiment
|
10
|
+
#
|
11
|
+
# @since 0.6.0
|
12
|
+
#
|
13
|
+
# @method self.symbol(*attributes, options = {})
|
14
|
+
end
|
15
|
+
|
16
|
+
# @private
|
17
|
+
class SymbolFilter < Filter
|
18
|
+
def cast(value)
|
19
|
+
case value
|
20
|
+
when Symbol
|
21
|
+
value
|
22
|
+
when String
|
23
|
+
value.to_sym
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|