Skip to content
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

Merged
merged 8 commits into from
Oct 25, 2024
Merged

Add rails 7.1 and 7.2 support #756

merged 8 commits into from
Oct 25, 2024

Conversation

jrafanie
Copy link
Member

@jrafanie jrafanie commented Oct 4, 2024

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 for serialize 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

# 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"
Copy link
Member Author

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words, we can specify the column serializer/coder in each migration or here only once. The negative of doing it here is it's less explicit and we're less likely to actually change to json or another / more supported coder.

cc @Fryguy @kbrock

Copy link
Member Author

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.

Copy link
Member

@Fryguy Fryguy Oct 10, 2024

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?

Copy link
Member

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

Copy link
Member Author

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.

Copy link
Member

@Fryguy Fryguy Oct 10, 2024

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.

Copy link
Member

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.

Copy link
Member Author

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:

  1. try moving the module to the plugin instead of the dummy app
  2. treat coder the same way as type, convert all serialize calls to specify a YAML coder and remove the default column serializer setting.

Copy link
Member Author

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.

@jrafanie jrafanie changed the title [WIP] Add rails 7.1 and 7.2 support Add rails 7.1 and 7.2 support Oct 10, 2024
@jrafanie jrafanie removed the wip label Oct 10, 2024
@jrafanie
Copy link
Member Author

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)
Copy link
Member Author

@jrafanie jrafanie Oct 10, 2024

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
Copy link
Member

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.

Copy link
Member Author

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
Copy link
Member Author

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really? 😞

Copy link
Member Author

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.

@jrafanie jrafanie added the wip label Oct 10, 2024
@jrafanie jrafanie changed the title Add rails 7.1 and 7.2 support [WIP]Add rails 7.1 and 7.2 support Oct 10, 2024
@jrafanie jrafanie changed the title [WIP]Add rails 7.1 and 7.2 support [WIP] Add rails 7.1 and 7.2 support Oct 10, 2024
@jrafanie jrafanie changed the title [WIP] Add rails 7.1 and 7.2 support Add rails 7.1 and 7.2 support Oct 23, 2024
@jrafanie jrafanie removed the wip label Oct 23, 2024
@jrafanie
Copy link
Member Author

Ok, I'm taking this out of WIP. I suspect we'll do something similar in serialize calls in the models in core.

@kbrock kbrock merged commit fe983e4 into ManageIQ:master Oct 25, 2024
11 of 12 checks passed
jrafanie added a commit to jrafanie/manageiq that referenced this pull request Nov 1, 2024
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
@jrafanie jrafanie deleted the rails71 branch November 1, 2024 20:28
jrafanie added a commit to jrafanie/manageiq-consumption that referenced this pull request Nov 1, 2024
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
jrafanie added a commit to jrafanie/manageiq that referenced this pull request Nov 7, 2024
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
jrafanie added a commit to jrafanie/manageiq that referenced this pull request Nov 19, 2024
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants