-
Notifications
You must be signed in to change notification settings - Fork 125
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
Add rails 7.1 and 7.2 support #756
Conversation
# argument previously. To avoid a case statement in all usages of serialize, we're defaulting | ||
# all serialized columns to YAML for rails 7.1+ here. Ideally, we would use JSON if we find we can | ||
# use a simpler datatype. See: https://github.com/rails/rails/pull/47463 | ||
config.active_record.default_column_serializer = YAML if Rails.version >= "7.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.
TODO: Do we want to inject this for each of the migrations and use the "bridge" in a similar way I'm handling :type
above? We'd need to specify :coder => YAML
for nearly all the migrations that do serialize
. This approach could help guide us on what to do in core in the models.
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 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.
On the flip side, I assume you can override the default in each migration and specify an override coder one by one so any that are serializing basic objects can likely specify json while the default for others will be to use yaml.
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'm trying to understand the implications of this change.
Ideally, ActiveRecord::Migration would know to use coder yaml for serialize on older migration versions that are indicated with the [7.0]
thing in the constant name. To me, it's a bug that they didn't do this, so maybe we should open a bug with them.
That aside, I'm concerned if we set a global default, then it will break future migrations. So, considering that, I think it's better, though more verbose, to set the coder => yaml on every migration. We're already changing it for the :type change, so it's not like it's more lines of code. This way we can do it the "right way" moving forward.
Related question, what is the coder on the model side? Do we need a similar change in core changing every serialized column to say what coder it is?
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.
What is in our way from converting all our serialized fields from yaml => json?
What do we see as the biggest barier
- Time to write migration code
- Time to run migrations on customer code (upgrades)
- Possible datatype incompatibility (symbols, dates, active record)
- Test that app is still working
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.
Related question, what is the coder on the model side? Do we need a similar change in core changing every serialized column to say what coder it is?
You can see some of the very wet stuff on the core PR... so far, type is where I did changes since I could specify a default coder using config.active_record.default_column_serializer = YAML
. I would prefer a common approach for both and I like the idea of writing serialize in the rails 7.1+
kwargs way and the bridge module would convert it to positional arguments for rails 7.0.
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.
What is in our way from converting all our serialized fields from yaml => json?
non-json types, notable Ruby objects, DateTime, Symbol. If we know for a fact a column doesn't have those it's an easy conversion.
However, that's moving forward - we still need to deal with older migrations regardless.
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.
Technically, this is a gray area because we're defining stub models in migrations. I don't think they can guard for that type of thing.
'nuff said. My brain didn't click that this was a model problem, not really a migration problem.
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.
By the way, I kept the first attempt commit. I had the bridge module implementing "7.0 format" we don't need to change model calls to serialize but it's ugly:
737278c
Compare that to the "7.1 format" where we convert 7.0 format to 7.1 we have now 410fbfc
I kept it around to help decide which way forward would be best.
I'll mark this was WIP again and apply the changes suggested here:
- try moving the module to the plugin instead of the dummy app
- treat coder the same way as type, convert all serialize calls to specify a YAML coder and remove the default column serializer setting.
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 tried removing config.active_record.default_column_serializer = YAML if Rails.version >= "7.1"
and defaulted to setting :coder => YAML
throughout but that didn't work well with 7.0. I removed that change. We'll carry this for now and revisit it once we're off of 7.0.
Ok, ManageIQ/activerecord-id_regions#40 was merged and released as 0.5.0 so this is now ready for review. |
@@ -0,0 +1,19 @@ | |||
module Dummy | |||
module SerializePositionalToKwargsBridge | |||
def serialize(*args, **options) |
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 the largest change in rails 7.1+ for this repository. Unlike the "coder" change above, there isn't an option to default the type
so what I did was accepted the new interface: kwargs for type and built a bridge to convert kwargs back to positional arguments when run with rails 7.0.
@@ -0,0 +1,19 @@ | |||
module Dummy |
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 feels like it should be part of the plugin itself, and not dummy. The dummy app is only for tests here, so I presume we will hit this same issue in application code where the dummy won't be present. Perhaps it could be done similar to how we patch migrate for clearing caches.
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.
Nice, I can look into that. Good idea.
if Rails.version >= "7.1" | ||
include Rails::Generators::Testing::Behavior | ||
else | ||
include Rails::Generators::Testing::Behaviour |
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.
🇬🇧
include Rails::Generators::Testing::Behavior | ||
else | ||
include Rails::Generators::Testing::Behaviour | ||
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.
Really? 😞
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 was more a "consistency in naming" vs. 🇬🇧 / 🇺🇸 spelling fight. https://www.github.com/rails/rails/pull/45180
I do prefer the fight though. It's more fun.
Add them to the matrix.
We can intercept serialize for 7.0 and convert kwargs back to the positional class_name_or_coder. Update existing migrations to use rails 7.1 interface.
Ok, I'm taking this out of WIP. I suspect we'll do something similar in serialize calls in the models in core. |
Type was changed from positional to a keyword argument 'type' in 7.1. The positional argument is removed in rails 7.2. We have a helper bridge module prepending support for either kwargs or positional arguments passed to serialize which converts to positional for rails 7.0 and kwargs for 7.1+. This was added and automatically loaded in the rails app via the engine in schema: ManageIQ/manageiq-schema#756
Type was changed from positional to a keyword argument 'type' in 7.1. The positional argument is removed in rails 7.2. We have a helper bridge module prepending support for either kwargs or positional arguments passed to serialize which converts to positional for rails 7.0 and kwargs for 7.1+. This was added and automatically loaded in the rails app via the engine in schema: ManageIQ/manageiq-schema#756 Similar change as core: ManageIQ/manageiq#23253
Type was changed from positional to a keyword argument 'type' in 7.1. The positional argument is removed in rails 7.2. We have a helper bridge module prepending support for either kwargs or positional arguments passed to serialize which converts to positional for rails 7.0 and kwargs for 7.1+. This was added and automatically loaded in the rails app via the engine in schema: ManageIQ/manageiq-schema#756
Type was changed from positional to a keyword argument 'type' in 7.1. The positional argument is removed in rails 7.2. We have a helper bridge module prepending support for either kwargs or positional arguments passed to serialize which converts to positional for rails 7.0 and kwargs for 7.1+. This was added and automatically loaded in the rails app via the engine in schema: ManageIQ/manageiq-schema#756
Depends on:
High level:
YAML
serialize
is going out of style and we should convert as many to json or other types if possible. The interface forserialize
changed so I have a bridge that changes our existing migrations to use the 7.1 interface with a layer to convert it back to 7.0 format if using 7.0. I think this way is easier to read than the prior commit: Prepend serialize in 7.1+ to convert positional arguments to kwargs