coercive 1.1.0 → 1.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3eee84a8970b92e6b5d1b0e01e51a40c66cc0c7298b0fe37a6ea44aecd7b9064
4
- data.tar.gz: 9504d35e8ce6376fd821110a15d079783f723af1ae78606fa7fd2e565c053487
3
+ metadata.gz: 7ffc4474a94a2f1e246925e54549fdbf360fdc272ebdb670a99152b7ec6418b9
4
+ data.tar.gz: 92bdc78e8286dce0ce88464b843777f3c7b60bbb864a4c3daca3e3b80a9d6c8c
5
5
  SHA512:
6
- metadata.gz: 41fef05cb7a8c6a1d2f9b7f0f3737d76c5756a36903d6e2c45d028fb539d4de50f9ac0720b07e4262b97df2ff187638e0cf6d5fef4692d470ddc9484e00a9b57
7
- data.tar.gz: 94c3e1e38e740c7089d8913977fbd1feea04d1df592d918c76b46be18c53787c95d36fed451a39191781db63718a941f31d53b4ac56d960384e1e854ed4d6066
6
+ metadata.gz: 7a41ea8301735ce0b45d4c6d2e96a9e8c0bb06399c8b4f47be1f115d8996c640714a36e7211d4abc73e5ca40944f9be387b31eed0e9c8b22f7e859f10bd59480
7
+ data.tar.gz: e9f73c7c476d50e49bfbc7433d3b9da14541999a92582462e5ca1042ef80743a748ce83af2eb418ffb54ec393d4196cba1a49f5f5008aa4c20907918af915e7d
data/README.md CHANGED
@@ -128,6 +128,30 @@ CoerceFoo.call("foo" => "DEADBEEF")
128
128
  # => {"foo"=>"DEADBEEF"}
129
129
  ```
130
130
 
131
+ ### `date` and `datetime`
132
+
133
+ The `date` and `datetime` coercion functions will receive a `String` and give you `Date` and `DateTime` objects, respectively.
134
+
135
+ By default they expect an ISO 8601 string, but they provide a `format` option in case you need to parse something different, following the `strftime` format.
136
+
137
+ ```ruby
138
+ module CoerceFoo
139
+ extend Coercive
140
+
141
+ attribute :date_foo, date, optional
142
+ attribute :american_date, date(format: "%m-%d-%Y"), optional
143
+ attribute :datetime_foo, datetime, optional
144
+ end
145
+
146
+ CoerceFoo.call("date_foo" => "1988-05-18", "datetime_foo" => "1988-05-18T21:00:00Z", "american_date" => "05-18-1988")
147
+ # => {"date_foo"=>#<Date: 1988-05-18 ((2447300j,0s,0n),+0s,2299161j)>,
148
+ # "american_date"=>#<Date: 1988-05-18 ((2447300j,0s,0n),+0s,2299161j)>,
149
+ # "datetime_foo"=>#<DateTime: 1988-05-18T21:00:00+00:00 ((2447300j,75600s,0n),+0s,2299161j)>}
150
+
151
+ CoerceFoo.call("date_foo" => "18th May 1988")
152
+ # => Coercive::Error: {"date_foo"=>"not_valid"}
153
+ ```
154
+
131
155
  ### `any`
132
156
 
133
157
  The `any` coercion function lets anything pass through. It's commonly used with the `optional` fetch function when an attribute may or many not be a part of the input.
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "coercive"
3
- s.version = "1.1.0"
3
+ s.version = "1.2.0"
4
4
  s.summary = "Coercive is a library to validate and coerce user input"
5
5
  s.description = s.summary
6
6
  s.authors = ["Joe McIlvain", "Lucas Tolchinsky"]
@@ -1,3 +1,4 @@
1
+ require "date"
1
2
  require_relative "coercive/uri"
2
3
 
3
4
  # Public: The Coercive module implements a succinct DSL for declaring callable
@@ -192,6 +193,48 @@ module Coercive
192
193
  end
193
194
  end
194
195
 
196
+ # Public DSL: Return a coercion function to coerce input into a Date.
197
+ # Used when declaring an attribute. See documentation for attr_coerce_fns.
198
+ #
199
+ # format - String following Ruby's `strftime` format to change the parsing behavior. When empty
200
+ # it will expect the String to be ISO 8601 compatible.
201
+ def date(format: nil)
202
+ ->(input) do
203
+ input = begin
204
+ if format
205
+ Date.strptime(input, format)
206
+ else
207
+ Date.iso8601(input)
208
+ end
209
+ rescue ArgumentError
210
+ fail Coercive::Error.new("not_valid")
211
+ end
212
+
213
+ input
214
+ end
215
+ end
216
+
217
+ # Public DSL: Return a coercion function to coerce input into a DateTime.
218
+ # Used when declaring an attribute. See documentation for attr_coerce_fns.
219
+ #
220
+ # format - String following Ruby's `strftime` format to change the parsing behavior. When empty
221
+ # it will expect the String to be ISO 8601 compatible.
222
+ def datetime(format: nil)
223
+ ->(input) do
224
+ input = begin
225
+ if format
226
+ DateTime.strptime(input, format)
227
+ else
228
+ DateTime.iso8601(input)
229
+ end
230
+ rescue ArgumentError
231
+ fail Coercive::Error.new("not_valid")
232
+ end
233
+
234
+ input
235
+ end
236
+ end
237
+
195
238
  # Public DSL: Return a coercion function to coerce input to an Array.
196
239
  # Used when declaring an attribute. See documentation for attr_coerce_fns.
197
240
  #
@@ -199,6 +199,84 @@ describe "Coercive" do
199
199
  end
200
200
  end
201
201
 
202
+ describe "date" do
203
+ before do
204
+ @coercion = Module.new do
205
+ extend Coercive
206
+
207
+ attribute :date, date, optional
208
+ attribute :american_date, date(format: "%m-%d-%Y"), optional
209
+ end
210
+ end
211
+
212
+ it "coerces a string into a Date object with ISO 8601 format by default" do
213
+ attributes = { "date" => "1988-05-18" }
214
+
215
+ expected = { "date" => Date.new(1988, 5, 18) }
216
+
217
+ assert_equal expected, @coercion.call(attributes)
218
+ end
219
+
220
+ it "supports a custom date format" do
221
+ attributes = { "american_date" => "05-18-1988" }
222
+
223
+ expected = { "american_date" => Date.new(1988, 5, 18) }
224
+
225
+ assert_equal expected, @coercion.call(attributes)
226
+ end
227
+
228
+ it "errors if the input doesn't parse" do
229
+ attributes = { "date" => "12-31-1990" }
230
+
231
+ expected_errors = { "date" => "not_valid" }
232
+
233
+ assert_coercion_error(expected_errors) { @coercion.call(attributes) }
234
+ end
235
+ end
236
+
237
+ describe "datetime" do
238
+ before do
239
+ @coercion = Module.new do
240
+ extend Coercive
241
+
242
+ attribute :datetime, datetime, optional
243
+ attribute :american_date, datetime(format: "%m-%d-%Y %I:%M:%S %p"), optional
244
+ end
245
+ end
246
+
247
+ it "coerces a string into a DateTime object with ISO 8601 format by default" do
248
+ attributes = { "datetime" => "1988-05-18T21:00:00Z" }
249
+
250
+ expected = { "datetime" => DateTime.new(1988, 5, 18, 21, 00, 00) }
251
+
252
+ assert_equal expected, @coercion.call(attributes)
253
+ end
254
+
255
+ it "honors the timezone" do
256
+ attributes = { "datetime" => "1988-05-18T21:00:00-0300" }
257
+
258
+ expected = { "datetime" => DateTime.new(1988, 5, 18, 21, 00, 00, "-03:00") }
259
+
260
+ assert_equal expected, @coercion.call(attributes)
261
+ end
262
+
263
+ it "supports a custom date format" do
264
+ attributes = { "american_date" => "05-18-1988 09:00:00 PM" }
265
+
266
+ expected = { "american_date" => DateTime.new(1988, 5, 18, 21, 00, 00) }
267
+
268
+ assert_equal expected, @coercion.call(attributes)
269
+ end
270
+
271
+ it "errors if the input doesn't parse" do
272
+ attributes = { "datetime" => "12-31-1990T21:00:00Z" }
273
+
274
+ expected_errors = { "datetime" => "not_valid" }
275
+
276
+ assert_coercion_error(expected_errors) { @coercion.call(attributes) }
277
+ end
278
+ end
279
+
202
280
  describe "array" do
203
281
  before do
204
282
  @coercion = Module.new do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coercive
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe McIlvain
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-08-13 00:00:00.000000000 Z
12
+ date: 2020-08-31 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Coercive is a library to validate and coerce user input
15
15
  email: