-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expand parameter validation to type DateTime #689
Comments
+1 |
3 similar comments
+1 |
+1 |
+1 |
Can you give more details? +1 |
More details? |
up |
@dblock Coercion is currently done via Virtus which brings along some interesting consequences. For example Virtus::Attribute.build(DateTime).coerce(1234) #=> #<DateTime: 1970-01-01T00:20:34+00:00 ((2440588j,1234s,0n),+0s,2299161j)>
Virtus::Attribute.build(Date).coerce(1234) #=> 1234
Virtus::Attribute.build(Time).coerce(1234) #=> 1234 and Virtus::Attribute.build(DateTime).coerce('1234') #=> "1234"
Virtus::Attribute.build(Date).coerce('1234') #=> "1234"
Virtus::Attribute.build(Time).coerce('1234') #=> "1234" There are several options here. One is to augment Grape to handle such cases. Another is to fix Virtus to handle these better. In any case, in my opinion, Grape should somehow be aware that coercion actually failed, i.e. that you demanded a Validations are a different beast. The a = DateTime.new(2015,1,1,0,0,0); b = DateTime.new(2015,2,1,0,0,0); c = DateTime.new(2015,1,10,0,0,0)
(a..b).include?(c) #=> true but these do not a = DateTime.new(2015,1,1,0,0,0); b = DateTime.new(2015,1,1,10,0,0); c = DateTime.new(2015,1,1,5,0,0)
(a..b).include?(c) #=> false
a = Time.new(2015,1,1,0,0,0); b = Time.new(2015,2,1,0,0,0); c = Time.new(2015,1,10,0,0,0)
(a..b).include?(c) #=> TypeError One possible thing to do here would be to use the a = DateTime.new(2015,1,1,0,0,0); b = DateTime.new(2015,2,1,0,0,0); c = DateTime.new(2015,1,10,0,0,0)
c.between?(a,b) #=> true
a = DateTime.new(2015,1,1,0,0,0); b = DateTime.new(2015,1,1,10,0,0); c = DateTime.new(2015,1,1,5,0,0)
c.between?(a,b) #=> true
a = Time.new(2015,1,1,0,0,0); b = Time.new(2015,2,1,0,0,0); c = Time.new(2015,1,10,0,0,0)
c.between?(a,b) #=> true which is what I did here. That is, I implemented a params do
requires :id, type: Integer, between: 5..9, default: 7
optional :created_at, type: DateTime, between: [DateTime.new(2014,1,1), DateTime.new(2015,1,1)]
optional :price, type: Float, between: [0.0, -> { rand(5.5..9.9) }]
end The implementation is pretty rough at the moment, I mainly wanted to see what you guys think about the proposed DSL. (That is why I haven't updated the documentation and/or created a PR, yet.) Looking further, a possible way would be to have a single class (that iterates across passed params and validation values) for validations which would get the criteria (different test functions) injected as a dependency. This way, it would be somewhat easy to create additional validators. Finally, a remark and a question. If I run the entire test suite, the specs pass, but if I try to run particular tests in isolation, some of them fail. Cf.: bundle exec rspec spec/grape/validations/params_scope_spec.rb (I'm using Ruby 2.1.5 and RSpec 3.3.0). And why are validators (and also other things) tested via integration and not unit specs? I would expect a validator spec to set up a validator class with the desired arguments and then expect the Lots to discuss here, I guess. |
That seems like a reasonable statement. So probably when parameter validation fails, it would include a coercion error? Lets look at your Feel free to PR a fix for the running of a standalone spec and refactoring of said specs as you see better, of course. |
Right. So, Regarding the validators' specs, my idea of how these should look like is something along the following lines it 'fails in a particular scenario' do
attrs = ...
opts = ...
required = ...
scope = ...
validator = Grape::Validations::ValuesValidator.new(attrs, opts, required, scope)
expect{ validator.validate! }.to raise_error Grape::Exceptions::Validation
end By going through the requests, things are slower and not isolated to the point one would, in my opinion, want. And I suspect there might be some problems because of this already (e.g. Finally, I think there are problems with tests isolation in general. Please, compare
with (at least in my case seed 35635 raises two errors)
but also
where I get different errors than in the second case. This should be sorted out first, I would add the |
Yes, please at least open an issue. |
Addresses ruby-grape#1164, ruby-grape#690, ruby-grape#689, ruby-grape#693. Depends on solnic/virtus#343 `Grape::ParameterTypes` is renamed `Grape::Validations::Types` to reflect that it should probably be bundled with an eventual `grape-validations` gem. It is expanded to include two new categories of types, 'special' and 'recognized' (see 'lib/grape/validations/types.rb'). `CoerceValidator` now makes use of `Virtus::Attribute::value_coerced?`, simplifying its internals. `CustomTypeCoercer` is introduced, attempting to standardize support for custom types by decoupling coercion and type-checking logic from the `type` class supplied to `Grape::Dsl::Parameters::requires`. `JSON`, `Array[JSON]` and `Rack::Multipart::UploadedFile (a.k.a `File`) are designated 'special' types, for which special implementations of `Virtus::Attribute` are provided. Instances of `Virtus::Attribute` built with `Virtus::Attribute.build` may now also be passed as the `type` parameter for `requires`. A number of pre-rolled attributes are available providing coercion for `Date` and `DateTime` objects from various formats in `lib/grape/validations/types/date.rb` and `date_time.rb`.
Addresses ruby-grape#1164, ruby-grape#690, ruby-grape#689, ruby-grape#693. Depends on solnic/virtus#343 `Grape::ParameterTypes` is renamed `Grape::Validations::Types` to reflect that it should probably be bundled with an eventual `grape-validations` gem. It is expanded to include two new categories of types, 'special' and 'recognized' (see 'lib/grape/validations/types.rb'). `CoerceValidator` now makes use of `Virtus::Attribute::value_coerced?`, simplifying its internals. `CustomTypeCoercer` is introduced, attempting to standardize support for custom types by decoupling coercion and type-checking logic from the `type` class supplied to `Grape::Dsl::Parameters::requires`. `JSON`, `Array[JSON]` and `Rack::Multipart::UploadedFile (a.k.a `File`) are designated 'special' types, for which special implementations of `Virtus::Attribute` are provided. Instances of `Virtus::Attribute` built with `Virtus::Attribute.build` may now also be passed as the `type` parameter for `requires`. A number of pre-rolled attributes are available providing coercion for `Date` and `DateTime` objects from various formats in `lib/grape/validations/types/date.rb` and `date_time.rb`.
Addresses ruby-grape#1164, ruby-grape#690, ruby-grape#689, ruby-grape#693. Depends on solnic/virtus#343 `Grape::ParameterTypes` is renamed `Grape::Validations::Types` to reflect that it should probably be bundled with an eventual `grape-validations` gem. It is expanded to include two new categories of types, 'special' and 'recognized' (see 'lib/grape/validations/types.rb'). `CoerceValidator` now makes use of `Virtus::Attribute::value_coerced?`, simplifying its internals. `CustomTypeCoercer` is introduced, attempting to standardize support for custom types by decoupling coercion and type-checking logic from the `type` class supplied to `Grape::Dsl::Parameters::requires`. `JSON`, `Array[JSON]` and `Rack::Multipart::UploadedFile (a.k.a `File`) are designated 'special' types, for which special implementations of `Virtus::Attribute` are provided. Instances of `Virtus::Attribute` built with `Virtus::Attribute.build` may now also be passed as the `type` parameter for `requires`. A number of pre-rolled attributes are available providing coercion for `Date` and `DateTime` objects from various formats in `lib/grape/validations/types/date.rb` and `date_time.rb`.
Addresses ruby-grape#1164, ruby-grape#690, ruby-grape#689, ruby-grape#693. Depends on solnic/virtus#343 `Grape::ParameterTypes` is renamed `Grape::Validations::Types` to reflect that it should probably be bundled with an eventual `grape-validations` gem. It is expanded to include two new categories of types, 'special' and 'recognized' (see 'lib/grape/validations/types.rb'). `CoerceValidator` now makes use of `Virtus::Attribute::value_coerced?`, simplifying its internals. `CustomTypeCoercer` is introduced, attempting to standardize support for custom types by decoupling coercion and type-checking logic from the `type` class supplied to `Grape::Dsl::Parameters::requires`. The process for inferring which logic to use for each type and coercion method is encoded in `lib/grape/validations/types/build_coercer.rb`. `JSON`, `Array[JSON]` and `Rack::Multipart::UploadedFile (a.k.a `File`) are designated 'special' types, for which special implementations of `Virtus::Attribute` are provided. Instances of `Virtus::Attribute` built with `Virtus::Attribute.build` may now also be passed as the `type` parameter for `requires`. A number of pre-rolled attributes are available providing coercion for `Date` and `DateTime` objects from various formats in `lib/grape/validations/formats/date.rb` and `date_time.rb`.
Addresses ruby-grape#1164, ruby-grape#690, ruby-grape#689, ruby-grape#693. `Grape::ParameterTypes` is renamed `Grape::Validations::Types` to reflect that it should probably be bundled with an eventual `grape-validations` gem. It is expanded to include two new categories of types, 'special' and 'recognized' (see 'lib/grape/validations/types.rb'). `CoerceValidator` now makes use of `Virtus::Attribute::value_coerced?`, simplifying its internals. `CustomTypeCoercer` is introduced, attempting to standardize support for custom types by decoupling coercion and type-checking logic from the `type` class supplied to `Grape::Dsl::Parameters::requires`. The process for inferring which logic to use for each type and coercion method is encoded in `lib/grape/validations/types/build_coercer.rb`. `JSON`, `Array[JSON]` and `Rack::Multipart::UploadedFile (a.k.a `File`) are designated 'special' types, for which special implementations of `Virtus::Attribute` are provided. Instances of `Virtus::Attribute` built with `Virtus::Attribute.build` may now also be passed as the `type` parameter for `requires`. A number of pre-rolled attributes are available providing coercion for `Date` and `DateTime` objects from various formats in `lib/grape/validations/formats/date.rb` and `date_time.rb`. Depends on a monkey patch to `Virtus::Attribute::Collection`, included in `lib/grape/validations/types/virtus_collection_patch.rb`. See pull request 343 on solnic/virtus for more details.
Addresses ruby-grape#1164, ruby-grape#690, ruby-grape#689, ruby-grape#693. `Grape::ParameterTypes` is renamed `Grape::Validations::Types` to reflect that it should probably be bundled with an eventual `grape-validations` gem. It is expanded to include two new categories of types, 'special' and 'recognized' (see 'lib/grape/validations/types.rb'). `CoerceValidator` now makes use of `Virtus::Attribute::value_coerced?`, simplifying its internals. `CustomTypeCoercer` is introduced, attempting to standardize support for custom types by decoupling coercion and type-checking logic from the `type` class supplied to `Grape::Dsl::Parameters::requires`. The process for inferring which logic to use for each type and coercion method is encoded in `lib/grape/validations/types/build_coercer.rb`. `JSON`, `Array[JSON]` and `Rack::Multipart::UploadedFile (a.k.a `File`) are designated 'special' types, for which special implementations of `Virtus::Attribute` are provided. Instances of `Virtus::Attribute` built with `Virtus::Attribute.build` may now also be passed as the `type` parameter for `requires`. Depends on a monkey patch to `Virtus::Attribute::Collection`, included in `lib/grape/validations/types/virtus_collection_patch.rb`. See pull request 343 on solnic/virtus for more details.
I've bundled up some code that was cut from #1167 into its own project, grape-formats. It provides some tokens that can be used for the There's no gem released yet since it depends on unreleased changes to grape itself, and anyway would be good to get some feedback or hear if there's any interest. It's so small it barely seems worth the time but it could be a good starting point for a collection of various ISO/RFC formats and so on. Note that at this point you can also just drop the |
I think it looks great. |
@dblock I believe this one doesn't require any work any more, Date and DateTime implement the parse method, so they can be used as custom types. class API < Grape::API
prefix :api
version 'v1', using: :path
params do
requires :datetime, type: DateTime
requires :date, type: Date
end
post '/' do
declared = declared(params)
puts declared[:datetime].inspect
puts declared[:date].inspect
end
end Input: {
datetime: '3rd Feb 2020 04:05:06 PM',
date: '2020-10-01'
} Output:
Output in case of invalid values:
|
Dates may be posted as Integer, ISO strings, Date, DateTime, etc.
The text was updated successfully, but these errors were encountered: