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

Rails 7 upgrade #3250

Merged
merged 13 commits into from
Jan 17, 2024
Merged

Rails 7 upgrade #3250

merged 13 commits into from
Jan 17, 2024

Conversation

murny
Copy link
Contributor

@murny murny commented Sep 27, 2023

This PR is to upgrade Jupiter from Rails v6.1.X to v7.0.X

List of major changes:

  • Remove require_dependency as this has been dropped (replace with require_relative for now, Rails 7.1 allows autoloading from "lib" directory and this will all go away)
  • Fix "TimeWithZone#to_s(:db) is deprecated. Please use TimeWithZone#to_fs(:db) instead." warnings
  • fix "include Pundit is deprecated. Please use include Pundit::Authorization instead." PR fix "include Pundit is deprecated. Please use include Pundit::Authorization instead." warnings #3318
  • Update files from Rails generator
  • Fix bad fixtures using non-existent associations
  • Fix issue with redirect_to for an external URL
  • Explicitly opt into mini_magick for ActiveStorage
  • Fix issue with singleton_class usage in Rails 7 for ActsAsRDFable gem, point gem to branch with hot fix for this PR Bump acts_as_rdfable from 0.4.0 to v0.5.0 #3291

@github-actions
Copy link

github-actions bot commented Oct 7, 2023

1 Warning
⚠️ This PR is too big! Consider breaking it down into smaller PRs.

Generated by 🚫 Danger

@murny
Copy link
Contributor Author

murny commented Oct 10, 2023

Tests are failing due to ActsAsRDF gem. We are seeing errors like this:

/Users/murny/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/activerecord-7.0.8/lib/active_record/model_schema.rb:633:in `compute_table_name': undefined method `table_name' for nil:NilClass (NoMethodError)

            base_class.table_name
                      ^^^^^^^^^^^
	from /Users/murny/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/activerecord-7.0.8/lib/active_record/model_schema.rb:284:in `reset_table_name'
	from /Users/murny/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/activerecord-7.0.8/lib/active_record/model_schema.rb:248:in `table_name'
	from /Users/murny/jupiter/app/services/rdf_graph_creation_service.rb:5:in `get_prefixed_predicates'

I believe the issue from troubleshooting is due to the way we were relying on singleton_class in this gem to get the "class" of the model. It appears something broke in a newer version in Rails where the singleton_class no longer returns the correct data back.

I believe this is related to this issue which was closed with no action:
rails/rails#38293.
Which is where the singleton_class no longer responds to .inspect with a similar error.

A simple solution is just use self.class instead of self.singleton_class for getting the models class. Will have to investigate if theirs any side effects from making this change.

Also feel like this gem could be improved. We have multiple ways to "register" the gem into models, not sure why we have many ways? (Activerecord base include and add_annotation_bindings! etc)

UPDATE: PR created for this in ActsAsRDFable to fix this issue: ualbertalib/acts_as_rdfable#14

@@ -59,5 +59,9 @@ class Application < Rails::Application
link_attributes: { rel: 'noopener noreferrer', target: '_blank' }
}

# We should be using VIPS which is now the default, but this requires work to migrate?
# Delete this line if we ever migrate to VIPS
config.active_storage.variant_processor = :mini_magick
Copy link
Contributor Author

@murny murny Oct 14, 2023

Choose a reason for hiding this comment

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

To move to VIPS we probably need some code changes and Production/Staging needs the correct binaries install?

https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#active-storage-default-variant-processor-changed-to-vips

I'll throw an issue in the backlog for this. But this isn't a big deal. mini_magick isn't being deprecated. Just that VIPS is a superior and more performant library.

@@ -16,19 +16,19 @@ item_fancy:

item_practical:
visibility: <%= JupiterCore::VISIBILITY_PUBLIC %>
owner: regular
owner: user_regular
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This and the member_of_paths were references non existant associations? Looks like in Rails 7 this will start throwing errors, but not sure how this ever worked before?

We use this fixture in SearchTest 🤔

Copy link
Member

Choose a reason for hiding this comment

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

Good catch!

@@ -5,7 +5,7 @@ def new

if params['code'].nil?
auth_uri = auth_client.authorization_uri.to_s
redirect_to auth_uri
redirect_to(auth_uri, allow_other_host: true)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Rails 7 protects against trying to redirect_to to an external URL: https://api.rubyonrails.org/v7.0.8/classes/ActionController/Redirecting.html#method-i-redirect_to

This is safe because we are setting this auth_uri ourselves and it's not coming from a user-provided param/link

@@ -22,11 +22,11 @@
module Jupiter
class Application < Rails::Application

require_dependency 'lib/jupiter'
require_dependency 'lib/jupiter/version'
require_relative '../lib/jupiter'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These require relatives to lib directory can go away after Rails 7.1 which introduces autoloading lib automatically:

https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#config-autoload-lib-ignore

@@ -16,6 +16,9 @@
# Show full error reports.
config.consider_all_requests_local = true

# Enable server timing
config.server_timing = true
Copy link
Contributor Author

@murny murny Dec 24, 2023

Choose a reason for hiding this comment

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

These environments changes came from the generator. So just updating them to match.

gem 'pry-byebug'
gem 'pry-rails'
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem 'debug', platforms: [:mri, :mingw, :x64_mingw]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ruby ships with a debugger out of the box now and it's actually really good (and getting better all the time). Will remove pry/byebug unless anyone has concerns about this.

Can use binding.irb now to create a debugger in your code instead of byebug or binding.pry

Copy link
Member

Choose a reason for hiding this comment

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

Looks good, thanks for the link! It looks like debugger is another way to create a debugger in your code.

Copy link
Member

@pgwillia pgwillia left a comment

Choose a reason for hiding this comment

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

Nice work! Thanks for your explanatory comments.

I just have some minor questions. Overall looks good 👍

Gemfile Outdated
@@ -102,9 +101,8 @@ end
group :development do
gem 'better_errors', '>= 2.3.0'
gem 'binding_of_caller'
# gem "rack-mini-profiler"
Copy link
Member

Choose a reason for hiding this comment

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

Just curious why the comment here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's brought in by the generator, I can remove it for now

(although think it is a nice thing to bring in. Rack mini profiler gives a tool tip that shows performance metrics like how fast a page was rendered and where that time was all spent. But we can do this after this gets merged)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed this comment 👍

gem 'pry-byebug'
gem 'pry-rails'
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem 'debug', platforms: [:mri, :mingw, :x64_mingw]
Copy link
Member

Choose a reason for hiding this comment

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

Looks good, thanks for the link! It looks like debugger is another way to create a debugger in your code.

Comment on lines 25 to 26
require_relative '../lib/jupiter'
require_relative '../lib/jupiter/version'
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this work now? https://devdocs.io/rails~7.0/activesupport/dependencies/requiredependency#method-i-require_dependency

Suggested change
require_relative '../lib/jupiter'
require_relative '../lib/jupiter/version'
require 'jupiter'
require 'jupiter/version'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

require needs an absolute URL unless its on your $LOAD_PATH. So jupiter shouldn't be on the $LOAD_PATH so this wouldnt work.

But require '/code/jupiter/lib/jupiter/version' would work.

require_relative is just an alternative to allow you to use relative version of require which is what I did here.

Either way in Rails 7.1 this should go away as we will autoload the lib directory.

Copy link
Member

Choose a reason for hiding this comment

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

That's not what I'm observing.
image

Idiomatic Rails applications only issue require calls to load stuff from their lib directory, the Ruby standard library, Ruby gems, etc. That is, anything that does not belong to their autoload paths, explained below.
https://guides.rubyonrails.org/v7.0/autoloading_and_reloading_constants.html#introduction

Copy link
Contributor Author

@murny murny Jan 16, 2024

Choose a reason for hiding this comment

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

Ah cool, thanks for the link. Will change this 👍

Seems like they put lib directory in the $LOAD_PATH by default.

Another nice quote from the above article:

For instance, lib is an idiomatic choice. It does not belong to the autoload paths by default, but it does
belong to $LOAD_PATH. Just perform a regular require to load it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated code to use the simple require version for these

@@ -65,16 +65,10 @@

# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = [:en]
config.i18n.fallbacks = true
Copy link
Member

Choose a reason for hiding this comment

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

We changed this deliberately, but it's been a while: 1b8aee7 Was there another change in behaviour in the interim?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This came from the generator but it should be equivalent?

config.i18n.fallbacks = true will fall back to the I18n.default_locale value, which defaults to :en if it isn't defined.

config.i18n.fallbacks = [:en] well, just sets it to :en

So should be the same.

More info: https://guides.rubyonrails.org/v7.0.0/configuring.html#configuring-i18n

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reading that issue and the PR leaves me more confused 🤔 But even on a brand new rails application it would be set as true with the following comment:

# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true

Wonder if Rails does something different here?

Copy link
Member

Choose a reason for hiding this comment

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

I think I'm out to lunch. It looks like I missed the instruction about Rails < 5.2.2. We were on 5.2.3 at the time so this never applied to us. All good here!

config/routes.rb Outdated
Comment on lines 3 to 4
require_relative '../lib/admin_constraint'
require_relative '../lib/entity_constraint'
Copy link
Member

Choose a reason for hiding this comment

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

Same as above.

Suggested change
require_relative '../lib/admin_constraint'
require_relative '../lib/entity_constraint'
require 'admin_constraint'
require 'entity_constraint'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done! Thanks for calling this out 🙏

@@ -16,19 +16,19 @@ item_fancy:

item_practical:
visibility: <%= JupiterCore::VISIBILITY_PUBLIC %>
owner: regular
owner: user_regular
Copy link
Member

Choose a reason for hiding this comment

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

Good catch!

@@ -1,5 +1,5 @@
class ApplicationRecord < ActiveRecord::Base

self.abstract_class = true
primary_abstract_class
Copy link
Member

Choose a reason for hiding this comment

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

I hadn't seen this discussed anywhere, but maybe I missed it. Is this a new convention? It means the same thing, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Came from the generator but yeah, it does the same thing. Just with a bit of checks/guards around it.

More info and the source code of this method here:
https://edgeapi.rubyonrails.org/classes/ActiveRecord/Inheritance/ClassMethods.html#method-i-primary_abstract_class


# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.1
config.load_defaults 7.0
Copy link
Contributor

Choose a reason for hiding this comment

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

Found this tid-bit in the Rails upgrade docs regarding staged deployment, I am curious if this is relevant or has an impact:

... Rails 6.1 applications are not able to read this new serialization format, so to ensure a seamless upgrade you must first deploy your Rails 7.0 upgrade with config.active_support.cache_format_version = 6.1, and then only once all Rails processes have been updated you can set config.active_support.cache_format_version = 7.0.

https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#new-activesupport-cache-serialization-format

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call out 👍

But I think we okay here, as "Rails 7.0 is able to read both formats, so the cache won't be invalidated during the upgrade."

We also only use cache in a single place in our application (for Read Only mode), so if the cache does get invalidated, it's not a big issue.

Copy link
Contributor

@ConnorSheremeta ConnorSheremeta left a comment

Choose a reason for hiding this comment

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

Looks good from my end! 👍

Copy link
Member

@pgwillia pgwillia left a comment

Choose a reason for hiding this comment

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

@murny murny merged commit 57bee3a into master Jan 17, 2024
4 checks passed
@murny murny deleted the Rails-7-upgrade branch January 17, 2024 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants