coercible 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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