-
-
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
Replace Virtus with dry-types #1920
Replace Virtus with dry-types #1920
Conversation
Following this, shout if you get stuck or need some help |
👀 |
Gemfile
Outdated
@@ -9,6 +9,7 @@ group :development, :test do | |||
gem 'hashie' | |||
gem 'rake' | |||
gem 'rubocop', '0.51.0' | |||
gem 'virtus' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can't be used at all in the final PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few tests which use Virtus to verify that it can be used as a custom type, it means I need to remove the 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I worry that we'll leave something that works in tests but not in prod. Maybe those can become integration tests with their own Gemfile?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, Virtus isn't needed anymore. I removed it and adjusted tests testing custom types 🙂
UPGRADING.md
Outdated
@@ -1,6 +1,39 @@ | |||
Upgrading Grape | |||
=============== | |||
|
|||
### Upgrading to >= 1.2.5 | |||
|
|||
[Virtus](https://github.com/solnic/virtus) isn't used for coercing anymore. If your project depends on Virtus, you have to add it to your `Gemfile`. Also, if Virtus is used as a custom type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simlify and shorten, "has been replaced by dry-types
for parameter coercion" and just ", add it to your Gemfile"
end | ||
end | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to explain how to rewrite a custom type with dry-types here, first. If I am upgrading I'd rather not use Virtus unless I can't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dry-types cannot be used in place of Virtus for custom types, dry-schema might be. So, if users need something like Virtus they need to keep it or migrate to dry-schema. I guess it is up to them to decide, the goal is to avoid breaking changes, so if they use Virtus, they can still use it until they have time to migrate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like you're saying that if you want a custom type you have to use Virtus? Or are you saying you can use Virtus? Either way let's make this very clear in the upgrading/readme doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, Virtus isn't required for custom types. As it was before, any class implementing the parse
method might be used. 🙂 I've added an additional sentence to the upgrading doc.
|
||
# This method maintaine logic which was defined by Virtus for arrays. | ||
# Virtus doesn't allow nil in arrays. | ||
def would_virtus_reject?(val) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it's Virtus related, but I would just call this reject?
. It's about the current coercer, not some library-specific behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM once it's cleaned up & al. Nice work.
end | ||
rescue StandardError => _e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is too broad of a catch-all, I think should be a parser error only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't know which error might be raised by a custom type. Users define it. 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's why it's a problem. Catch all could be something you actually don't expect and there's no way to know if you catch all. We should not be catching all here at all or having an explicit contract with a coercer. If you want the latter, introduce an exception such as CoercionError and rescue that. Document that coercers should throw this or a child of this exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, this begin/rescue
isn't required. Most likely I added to fix some broken tests, after refactoring, it became useless.
require 'dry-types' | ||
|
||
module DryTypes | ||
include Dry.Types() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove ()
, or maybe just use Dry.Types....
everywhere. It's liberally used below as either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would love to do that, but it is how dry-types should be used. After calling Dry.Types()
registered types get added to a container, it involves adding constants and some other meta-programming.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think I am missing something. I'm probably just bad at Ruby :) I am staring at dry-types types.rb code and I don't get it. How does it make Dry.Types
different from Dry.Types()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dry.Types is a method which returns an instance of a module to be included. 🙂 Here is that module.
Dry-types requires Ruby 2.4 or greater 😞 |
Deprecate Ruby 2.3 with a note, changelog, readme change, etc. |
Hi @dblock I made recommended changes, please, have a look again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am good with merging this via a squash with some minor changes in docs, see above.
Since it's a big one, @myxoh, care to take another look?
README.md
Outdated
@@ -167,6 +167,8 @@ The current stable release is [1.2.4](https://github.com/ruby-grape/grape/blob/v | |||
|
|||
## Installation | |||
|
|||
After **1.2.5**, Ruby 2.4.0 or newer is required. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should go into UPGRADING, for this doc just state that Ruby 2.4 or newer is required.
UPGRADING.md
Outdated
end | ||
``` | ||
|
||
you need to add a class-level `parse` method to the model: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Start with a cap, "Add a ..."
UPGRADING.md
Outdated
|
||
#### Ruby | ||
|
||
After adding dry-types, Ruby 2.4.0 or newer is required. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's put this section on top of the list?
end | ||
``` | ||
|
||
Custom types which don't depend on Virtus don't require any changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a "For more information see ..." and link to this PR.
@dblock I've made changes to |
I'm good with this! @myxoh want to confirm and merge? |
Let's get this build to green? There's some legit looking failure with rack-edge. If it's rack's fault we can skip or mark pending and open an issue. I also released 1.2.5 so this will need an update in CHANGELOG and a rebase. |
UPGRADING.md
Outdated
@@ -1,6 +1,49 @@ | |||
Upgrading Grape | |||
=============== | |||
|
|||
### Upgrading to >= 1.2.5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make this 1.3.0. Also change in README/version.rb.
@dblock that commit broke Grape tests 😞 |
As we know Virtus isn't maintained anymore, so it makes sense to use something different for coercing. There is a dry-types lib which was created as a replacement for Virtus (at least a part of it). Although, it is only about coercion. This change gets rid of Virtus and adds dry-types to the stack. The structure inside didn't change match. Dry-types was integrated without huge refactoring. If people want to use Virtus for custom types, it is possible after implementing a parse method which initializes a model. class User include Virtus.model attribute :id, Integer attribute :name, String def self.parse(*args) new(*args) end end
@@ -1133,7 +1133,7 @@ class DummyFormatClass | |||
|
|||
subject.use Rack::Chunked | |||
subject.get('/stream') { stream test_stream } | |||
get '/stream', {}, 'HTTP_VERSION' => 'HTTP/1.1' | |||
get '/stream', {}, 'HTTP_VERSION' => 'HTTP/1.1', 'SERVER_PROTOCOL' => 'HTTP/1.1' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dblock Here is how I fixed the problem with Rack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's totally fine, we just want to make sure Grape is compatible.
I merged this, thank you so much for doing this work @dnesteryuk, it's a big one. I suggest you email the mailing list describing this change and asking people to give the master branch a try, especially if they do custom type checking. |
@dblock I've just tried to run a test suite on one of my projects against your master branch, and all green 😁 There's no custom type checking though. |
@dblock where is the mailing list? 😬 |
|
Any reason why we tied to version 1.1.x of dry-types? @dnesteryuk I know gem changes even with patch version and can bring some incompatibilities, but ... I don't think it's a good solution btw I tried Grape from the
Even if it's already fixed or would be fixed in the future versions of Dry-types we can't update to it due to version restrictions :( |
We should relax it, please PR. |
It was removed in Grape 1.3: ruby-grape/grape#1920 / https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#upgrading-to--130 I'm not sure this particular constant definition is useful anyway.
It was removed in Grape 1.3: ruby-grape/grape#1920 / https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#upgrading-to--130 I'm not sure this particular constant definition is useful anyway.
As we know Virtus isn't maintained anymore, so it makes sense to use something different for coercing. There is a dry-types lib which was created as a replacement for Virtus (at least a part of it). Although, it is only about coercion.
This change gets rid of Virtus and adds dry-types to the stack. Almost, all tests pass. However, there are a few tests which were modified, actually, they didn't make any sense. Yeah, Virtus was providing
some "magic" to make them green, but I think they were unreal.
The structure inside didn't change match. I tried to integrate dry-types without huge refactoring.
If people want to use Virtus for custom types, it is possible after implementing a parse method which initializes a model.
This PR is kind of "work in progress", I would like to gather feedback then proceed. If somebody can add this change to their project and launch tests, it will be awesome, the goal is to avoid breaking changes.
Missing parts:
Hashie::Mash
It closes #1347.