coercible 0.0.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.
Files changed (99) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +19 -0
  4. data/Changelog.md +4 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.devtools +44 -0
  7. data/Guardfile +58 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +64 -0
  10. data/Rakefile +2 -0
  11. data/coercible.gemspec +22 -0
  12. data/config/flay.yml +3 -0
  13. data/config/flog.yml +2 -0
  14. data/config/mutant.yml +3 -0
  15. data/config/roodi.yml +17 -0
  16. data/config/site.reek +91 -0
  17. data/config/yardstick.yml +2 -0
  18. data/lib/coercible.rb +42 -0
  19. data/lib/coercible/coercer.rb +155 -0
  20. data/lib/coercible/coercer/array.rb +24 -0
  21. data/lib/coercible/coercer/configurable.rb +54 -0
  22. data/lib/coercible/coercer/date.rb +27 -0
  23. data/lib/coercible/coercer/date_time.rb +27 -0
  24. data/lib/coercible/coercer/decimal.rb +41 -0
  25. data/lib/coercible/coercer/false_class.rb +25 -0
  26. data/lib/coercible/coercer/float.rb +40 -0
  27. data/lib/coercible/coercer/hash.rb +72 -0
  28. data/lib/coercible/coercer/integer.rb +130 -0
  29. data/lib/coercible/coercer/numeric.rb +67 -0
  30. data/lib/coercible/coercer/object.rb +160 -0
  31. data/lib/coercible/coercer/string.rb +251 -0
  32. data/lib/coercible/coercer/symbol.rb +25 -0
  33. data/lib/coercible/coercer/time.rb +41 -0
  34. data/lib/coercible/coercer/time_coercions.rb +87 -0
  35. data/lib/coercible/coercer/true_class.rb +25 -0
  36. data/lib/coercible/configuration.rb +33 -0
  37. data/lib/coercible/version.rb +3 -0
  38. data/lib/support/options.rb +113 -0
  39. data/lib/support/type_lookup.rb +113 -0
  40. data/spec/integration/configuring_coercers_spec.rb +14 -0
  41. data/spec/shared/unit/configurable.rb +27 -0
  42. data/spec/spec_helper.rb +30 -0
  43. data/spec/unit/coercible/coercer/array/to_set_spec.rb +12 -0
  44. data/spec/unit/coercible/coercer/class_methods/new_spec.rb +13 -0
  45. data/spec/unit/coercible/coercer/date/to_date_spec.rb +10 -0
  46. data/spec/unit/coercible/coercer/date/to_datetime_spec.rb +30 -0
  47. data/spec/unit/coercible/coercer/date/to_string_spec.rb +12 -0
  48. data/spec/unit/coercible/coercer/date/to_time_spec.rb +12 -0
  49. data/spec/unit/coercible/coercer/date_time/to_date_spec.rb +30 -0
  50. data/spec/unit/coercible/coercer/date_time/to_datetime_spec.rb +10 -0
  51. data/spec/unit/coercible/coercer/date_time/to_string_spec.rb +12 -0
  52. data/spec/unit/coercible/coercer/date_time/to_time_spec.rb +30 -0
  53. data/spec/unit/coercible/coercer/decimal/to_decimal_spec.rb +9 -0
  54. data/spec/unit/coercible/coercer/decimal/to_float_spec.rb +12 -0
  55. data/spec/unit/coercible/coercer/decimal/to_integer_spec.rb +12 -0
  56. data/spec/unit/coercible/coercer/decimal/to_string_spec.rb +12 -0
  57. data/spec/unit/coercible/coercer/element_reference_spec.rb +19 -0
  58. data/spec/unit/coercible/coercer/false_class/to_string_spec.rb +12 -0
  59. data/spec/unit/coercible/coercer/float/to_decimal_spec.rb +12 -0
  60. data/spec/unit/coercible/coercer/float/to_float_spec.rb +9 -0
  61. data/spec/unit/coercible/coercer/float/to_integer_spec.rb +12 -0
  62. data/spec/unit/coercible/coercer/float/to_string_spec.rb +12 -0
  63. data/spec/unit/coercible/coercer/hash/to_date_spec.rb +38 -0
  64. data/spec/unit/coercible/coercer/hash/to_datetime_spec.rb +38 -0
  65. data/spec/unit/coercible/coercer/hash/to_time_spec.rb +38 -0
  66. data/spec/unit/coercible/coercer/integer/to_boolean_spec.rb +27 -0
  67. data/spec/unit/coercible/coercer/integer/to_decimal_spec.rb +12 -0
  68. data/spec/unit/coercible/coercer/integer/to_float_spec.rb +12 -0
  69. data/spec/unit/coercible/coercer/integer/to_integer_spec.rb +9 -0
  70. data/spec/unit/coercible/coercer/integer/to_string_spec.rb +12 -0
  71. data/spec/unit/coercible/coercer/integer_spec.rb +11 -0
  72. data/spec/unit/coercible/coercer/numeric/to_decimal_spec.rb +10 -0
  73. data/spec/unit/coercible/coercer/numeric/to_float_spec.rb +10 -0
  74. data/spec/unit/coercible/coercer/numeric/to_integer_spec.rb +10 -0
  75. data/spec/unit/coercible/coercer/numeric/to_string_spec.rb +12 -0
  76. data/spec/unit/coercible/coercer/object/to_array_spec.rb +51 -0
  77. data/spec/unit/coercible/coercer/object/to_hash_spec.rb +22 -0
  78. data/spec/unit/coercible/coercer/object/to_integer_spec.rb +22 -0
  79. data/spec/unit/coercible/coercer/object/to_string_spec.rb +22 -0
  80. data/spec/unit/coercible/coercer/string/to_boolean_spec.rb +31 -0
  81. data/spec/unit/coercible/coercer/string/to_constant_spec.rb +49 -0
  82. data/spec/unit/coercible/coercer/string/to_date_spec.rb +25 -0
  83. data/spec/unit/coercible/coercer/string/to_datetime_spec.rb +52 -0
  84. data/spec/unit/coercible/coercer/string/to_decimal_spec.rb +47 -0
  85. data/spec/unit/coercible/coercer/string/to_float_spec.rb +57 -0
  86. data/spec/unit/coercible/coercer/string/to_integer_spec.rb +68 -0
  87. data/spec/unit/coercible/coercer/string/to_symbol_spec.rb +9 -0
  88. data/spec/unit/coercible/coercer/string/to_time_spec.rb +52 -0
  89. data/spec/unit/coercible/coercer/string_spec.rb +11 -0
  90. data/spec/unit/coercible/coercer/symbol/to_string_spec.rb +12 -0
  91. data/spec/unit/coercible/coercer/time/to_integer_spec.rb +10 -0
  92. data/spec/unit/coercible/coercer/time/to_time_spec.rb +10 -0
  93. data/spec/unit/coercible/coercer/time_coercions/to_date_spec.rb +30 -0
  94. data/spec/unit/coercible/coercer/time_coercions/to_datetime_spec.rb +34 -0
  95. data/spec/unit/coercible/coercer/time_coercions/to_string_spec.rb +19 -0
  96. data/spec/unit/coercible/coercer/time_coercions/to_time_spec.rb +34 -0
  97. data/spec/unit/coercible/coercer/true_class/to_string_spec.rb +12 -0
  98. data/spec/unit/coercible/configuration/class_methods/build_spec.rb +15 -0
  99. metadata +235 -0
@@ -0,0 +1,130 @@
1
+ module Coercible
2
+ class Coercer
3
+
4
+ # Coerce Fixnum values
5
+ class Integer < Numeric
6
+ extend Configurable
7
+
8
+ primitive ::Integer
9
+
10
+ config_keys [ :datetime_format, :datetime_proc, :boolean_map ]
11
+
12
+ # Return default config for Integer coercer type
13
+ #
14
+ # @return [Configuration]
15
+ #
16
+ # @see Configurable#config
17
+ #
18
+ # @api private
19
+ def self.config
20
+ # FIXME: Remove after Rubinius 2.0 is released
21
+ is_rbx = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
22
+
23
+ super do |config|
24
+ config.datetime_format = is_rbx ? '%Q' : '%s'
25
+
26
+ config.datetime_proc = is_rbx ?
27
+ Proc.new { |value| "#{value * 10**3}" } : Proc.new { |value| "#{value}" }
28
+
29
+ config.boolean_map = { 0 => false, 1 => true }
30
+ end
31
+ end
32
+
33
+ # Return datetime format from config
34
+ #
35
+ # @return [::String]
36
+ #
37
+ # @api private
38
+ attr_reader :datetime_format
39
+
40
+ # Return datetime proc from config
41
+ #
42
+ # @return [Proc]
43
+ #
44
+ # @api private
45
+ attr_reader :datetime_proc
46
+
47
+ # Return boolean map from config
48
+ #
49
+ # @return [::Hash]
50
+ #
51
+ # @api private
52
+ attr_reader :boolean_map
53
+
54
+ # Initialize a new Integer coercer instance and set its configuration
55
+ #
56
+ # @return [undefined]
57
+ #
58
+ # @api private
59
+ def initialize(coercer = Coercer.new, config = self.class.config)
60
+ super(coercer)
61
+ @boolean_map = config.boolean_map
62
+ @datetime_format = config.datetime_format
63
+ @datetime_proc = config.datetime_proc
64
+ end
65
+
66
+ # Coerce given value to String
67
+ #
68
+ # @example
69
+ # coercer[Integer].to_string(1) # => "1"
70
+ #
71
+ # @param [Fixnum] value
72
+ #
73
+ # @return [String]
74
+ #
75
+ # @api public
76
+ def to_string(value)
77
+ value.to_s
78
+ end
79
+
80
+ # Passthrough the value
81
+ #
82
+ # @example
83
+ # coercer[Integer].to_integer(1) # => 1
84
+ #
85
+ # @param [Fixnum] value
86
+ #
87
+ # @return [Float]
88
+ #
89
+ # @api public
90
+ def to_integer(value)
91
+ value
92
+ end
93
+
94
+ # Coerce given value to a Boolean
95
+ #
96
+ # @example with a 1
97
+ # coercer[Integer].to_boolean(1) # => true
98
+ #
99
+ # @example with a 0
100
+ # coercer[Integer].to_boolean(0) # => false
101
+ #
102
+ # @param [Fixnum] value
103
+ #
104
+ # @return [BigDecimal]
105
+ #
106
+ # @api public
107
+ def to_boolean(value)
108
+ boolean_map.fetch(value) {
109
+ raise_unsupported_coercion(value, __method__)
110
+ }
111
+ end
112
+
113
+ # Coerce given value to a DateTime
114
+ #
115
+ # @example
116
+ # coercer[Integer].to_datetime(0) # => Thu, 01 Jan 1970 00:00:00 +0000
117
+ #
118
+ # @param [Integer] value
119
+ #
120
+ # @return [DateTime]
121
+ #
122
+ # @api public
123
+ def to_datetime(value)
124
+ ::DateTime.strptime(datetime_proc.call(value), datetime_format)
125
+ end
126
+
127
+ end # class Fixnum
128
+
129
+ end # class Coercer
130
+ end # module Coercible
@@ -0,0 +1,67 @@
1
+ module Coercible
2
+ class Coercer
3
+
4
+ # Base class for all numeric Coercion classes
5
+ class Numeric < Object
6
+ primitive ::Numeric
7
+
8
+ # Coerce given value to String
9
+ #
10
+ # @example
11
+ # coercer[Numeric].to_string(Rational(2, 2)) # => "1.0"
12
+ #
13
+ # @param [Numeric] value
14
+ #
15
+ # @return [String]
16
+ #
17
+ # @api public
18
+ def to_string(value)
19
+ value.to_s
20
+ end
21
+
22
+ # Creates an Integer instance from a numeric object
23
+ #
24
+ # @example
25
+ # coercer[Numeric].to_integer(Rational(2, 2)) # => 1
26
+ #
27
+ # @param [Numeric] value
28
+ #
29
+ # @return [Integer]
30
+ #
31
+ # @api public
32
+ def to_integer(value)
33
+ value.to_i
34
+ end
35
+
36
+ # Creates a Float instance from a numeric object
37
+ #
38
+ # @example
39
+ # coercer[Numeric].to_float(Rational(2, 2)) # => 1.0
40
+ #
41
+ # @param [Numeric] value
42
+ #
43
+ # @return [Float]
44
+ #
45
+ # @api public
46
+ def to_float(value)
47
+ value.to_f
48
+ end
49
+
50
+ # Coerce a BigDecimal instance from a numeric object
51
+ #
52
+ # @example
53
+ # coercer[Numeric].to_decimal(Rational(2, 2)) # => BigDecimal('1.0')
54
+ #
55
+ # @param [Numeric] value
56
+ #
57
+ # @return [BigDecimal]
58
+ #
59
+ # @api public
60
+ def to_decimal(value)
61
+ to_string(value).to_d
62
+ end
63
+
64
+ end # class Numeric
65
+
66
+ end # class Coercer
67
+ end # module Coercible
@@ -0,0 +1,160 @@
1
+ module Coercible
2
+ class Coercer
3
+
4
+ # Coerce Object values
5
+ class Object
6
+ extend DescendantsTracker, TypeLookup, Options
7
+
8
+ accept_options :primitive
9
+
10
+ primitive ::Object
11
+
12
+ COERCION_METHOD_REGEXP = /\Ato_/.freeze
13
+
14
+ # Return coercers object
15
+ #
16
+ # @return [Coercer]
17
+ #
18
+ # @api private
19
+ attr_reader :coercers
20
+
21
+ # Initialize a new coercer instance
22
+ #
23
+ # @param [Coercer] coercers
24
+ #
25
+ # @return [undefined]
26
+ #
27
+ # @api private
28
+ def initialize(coercers = Coercer.new)
29
+ @coercers = coercers
30
+ end
31
+
32
+ # Create an Array from any Object
33
+ #
34
+ # @example with an object that does not respond to #to_a or #to_ary
35
+ # coercer[Object].to_array(value) # => [ value ]
36
+ #
37
+ # @example with an object that responds to #to_a
38
+ # coercer[Object].to_array(Set[ value ]) # => [ value ]
39
+ #
40
+ # @example with n object that responds to #to_ary
41
+ # coercer[Object].to_array([ value ]) # => [ value ]
42
+ #
43
+ # @param [#to_a,#to_ary,Object] value
44
+ # @param [#to_a,#to_ary,Object] value
45
+ #
46
+ # @return [Array]
47
+ #
48
+ # @api public
49
+ def to_array(value)
50
+ Array(value)
51
+ end
52
+
53
+ # Create a Hash from the Object if possible
54
+ #
55
+ # @example with a coercible object
56
+ # coercer[Object].to_hash(key => value) # => { key => value }
57
+ #
58
+ # @example with an object that is not coercible
59
+ # coercer[Object].to_hash(value) # => value
60
+ #
61
+ # @param [#to_hash, Object] value
62
+ #
63
+ # @return [Hash]
64
+ # returns a Hash when the object can be coerced
65
+ # @return [Object]
66
+ # returns the value when the object cannot be coerced
67
+ #
68
+ # @api public
69
+ def to_hash(value)
70
+ coerce_with_method(value, :to_hash)
71
+ end
72
+
73
+ # Create a String from the Object if possible
74
+ #
75
+ # @example with a coercible object
76
+ # coercer[Object].to_string("string") # => "string"
77
+ #
78
+ # @example with an object that is not coercible
79
+ # coercer[Object].to_string(value) # => value
80
+ #
81
+ # @param [#to_str, Object] value
82
+ #
83
+ # @return [String]
84
+ # returns a String when the object can be coerced
85
+ # @return [Object]
86
+ # returns the value when the object cannot be coerced
87
+ #
88
+ # @api public
89
+ def to_string(value)
90
+ coerce_with_method(value, :to_str)
91
+ end
92
+
93
+ # Create an Integer from the Object if possible
94
+ #
95
+ # @example with a coercible object
96
+ # coercer[Object].to_integer(1) # => 1
97
+ #
98
+ # @example with an object that is not coercible
99
+ # coercer[Object].to_integer(value) # => value
100
+ #
101
+ # @param [#to_int, Object] value
102
+ #
103
+ # @return [Integer]
104
+ # returns an Integer when the object can be coerced
105
+ # @return [Object]
106
+ # returns the value when the object cannot be coerced
107
+ #
108
+ # @api public
109
+ def to_integer(value)
110
+ coerce_with_method(value, :to_int)
111
+ end
112
+
113
+ private
114
+
115
+ # Raise an unsupported coercion error
116
+ #
117
+ # @raises [UnsupportedCoercion]
118
+ #
119
+ # @return [undefined]
120
+ #
121
+ # @api private
122
+ def raise_unsupported_coercion(value, method)
123
+ raise(
124
+ UnsupportedCoercion,
125
+ "#{self.class}##{method} doesn't know how to coerce #{value.inspect}"
126
+ )
127
+ end
128
+
129
+ # Passthrough given value
130
+ #
131
+ # @param [Object] value
132
+ #
133
+ # @return [Object]
134
+ #
135
+ # @api private
136
+ def method_missing(method, *args)
137
+ if method.to_s =~ COERCION_METHOD_REGEXP and args.size == 1
138
+ args.first
139
+ else
140
+ super
141
+ end
142
+ end
143
+
144
+ # Try to use native coercion method on the given value
145
+ #
146
+ # @param [Object] value
147
+ #
148
+ # @param [Symbol] method
149
+ #
150
+ # @return [Object]
151
+ #
152
+ # @api private
153
+ def coerce_with_method(value, method)
154
+ value.respond_to?(method) ? value.public_send(method) : value
155
+ end
156
+
157
+ end # class Object
158
+
159
+ end # class Coercer
160
+ end # module Coercible
@@ -0,0 +1,251 @@
1
+ module Coercible
2
+ class Coercer
3
+
4
+ # Coerce String values
5
+ class String < Object
6
+ extend Configurable
7
+
8
+ primitive ::String
9
+
10
+ config_keys [ :boolean_map ]
11
+
12
+ TRUE_VALUES = %w[ 1 on t true y yes ].freeze
13
+ FALSE_VALUES = %w[ 0 off f false n no ].freeze
14
+ BOOLEAN_MAP = ::Hash[ TRUE_VALUES.product([ true ]) + FALSE_VALUES.product([ false ]) ].freeze
15
+
16
+ INTEGER_REGEXP = /[-+]?(?:[0-9]\d*)/.freeze
17
+ EXPONENT_REGEXP = /(?:[eE][-+]?\d+)/.freeze
18
+ FRACTIONAL_REGEXP = /(?:\.\d+)/.freeze
19
+
20
+ NUMERIC_REGEXP = /\A(
21
+ #{INTEGER_REGEXP}#{FRACTIONAL_REGEXP}?#{EXPONENT_REGEXP}? |
22
+ #{FRACTIONAL_REGEXP}#{EXPONENT_REGEXP}?
23
+ )\z/x.freeze
24
+
25
+ # Return default configuration for string coercer type
26
+ #
27
+ # @return [Configuration]
28
+ #
29
+ # @api private
30
+ def self.config
31
+ super { |config| config.boolean_map = BOOLEAN_MAP }
32
+ end
33
+
34
+ # Return boolean map from the config
35
+ #
36
+ # @return [::Hash]
37
+ #
38
+ # @api private
39
+ attr_reader :boolean_map
40
+
41
+ # Initialize a new string coercer instance
42
+ #
43
+ # @param [Coercer]
44
+ #
45
+ # @param [Configuration]
46
+ #
47
+ # @return [undefined]
48
+ #
49
+ # @api private
50
+ def initialize(coercer = Coercer.new, config = self.class.config)
51
+ super(coercer)
52
+ @boolean_map = config.boolean_map
53
+ end
54
+
55
+ # Coerce give value to a constant
56
+ #
57
+ # @example
58
+ # coercer[String].to_constant('String') # => String
59
+ #
60
+ # @param [String] value
61
+ #
62
+ # @return [Object]
63
+ #
64
+ # @api public
65
+ def to_constant(value)
66
+ names = value.split('::')
67
+ names.shift if names.first.empty?
68
+ names.inject(::Object) { |*args| constant_lookup(*args) }
69
+ end
70
+
71
+ # Coerce give value to a symbol
72
+ #
73
+ # @example
74
+ # coercer[String].to_symbol('string') # => :string
75
+ #
76
+ # @param [String] value
77
+ #
78
+ # @return [Symbol]
79
+ #
80
+ # @api public
81
+ def to_symbol(value)
82
+ value.to_sym
83
+ end
84
+
85
+ # Coerce given value to Time
86
+ #
87
+ # @example
88
+ # coercer[String].to_time(string) # => Time object
89
+ #
90
+ # @param [String] value
91
+ #
92
+ # @return [Time]
93
+ #
94
+ # @api public
95
+ def to_time(value)
96
+ parse_value(::Time, value, __method__)
97
+ end
98
+
99
+ # Coerce given value to Date
100
+ #
101
+ # @example
102
+ # coercer[String].to_date(string) # => Date object
103
+ #
104
+ # @param [String] value
105
+ #
106
+ # @return [Date]
107
+ #
108
+ # @api public
109
+ def to_date(value)
110
+ parse_value(::Date, value, __method__)
111
+ end
112
+
113
+ # Coerce given value to DateTime
114
+ #
115
+ # @example
116
+ # coercer[String].to_datetime(string) # => DateTime object
117
+ #
118
+ # @param [String] value
119
+ #
120
+ # @return [DateTime]
121
+ #
122
+ # @api public
123
+ def to_datetime(value)
124
+ parse_value(::DateTime, value, __method__)
125
+ end
126
+
127
+ # Coerce value to TrueClass or FalseClass
128
+ #
129
+ # @example with "T"
130
+ # coercer[String].to_boolean('T') # => true
131
+ #
132
+ # @example with "F"
133
+ # coercer[String].to_boolean('F') # => false
134
+ #
135
+ # @param [#to_s]
136
+ #
137
+ # @return [Boolean]
138
+ #
139
+ # @api public
140
+ def to_boolean(value)
141
+ boolean_map.fetch(value.downcase) {
142
+ raise_unsupported_coercion(value, __method__)
143
+ }
144
+ end
145
+
146
+ # Coerce value to integer
147
+ #
148
+ # @example
149
+ # coercer[String].to_integer('1') # => 1
150
+ #
151
+ # @param [Object] value
152
+ #
153
+ # @return [Integer]
154
+ #
155
+ # @api public
156
+ def to_integer(value)
157
+ if value =~ /\A#{INTEGER_REGEXP}\z/
158
+ value.to_i
159
+ else
160
+ # coerce to a Float first to evaluate scientific notation (if any)
161
+ # that may change the integer part, then convert to an integer
162
+ coerced = to_float(value)
163
+ ::Float === coerced ? coerced.to_i : coerced
164
+ end
165
+ end
166
+
167
+ # Coerce value to float
168
+ #
169
+ # @example
170
+ # coercer[String].to_float('1.2') # => 1.2
171
+ #
172
+ # @param [Object] value
173
+ #
174
+ # @return [Float]
175
+ #
176
+ # @api public
177
+ def to_float(value)
178
+ to_numeric(value, :to_f)
179
+ end
180
+
181
+ # Coerce value to decimal
182
+ #
183
+ # @example
184
+ # coercer[String].to_decimal('1.2') # => #<BigDecimal:b72157d4,'0.12E1',8(8)>
185
+ #
186
+ # @param [Object] value
187
+ #
188
+ # @return [BigDecimal]
189
+ #
190
+ # @api public
191
+ def to_decimal(value)
192
+ to_numeric(value, :to_d)
193
+ end
194
+
195
+ private
196
+
197
+ # Lookup a constant within a module
198
+ #
199
+ # @param [Module] mod
200
+ #
201
+ # @param [String] name
202
+ #
203
+ # @return [Object]
204
+ #
205
+ # @api private
206
+ def constant_lookup(mod, name)
207
+ if mod.const_defined?(name, *EXTRA_CONST_ARGS)
208
+ mod.const_get(name, *EXTRA_CONST_ARGS)
209
+ else
210
+ mod.const_missing(name)
211
+ end
212
+ end
213
+
214
+ # Match numeric string
215
+ #
216
+ # @param [String] value
217
+ # value to typecast
218
+ # @param [Symbol] method
219
+ # method to typecast with
220
+ #
221
+ # @return [Numeric]
222
+ # number if matched, value if no match
223
+ #
224
+ # @api private
225
+ def to_numeric(value, method)
226
+ if value =~ NUMERIC_REGEXP
227
+ $1.public_send(method)
228
+ else
229
+ value
230
+ end
231
+ end
232
+
233
+ # Parse the value or return it as-is if it is invalid
234
+ #
235
+ # @param [#parse] parser
236
+ #
237
+ # @param [String] value
238
+ #
239
+ # @return [Time]
240
+ #
241
+ # @api private
242
+ def parse_value(parser, value, method)
243
+ parser.parse(value)
244
+ rescue ArgumentError
245
+ raise_unsupported_coercion(value, method)
246
+ end
247
+
248
+ end # class String
249
+
250
+ end # class Coercer
251
+ end # module Coercible