From 00ee57cd80a47277e556d520790ad8e05e374c1c Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 15:46:24 +0200 Subject: [PATCH 01/13] Use Rails 7.1.5.1 This upgrades the gem, and following commits will change configuration, using the "rails app:update" process. --- Gemfile | 6 +- Gemfile.lock | 168 +++++++++++++++++++++++++++++---------------------- 2 files changed, 98 insertions(+), 76 deletions(-) diff --git a/Gemfile b/Gemfile index 7cd363a7a..bca0b246a 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' ruby '3.4.4' -gem 'rails', '7.0.8.1' +gem 'rails', '~> 7.1.5.1' # LOCKED: It is Rails. # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails] gem 'sprockets-rails' @@ -10,7 +10,7 @@ gem 'benchmark' # LOCKED: Added because of activesupport 7.0 gem 'bigdecimal' # LOCKED: Added because of activesupport 7.0 gem 'carrierwave' gem 'cocoon' -gem "csv" # LOCKED: csv was loaded from the standard library, but is not part of the default gems starting from Ruby 3.4.0. Due to config/application.rb +gem 'csv' # LOCKED: csv was loaded from the standard library, but is not part of the default gems starting from Ruby 3.4.0. Due to config/application.rb gem 'delayed_job' gem 'delayed_job_active_record' gem 'drb' # LOCKED: Added because of pry-remote @@ -118,4 +118,4 @@ end gem 'rollbar' -gem "carrierwave-aws", "~> 1.6" +gem 'carrierwave-aws', '~> 1.6' diff --git a/Gemfile.lock b/Gemfile.lock index fa9fce605..9051b1a0c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,73 +1,85 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.0.8.1) - actionpack (= 7.0.8.1) - activesupport (= 7.0.8.1) + actioncable (7.1.5.1) + actionpack (= 7.1.5.1) + activesupport (= 7.1.5.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.8.1) - actionpack (= 7.0.8.1) - activejob (= 7.0.8.1) - activerecord (= 7.0.8.1) - activestorage (= 7.0.8.1) - activesupport (= 7.0.8.1) + zeitwerk (~> 2.6) + actionmailbox (7.1.5.1) + actionpack (= 7.1.5.1) + activejob (= 7.1.5.1) + activerecord (= 7.1.5.1) + activestorage (= 7.1.5.1) + activesupport (= 7.1.5.1) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.0.8.1) - actionpack (= 7.0.8.1) - actionview (= 7.0.8.1) - activejob (= 7.0.8.1) - activesupport (= 7.0.8.1) + actionmailer (7.1.5.1) + actionpack (= 7.1.5.1) + actionview (= 7.1.5.1) + activejob (= 7.1.5.1) + activesupport (= 7.1.5.1) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp - rails-dom-testing (~> 2.0) - actionpack (7.0.8.1) - actionview (= 7.0.8.1) - activesupport (= 7.0.8.1) - rack (~> 2.0, >= 2.2.4) + rails-dom-testing (~> 2.2) + actionpack (7.1.5.1) + actionview (= 7.1.5.1) + activesupport (= 7.1.5.1) + nokogiri (>= 1.8.5) + racc + rack (>= 2.2.4) + rack-session (>= 1.0.1) rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (7.0.8.1) - actionpack (= 7.0.8.1) - activerecord (= 7.0.8.1) - activestorage (= 7.0.8.1) - activesupport (= 7.0.8.1) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + actiontext (7.1.5.1) + actionpack (= 7.1.5.1) + activerecord (= 7.1.5.1) + activestorage (= 7.1.5.1) + activesupport (= 7.1.5.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.8.1) - activesupport (= 7.0.8.1) + actionview (7.1.5.1) + activesupport (= 7.1.5.1) builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (7.0.8.1) - activesupport (= 7.0.8.1) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (7.1.5.1) + activesupport (= 7.1.5.1) globalid (>= 0.3.6) - activemodel (7.0.8.1) - activesupport (= 7.0.8.1) - activerecord (7.0.8.1) - activemodel (= 7.0.8.1) - activesupport (= 7.0.8.1) - activestorage (7.0.8.1) - actionpack (= 7.0.8.1) - activejob (= 7.0.8.1) - activerecord (= 7.0.8.1) - activesupport (= 7.0.8.1) + activemodel (7.1.5.1) + activesupport (= 7.1.5.1) + activerecord (7.1.5.1) + activemodel (= 7.1.5.1) + activesupport (= 7.1.5.1) + timeout (>= 0.4.0) + activestorage (7.1.5.1) + actionpack (= 7.1.5.1) + activejob (= 7.1.5.1) + activerecord (= 7.1.5.1) + activesupport (= 7.1.5.1) marcel (~> 1.0) - mini_mime (>= 1.1.0) - activesupport (7.0.8.1) + activesupport (7.1.5.1) + base64 + benchmark (>= 0.3) + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) + mutex_m + securerandom (>= 0.3) tzinfo (~> 2.0) - acts-as-taggable-on (11.0.0) - activerecord (>= 7.0, < 8.0) + acts-as-taggable-on (12.0.0) + activerecord (>= 7.1, < 8.1) zeitwerk (>= 2.4, < 3.0) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) @@ -144,6 +156,7 @@ GEM commonmarker (2.3.2) rb_sys (~> 0.9) concurrent-ruby (1.3.5) + connection_pool (2.5.3) crass (1.0.6) css_parser (1.14.0) addressable @@ -261,14 +274,14 @@ GEM mutex_m (0.3.0) net-http (0.6.0) uri - net-imap (0.4.20) + net-imap (0.5.9) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.2) timeout - net-smtp (0.4.0.1) + net-smtp (0.5.1) net-protocol nio4r (2.7.4) nokogiri (1.18.9) @@ -341,28 +354,34 @@ GEM pundit (2.5.0) activesupport (>= 3.0.0) racc (1.8.1) - rack (2.2.17) + rack (3.2.0) rack-mini-profiler (4.0.1) rack (>= 1.2.0) - rack-protection (3.2.0) + rack-protection (4.1.1) base64 (>= 0.1.0) - rack (~> 2.2, >= 2.2.4) + logger (>= 1.6.0) + rack (>= 3.0.0, < 4) + rack-session (2.1.1) + base64 (>= 0.1.0) + rack (>= 3.0.0) rack-test (2.2.0) rack (>= 1.3) - rails (7.0.8.1) - actioncable (= 7.0.8.1) - actionmailbox (= 7.0.8.1) - actionmailer (= 7.0.8.1) - actionpack (= 7.0.8.1) - actiontext (= 7.0.8.1) - actionview (= 7.0.8.1) - activejob (= 7.0.8.1) - activemodel (= 7.0.8.1) - activerecord (= 7.0.8.1) - activestorage (= 7.0.8.1) - activesupport (= 7.0.8.1) + rackup (2.2.1) + rack (>= 3) + rails (7.1.5.1) + actioncable (= 7.1.5.1) + actionmailbox (= 7.1.5.1) + actionmailer (= 7.1.5.1) + actionpack (= 7.1.5.1) + actiontext (= 7.1.5.1) + actionview (= 7.1.5.1) + activejob (= 7.1.5.1) + activemodel (= 7.1.5.1) + activerecord (= 7.1.5.1) + activestorage (= 7.1.5.1) + activesupport (= 7.1.5.1) bundler (>= 1.15.0) - railties (= 7.0.8.1) + railties (= 7.1.5.1) rails-dom-testing (2.3.0) activesupport (>= 5.0.0) minitest @@ -377,13 +396,14 @@ GEM rails_stdout_logging rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) - railties (7.0.8.1) - actionpack (= 7.0.8.1) - activesupport (= 7.0.8.1) - method_source + railties (7.1.5.1) + actionpack (= 7.1.5.1) + activesupport (= 7.1.5.1) + irb + rackup (>= 1.0.0) rake (>= 12.2) - thor (~> 1.0) - zeitwerk (~> 2.5) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) rainbow (3.1.1) rake (13.3.0) rake-compiler-dock (1.9.1) @@ -461,6 +481,7 @@ GEM sprockets (> 3.0) sprockets-rails tilt + securerandom (0.4.1) selenium-webdriver (4.34.0) base64 (~> 0.2) logger (~> 1.4) @@ -522,7 +543,8 @@ GEM bindex (>= 0.4.0) railties (>= 6.0.0) websocket (1.2.11) - websocket-driver (0.7.6) + websocket-driver (0.8.0) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) @@ -586,7 +608,7 @@ DEPENDENCIES puma (~> 6.6) pundit rack-mini-profiler (~> 4.0) - rails (= 7.0.8.1) + rails (~> 7.1.5.1) rails-html-sanitizer (~> 1.6.2) rails4-autocomplete rails_12factor From c0cc45e96aaad2cd86ff8a217921084d7d378e21 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 16:33:19 +0200 Subject: [PATCH 02/13] Rails 7.1: rails app:update This amended all the configuration files with manually-edited new diffs, getting rid of outdated configuration where known to be outdated. We wish to keep close to the default configuration, to make updates using these diff scripts easy. --- app/models/group.rb | 2 +- config/application.rb | 21 +- config/boot.rb | 1 - config/environments/development.rb | 9 +- config/environments/production.rb | 59 ++-- config/environments/test.rb | 26 +- .../initializers/content_security_policy.rb | 4 +- .../initializers/filter_parameter_logging.rb | 6 +- config/initializers/inflections.rb | 8 +- .../new_framework_defaults_7_1.rb | 280 ++++++++++++++++++ config/initializers/permissions_policy.rb | 20 +- spec/spec_helper.rb | 2 +- 12 files changed, 352 insertions(+), 86 deletions(-) create mode 100644 config/initializers/new_framework_defaults_7_1.rb diff --git a/app/models/group.rb b/app/models/group.rb index 85910ae57..e57bc93fc 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -13,7 +13,7 @@ class Group < ApplicationRecord validates :name, presence: true, inclusion: { in: NAMES, message: 'Invalid name for Group' } - alias_attribute :city, :chapter + alias city chapter default_scope -> { joins(:chapter).includes(:chapter) } diff --git a/config/application.rb b/config/application.rb index 2dff52771..fd42b8120 100644 --- a/config/application.rb +++ b/config/application.rb @@ -24,6 +24,8 @@ class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 7.0 + config.autoload_lib(ignore: %w(assets tasks)) + # Configuration for the application, engines, and railties goes here. # # These settings can be overridden in specific environments using the files @@ -32,30 +34,13 @@ class Application < Rails::Application # config.time_zone = "Central Time (US & Canada)" # config.eager_load_paths << Rails.root.join("extras") - # Settings in config/environments/* take precedence over those specified here. - # Application configuration can go into files in config/initializers - # -- all .rb files in that directory are automatically loaded after loading - # the framework and any gems in your application. - - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. config.time_zone = 'London' config.active_record.default_timezone = :local - # Remove config.active_record.raise_in_transactional_callbacks, which is deprecated and removed without replacement, see - # https://apidock.com/rails/v5.0.0.1/ActiveRecord/Transactions/ClassMethods/raise_in_transactional_callbacks%3D. - # config.active_record.raise_in_transactional_callbacks = true - # Related to https://stackoverflow.com/questions/72970170/upgrading-to-rails-6-1-6-1-causes-psychdisallowedclass-tried-to-load-unspecif # and https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017 config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time, ActiveSupport::TimeWithZone, ActiveSupport::TimeZone, ActiveSupport::HashWithIndifferentAccess] config.active_record.belongs_to_required_by_default = true end -end - -require 'csv' # the standard library CSV Class +end \ No newline at end of file diff --git a/config/boot.rb b/config/boot.rb index 37a5619ce..d69bd27dc 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,4 +1,3 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require "bundler/setup" # Set up gems listed in the Gemfile. -require "logger" # Fix concurrent-ruby removing logger dependency which Rails itself does not have diff --git a/config/environments/development.rb b/config/environments/development.rb index 027057416..48696fa62 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -6,7 +6,7 @@ # In the development environment your application's code is reloaded any time # it changes. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. - config.cache_classes = false + config.enable_reloading = true # Do not eager load code on boot. config.eager_load = false @@ -56,6 +56,9 @@ # Highlight code that triggered database queries in logs. config.active_record.verbose_query_logs = true + # Highlight code that enqueued background job in logs. + config.active_job.verbose_enqueue_logs = true + # Suppress logger output for asset requests. config.assets.quiet = true @@ -65,8 +68,8 @@ # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true - # Uncomment if you wish to allow Action Cable access from any origin. - # config.action_cable.disable_request_forgery_protection = true + # Raise error when a before_action's only/except options reference missing actions + config.action_controller.raise_on_missing_callback_actions = true # Required default host to link to! config.action_mailer.default_url_options = { host: 'localhost:3000' } diff --git a/config/environments/production.rb b/config/environments/production.rb index 987ab41d2..ab6fa06aa 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -4,7 +4,7 @@ # Settings specified here will take precedence over those in config/application.rb. # Code is not reloaded between requests. - config.cache_classes = true + config.enable_reloading = false # Eager load code on boot. This eager loads most of Rails and # your application in memory, allowing both threaded web servers @@ -13,15 +13,14 @@ config.eager_load = true # Full error reports are disabled and caching is turned on. - config.consider_all_requests_local = false + config.consider_all_requests_local = false config.action_controller.perform_caching = true - # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] - # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment + # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). # config.require_master_key = true - # Disable serving static files from the `/public` folder by default since - # Apache or NGINX already handles this. + # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead. config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? # Compress CSS using a preprocessor. @@ -30,7 +29,7 @@ # Compress JS using a preprocessor. config.assets.js_compressor = :terser - # Do not fallback to assets pipeline if a precompiled asset is missed. + # Do not fall back to assets pipeline if a precompiled asset is missed. config.assets.compile = false # Enable serving of images, stylesheets, and JavaScripts from an asset server. @@ -43,21 +42,31 @@ # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. + # config.assume_ssl = true + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true - # Include generic and useful information about system operation, but avoid logging too much - # information to avoid inadvertent exposure of personally identifiable information (PII). - config.log_level = ENV.fetch("RAILS_LOG_LEVEL") { "info" } + # Log to STDOUT by default + config.logger = ActiveSupport::Logger.new(STDOUT) + .tap { |logger| logger.formatter = ::Logger::Formatter.new } + .then { |logger| ActiveSupport::TaggedLogging.new(logger) } # Prepend all log lines with the following tags. config.log_tags = [ :request_id ] + # "info" includes generic and useful information about system operation, but avoids logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). If you + # want to log everything, set the level to "debug". + config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") + # Use a different cache store in production. # config.cache_store = :mem_cache_store # Use a real queuing backend for Active Job (and separate queues per environment). - # config.active_job.queue_adapter = :resque + # config.active_job.queue_adapter = :resque # config.active_job.queue_name_prefix = "planner_#{Rails.env}" config.action_mailer.perform_caching = false @@ -73,28 +82,17 @@ # Don't log any deprecations. config.active_support.report_deprecations = false - # Use default logging formatter so that PID and timestamp are not suppressed. - config.log_formatter = ::Logger::Formatter.new - - # Use a different logger for distributed setups. - # require "syslog/logger" - # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') - - if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new(STDOUT) - logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) - end - # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - # Required default host to link to! - config.action_mailer.default_url_options = { host: 'codebar.io' } + # Enable DNS rebinding protection and other `Host` header attacks. + # config.hosts = [ + # "example.com", # Allow requests from example.com + # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` + # ] - # Ignore bad email addresses and do not raise email delivery errors. - # Set this to true and configure the email server for immediate delivery to raise delivery errors. - # config.action_mailer.raise_delivery_errors = false + # Skip DNS rebinding protection for the default health check endpoint. + # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } config.action_mailer.smtp_settings = { port: '587', @@ -106,4 +104,5 @@ enable_starttls_auto: true } ActionMailer::Base.delivery_method = :smtp -end + config.action_mailer.default_url_options = { host: 'codebar.io' } +end \ No newline at end of file diff --git a/config/environments/test.rb b/config/environments/test.rb index e2239b940..4edc63a9e 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -9,12 +9,13 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # Turn false under Spring and add config.action_view.cache_template_loading = true. - config.cache_classes = true + # While tests run files are not watched, reloading is not necessary. + config.enable_reloading = false - # Eager loading loads your whole application. When running a single test locally, - # this probably isn't necessary. It's a good idea to do in a continuous integration - # system, or in some way before deploying your code. + # Eager loading loads your entire application. When running a single test locally, + # this is usually not necessary, and can slow down your test suite. However, it's + # recommended that you enable it in continuous integration systems to ensure eager + # loading is working properly before deploying your code. config.eager_load = ENV["CI"].present? # Configure public file server for tests with Cache-Control for performance. @@ -24,12 +25,12 @@ } # Show full error reports and disable caching. - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false config.cache_store = :null_store - # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false + # Render exception templates for rescuable exceptions and raise for other exceptions. + config.action_dispatch.show_exceptions = :rescuable # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false @@ -59,18 +60,15 @@ # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true - # Required default host to link to! - config.action_mailer.default_url_options = { host: 'localhost:3000' } + # Raise error when a before_action's only/except options reference missing actions + config.action_controller.raise_on_missing_callback_actions = true - # Configure static asset server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = 'public, max-age=3600' + config.action_mailer.default_url_options = { host: 'localhost:3000' } # Fake omniauth for testing OmniAuth.config.test_mode = true config.after_initialize do - # TODO: re-enable and go through failures Bullet.enable = true Bullet.bullet_logger = true Bullet.raise = false # raise an error if n+1 query occurs diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index 54f47cf15..b3076b38f 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -16,9 +16,9 @@ # # policy.report_uri "/csp-violation-report-endpoint" # end # -# # Generate session nonces for permitted importmap and inline scripts +# # Generate session nonces for permitted importmap, inline scripts, and inline styles. # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } -# config.content_security_policy_nonce_directives = %w(script-src) +# config.content_security_policy_nonce_directives = %w(script-src style-src) # # # Report violations without enforcing the policy. # # config.content_security_policy_report_only = true diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index adc6568ce..c2d89e28a 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,8 +1,8 @@ # Be sure to restart your server when you modify this file. -# Configure parameters to be filtered from the log file. Use this to limit dissemination of -# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported -# notations and behaviors. +# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. +# Use this to limit dissemination of sensitive information. +# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. Rails.application.config.filter_parameters += [ :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn ] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index ac033bf9d..3860f659e 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -4,13 +4,13 @@ # are locale specific, and you may define rules for as many different # locales as you wish. All of these examples are active by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" # inflect.uncountable %w( fish sheep ) # end # These inflection rules are supported but not enabled by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.acronym 'RESTful' +# inflect.acronym "RESTful" # end diff --git a/config/initializers/new_framework_defaults_7_1.rb b/config/initializers/new_framework_defaults_7_1.rb new file mode 100644 index 000000000..3dc295db6 --- /dev/null +++ b/config/initializers/new_framework_defaults_7_1.rb @@ -0,0 +1,280 @@ +# Be sure to restart your server when you modify this file. +# +# This file eases your Rails 7.1 framework defaults upgrade. +# +# Uncomment each configuration one by one to switch to the new default. +# Once your application is ready to run with all new defaults, you can remove +# this file and set the `config.load_defaults` to `7.1`. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. +# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html + +### +# No longer add autoloaded paths into `$LOAD_PATH`. This means that you won't be able +# to manually require files that are managed by the autoloader, which you shouldn't do anyway. +# +# This will reduce the size of the load path, making `require` faster if you don't use bootsnap, or reduce the size +# of the bootsnap cache if you use it. +# +# To set this configuration, add the following line to `config/application.rb` (NOT this file): +# config.add_autoload_paths_to_load_path = false + +### +# Remove the default X-Download-Options headers since it is used only by Internet Explorer. +# If you need to support Internet Explorer, add back `"X-Download-Options" => "noopen"`. +#++ +# Rails.application.config.action_dispatch.default_headers = { +# "X-Frame-Options" => "SAMEORIGIN", +# "X-XSS-Protection" => "0", +# "X-Content-Type-Options" => "nosniff", +# "X-Permitted-Cross-Domain-Policies" => "none", +# "Referrer-Policy" => "strict-origin-when-cross-origin" +# } + +### +# Do not treat an `ActionController::Parameters` instance +# as equal to an equivalent `Hash` by default. +#++ +# Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality = false + +### +# Active Record Encryption now uses SHA-256 as its hash digest algorithm. +# +# There are 3 scenarios to consider. +# +# 1. If you have data encrypted with previous Rails versions, and you have +# +config.active_support.key_generator_hash_digest_class+ configured as SHA1 (the default +# before Rails 7.0), you need to configure SHA-1 for Active Record Encryption too: +#++ +# Rails.application.config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA1 +# +# 2. If you have +config.active_support.key_generator_hash_digest_class+ configured as SHA256 (the new default +# in 7.0), then you need to configure SHA-256 for Active Record Encryption: +#++ +# Rails.application.config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA256 +# +# 3. If you don't currently have data encrypted with Active Record encryption, you can disable this setting to +# configure the default behavior starting 7.1+: +#++ +# Rails.application.config.active_record.encryption.support_sha1_for_non_deterministic_encryption = false + +### +# No longer run after_commit callbacks on the first of multiple Active Record +# instances to save changes to the same database row within a transaction. +# Instead, run these callbacks on the instance most likely to have internal +# state which matches what was committed to the database, typically the last +# instance to save. +#++ +# Rails.application.config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction = false + +### +# Configures SQLite with a strict strings mode, which disables double-quoted string literals. +# +# SQLite has some quirks around double-quoted string literals. +# It first tries to consider double-quoted strings as identifier names, but if they don't exist +# it then considers them as string literals. Because of this, typos can silently go unnoticed. +# For example, it is possible to create an index for a non existing column. +# See https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted for more details. +#++ +# Rails.application.config.active_record.sqlite3_adapter_strict_strings_by_default = true + +### +# Disable deprecated singular associations names. +#++ +# Rails.application.config.active_record.allow_deprecated_singular_associations_name = false + +### +# Enable the Active Job `BigDecimal` argument serializer, which guarantees +# roundtripping. Without this serializer, some queue adapters may serialize +# `BigDecimal` arguments as simple (non-roundtrippable) strings. +# +# When deploying an application with multiple replicas, old (pre-Rails 7.1) +# replicas will not be able to deserialize `BigDecimal` arguments from this +# serializer. Therefore, this setting should only be enabled after all replicas +# have been successfully upgraded to Rails 7.1. +#++ +# Rails.application.config.active_job.use_big_decimal_serializer = true + +### +# Specify if an `ArgumentError` should be raised if `Rails.cache` `fetch` or +# `write` are given an invalid `expires_at` or `expires_in` time. +# Options are `true`, and `false`. If `false`, the exception will be reported +# as `handled` and logged instead. +#++ +# Rails.application.config.active_support.raise_on_invalid_cache_expiration_time = true + +### +# Specify whether Query Logs will format tags using the SQLCommenter format +# (https://open-telemetry.github.io/opentelemetry-sqlcommenter/), or using the legacy format. +# Options are `:legacy` and `:sqlcommenter`. +#++ +# Rails.application.config.active_record.query_log_tags_format = :sqlcommenter + +### +# Specify the default serializer used by `MessageEncryptor` and `MessageVerifier` +# instances. +# +# The legacy default is `:marshal`, which is a potential vector for +# deserialization attacks in cases where a message signing secret has been +# leaked. +# +# In Rails 7.1, the new default is `:json_allow_marshal` which serializes and +# deserializes with `ActiveSupport::JSON`, but can fall back to deserializing +# with `Marshal` so that legacy messages can still be read. +# +# In Rails 7.2, the default will become `:json` which serializes and +# deserializes with `ActiveSupport::JSON` only. +# +# Alternatively, you can choose `:message_pack` or `:message_pack_allow_marshal`, +# which serialize with `ActiveSupport::MessagePack`. `ActiveSupport::MessagePack` +# can roundtrip some Ruby types that are not supported by JSON, and may provide +# improved performance, but it requires the `msgpack` gem. +# +# For more information, see +# https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer +# +# If you are performing a rolling deploy of a Rails 7.1 upgrade, wherein servers +# that have not yet been upgraded must be able to read messages from upgraded +# servers, first deploy without changing the serializer, then set the serializer +# in a subsequent deploy. +#++ +# Rails.application.config.active_support.message_serializer = :json_allow_marshal + +### +# Enable a performance optimization that serializes message data and metadata +# together. This changes the message format, so messages serialized this way +# cannot be read by older versions of Rails. However, messages that use the old +# format can still be read, regardless of whether this optimization is enabled. +# +# To perform a rolling deploy of a Rails 7.1 upgrade, wherein servers that have +# not yet been upgraded must be able to read messages from upgraded servers, +# leave this optimization off on the first deploy, then enable it on a +# subsequent deploy. +#++ +# Rails.application.config.active_support.use_message_serializer_for_metadata = true + +### +# Set the maximum size for Rails log files. +# +# `config.load_defaults 7.1` does not set this value for environments other than +# development and test. +#++ +# if Rails.env.local? +# Rails.application.config.log_file_size = 100 * 1024 * 1024 +# end + +### +# Enable raising on assignment to attr_readonly attributes. The previous +# behavior would allow assignment but silently not persist changes to the +# database. +#++ +# Rails.application.config.active_record.raise_on_assign_to_attr_readonly = true + +### +# Enable validating only parent-related columns for presence when the parent is mandatory. +# The previous behavior was to validate the presence of the parent record, which performed an extra query +# to get the parent every time the child record was updated, even when parent has not changed. +#++ +# Rails.application.config.active_record.belongs_to_required_validates_foreign_key = false + +### +# Enable precompilation of `config.filter_parameters`. Precompilation can +# improve filtering performance, depending on the quantity and types of filters. +#++ +# Rails.application.config.precompile_filter_parameters = true + +### +# Enable before_committed! callbacks on all enrolled records in a transaction. +# The previous behavior was to only run the callbacks on the first copy of a record +# if there were multiple copies of the same record enrolled in the transaction. +#++ +# Rails.application.config.active_record.before_committed_on_all_records = true + +### +# Disable automatic column serialization into YAML. +# To keep the historic behavior, you can set it to `YAML`, however it is +# recommended to explicitly define the serialization method for each column +# rather than to rely on a global default. +#++ +# Rails.application.config.active_record.default_column_serializer = nil + +### +# Enable a performance optimization that serializes Active Record models +# in a faster and more compact way. +# +# To perform a rolling deploy of a Rails 7.1 upgrade, wherein servers that have +# not yet been upgraded must be able to read caches from upgraded servers, +# leave this optimization off on the first deploy, then enable it on a +# subsequent deploy. +#++ +# Rails.application.config.active_record.marshalling_format_version = 7.1 + +### +# Run `after_commit` and `after_*_commit` callbacks in the order they are defined in a model. +# This matches the behaviour of all other callbacks. +# In previous versions of Rails, they ran in the inverse order. +#++ +# Rails.application.config.active_record.run_after_transaction_callbacks_in_order_defined = true + +### +# Whether a `transaction` block is committed or rolled back when exited via `return`, `break` or `throw`. +#++ +# Rails.application.config.active_record.commit_transaction_on_non_local_return = true + +### +# Controls when to generate a value for has_secure_token declarations. +#++ +# Rails.application.config.active_record.generate_secure_token_on = :initialize + +### +# ** Please read carefully, this must be configured in config/application.rb ** +# +# Change the format of the cache entry. +# +# Changing this default means that all new cache entries added to the cache +# will have a different format that is not supported by Rails 7.0 +# applications. +# +# Only change this value after your application is fully deployed to Rails 7.1 +# and you have no plans to rollback. +# When you're ready to change format, add this to `config/application.rb` (NOT +# this file): +# config.active_support.cache_format_version = 7.1 + +### +# Configure Action View to use HTML5 standards-compliant sanitizers when they are supported on your +# platform. +# +# `Rails::HTML::Sanitizer.best_supported_vendor` will cause Action View to use HTML5-compliant +# sanitizers if they are supported, else fall back to HTML4 sanitizers. +# +# In previous versions of Rails, Action View always used `Rails::HTML4::Sanitizer` as its vendor. +#++ +# Rails.application.config.action_view.sanitizer_vendor = Rails::HTML::Sanitizer.best_supported_vendor + +### +# Configure Action Text to use an HTML5 standards-compliant sanitizer when it is supported on your +# platform. +# +# `Rails::HTML::Sanitizer.best_supported_vendor` will cause Action Text to use HTML5-compliant +# sanitizers if they are supported, else fall back to HTML4 sanitizers. +# +# In previous versions of Rails, Action Text always used `Rails::HTML4::Sanitizer` as its vendor. +#++ +# Rails.application.config.action_text.sanitizer_vendor = Rails::HTML::Sanitizer.best_supported_vendor + +### +# Configure the log level used by the DebugExceptions middleware when logging +# uncaught exceptions during requests. +#++ +# Rails.application.config.action_dispatch.debug_exception_log_level = :error + +### +# Configure the test helpers in Action View, Action Dispatch, and rails-dom-testing to use HTML5 +# parsers. +# +# Nokogiri::HTML5 isn't supported on JRuby, so JRuby applications must set this to :html4. +# +# In previous versions of Rails, these test helpers always used an HTML4 parser. +#++ +# Rails.application.config.dom_testing_default_html_version = :html5 diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb index 00f64d71b..7db3b9577 100644 --- a/config/initializers/permissions_policy.rb +++ b/config/initializers/permissions_policy.rb @@ -1,11 +1,13 @@ +# Be sure to restart your server when you modify this file. + # Define an application-wide HTTP permissions policy. For further -# information see https://developers.google.com/web/updates/2018/06/feature-policy -# -# Rails.application.config.permissions_policy do |f| -# f.camera :none -# f.gyroscope :none -# f.microphone :none -# f.usb :none -# f.fullscreen :self -# f.payment :self, "https://secure.example.com" +# information see: https://developers.google.com/web/updates/2018/06/feature-policy + +# Rails.application.config.permissions_policy do |policy| +# policy.camera :none +# policy.gyroscope :none +# policy.microphone :none +# policy.usb :none +# policy.fullscreen :self +# policy.payment :self, "https://secure.example.com" # end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9f1aa18aa..9032c0420 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -35,7 +35,7 @@ def self.branch_coverage? Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } -ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration) +ActiveRecord::Migration.check_all_pending! if defined?(ActiveRecord::Migration) RSpec.configure do |config| config.include ApplicationHelper From 4a586398128c85ea7b24d44f06753fba903a3702 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 16:59:51 +0200 Subject: [PATCH 03/13] chore: Namespace a class to avoid Zeitwerk error Zeitwerk is the code loader in Rails. It expects files to define classes by a convention that it explains very clearly: Zeitwerk::NameError: expected file /home/runner/work/planner/planner/lib/services/event_calendar.rb to define constant Services::EventCalendar, but didn't --- app/mailers/event_invitation_mailer.rb | 2 +- lib/services/event_calendar.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/mailers/event_invitation_mailer.rb b/app/mailers/event_invitation_mailer.rb index 83c27d3b3..0587bf43a 100644 --- a/app/mailers/event_invitation_mailer.rb +++ b/app/mailers/event_invitation_mailer.rb @@ -34,7 +34,7 @@ def attending(event, member, invitation) require 'services/event_calendar' attachments['codebar.ics'] = { mime_type: 'text/calendar', - content: EventCalendar.new(@event).calendar.to_ical } + content: ServicesEventCalendar.new(@event).calendar.to_ical } subject = "Your spot to #{@event.name} has been confirmed." diff --git a/lib/services/event_calendar.rb b/lib/services/event_calendar.rb index 0b93330df..8b3f3c7ee 100644 --- a/lib/services/event_calendar.rb +++ b/lib/services/event_calendar.rb @@ -1,4 +1,4 @@ -class EventCalendar +class Services::EventCalendar attr_reader :event def initialize(event) From fbe49f8a405629121974e0ad2208043ed87cbd4e Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 17:04:40 +0200 Subject: [PATCH 04/13] chore: Avoid namespace for the Flodesk class. In order to avoid Zeitwerk expectations failing. --- config/initializers/flodesk.rb | 2 +- lib/{services => }/flodesk.rb | 0 spec/lib/services/flodesk_spec.rb | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename lib/{services => }/flodesk.rb (100%) diff --git a/config/initializers/flodesk.rb b/config/initializers/flodesk.rb index 248eb3d38..1e1d2fe8e 100644 --- a/config/initializers/flodesk.rb +++ b/config/initializers/flodesk.rb @@ -1,4 +1,4 @@ -require 'services/flodesk' +require 'flodesk' key = Rails.env.test? ? 'test' : ENV['FLODESK_KEY'] Rails.logger.warn 'Missing FLODESK_KEY environment variable' unless key diff --git a/lib/services/flodesk.rb b/lib/flodesk.rb similarity index 100% rename from lib/services/flodesk.rb rename to lib/flodesk.rb diff --git a/spec/lib/services/flodesk_spec.rb b/spec/lib/services/flodesk_spec.rb index 833232e4c..10f1761d5 100644 --- a/spec/lib/services/flodesk_spec.rb +++ b/spec/lib/services/flodesk_spec.rb @@ -1,5 +1,5 @@ require 'json' -require 'services/flodesk' +require 'flodesk' RSpec.describe Flodesk do let(:stub) { Faraday::Adapter::Test::Stubs.new } From c18b4e8a00cc814b99ec9ca3bc040b6cac71bd93 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 17:10:53 +0200 Subject: [PATCH 05/13] chore: Namespace MailingList for Zeitwerk --- app/controllers/concerns/mailing_list_concerns.rb | 8 ++++---- app/models/contact.rb | 2 +- app/models/subscription.rb | 4 ++-- lib/services/mailing_list.rb | 2 +- lib/tasks/delete_member.rake | 2 +- lib/tasks/mailing_list.rake | 2 +- spec/lib/services/mailing_list_spec.rb | 4 ++-- spec/lib/tasks/mailing_list_rake_spec.rb | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/controllers/concerns/mailing_list_concerns.rb b/app/controllers/concerns/mailing_list_concerns.rb index 6483664d9..8d94d39ab 100644 --- a/app/controllers/concerns/mailing_list_concerns.rb +++ b/app/controllers/concerns/mailing_list_concerns.rb @@ -10,14 +10,14 @@ module MailingListConcerns module InstanceMethods def subscribe_to_newsletter(member) member.update(opt_in_newsletter_at: Time.zone.now) - MailingList.new(ENV['NEWSLETTER_ID']).subscribe(member.email, - member.name, - member.surname) + Services::MailingList.new(ENV['NEWSLETTER_ID']).subscribe(member.email, + member.name, + member.surname) end def unsubscribe_from_newsletter(member) member.update(opt_in_newsletter_at: nil) - MailingList.new(ENV['NEWSLETTER_ID']).unsubscribe(member.email) + Services::MailingList.new(ENV['NEWSLETTER_ID']).unsubscribe(member.email) end end end diff --git a/app/models/contact.rb b/app/models/contact.rb index e9e8b7279..78ba48490 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -18,7 +18,7 @@ def unsubscribe_from_mailing_list end def mailing_list - @mailing_list ||= MailingList.new(ENV['SPONSOR_NEWSLETTER_ID']) + @mailing_list ||= Services::MailingList.new(ENV['SPONSOR_NEWSLETTER_ID']) end private diff --git a/app/models/subscription.rb b/app/models/subscription.rb index da6faa758..dad167d46 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -22,10 +22,10 @@ def coach? private def subscribe_to_mailing_list - MailingList.new(group.mailing_list_id).subscribe(member.email, member.name, member.surname) + Services::MailingList.new(group.mailing_list_id).subscribe(member.email, member.name, member.surname) end def unsubscribe_from_mailing_list - MailingList.new(group.mailing_list_id).unsubscribe(member.email) + Services::MailingList.new(group.mailing_list_id).unsubscribe(member.email) end end diff --git a/lib/services/mailing_list.rb b/lib/services/mailing_list.rb index 6530baab5..98d0dc631 100644 --- a/lib/services/mailing_list.rb +++ b/lib/services/mailing_list.rb @@ -1,4 +1,4 @@ -class MailingList +class Services::MailingList attr_reader :list_id def initialize(list_id) diff --git a/lib/tasks/delete_member.rake b/lib/tasks/delete_member.rake index 044ccb2fc..927923b1d 100644 --- a/lib/tasks/delete_member.rake +++ b/lib/tasks/delete_member.rake @@ -17,7 +17,7 @@ namespace :member do $stdin.getch ActiveRecord::Base.transaction do - MailingList.new(ENV['NEWSLETTER_ID']).unsubscribe(member.email) + Services::MailingList.new(ENV['NEWSLETTER_ID']).unsubscribe(member.email) member.auth_services.delete_all member.subscriptions.delete_all diff --git a/lib/tasks/mailing_list.rake b/lib/tasks/mailing_list.rake index 556e13b17..15921a4fc 100644 --- a/lib/tasks/mailing_list.rake +++ b/lib/tasks/mailing_list.rake @@ -6,7 +6,7 @@ namespace :mailing_list do newsletter_id = ENV['NEWSLETTER_ID'] || Rails.logger.info('NEWSLETTER_ID not set. Aborting task') && abort members = Member.includes(:subscriptions).where.not('subscriptions.member_id' => nil).uniq - newsletter = MailingList.new(newsletter_id) + newsletter = Services::MailingList.new(newsletter_id) members.each do |member| member.update(opt_in_newsletter_at: Time.zone.now) diff --git a/spec/lib/services/mailing_list_spec.rb b/spec/lib/services/mailing_list_spec.rb index 1ec9e335a..d71097cd1 100644 --- a/spec/lib/services/mailing_list_spec.rb +++ b/spec/lib/services/mailing_list_spec.rb @@ -1,8 +1,8 @@ require 'json' require 'services/mailing_list' -RSpec.describe MailingList do - let(:mailing_list) { MailingList.new(:list_id) } +RSpec.describe Services::MailingList do + let(:mailing_list) { Services::MailingList.new(:list_id) } let(:client) { double(:flodesk) } before do diff --git a/spec/lib/tasks/mailing_list_rake_spec.rb b/spec/lib/tasks/mailing_list_rake_spec.rb index e851beeae..a5298fa13 100644 --- a/spec/lib/tasks/mailing_list_rake_spec.rb +++ b/spec/lib/tasks/mailing_list_rake_spec.rb @@ -17,8 +17,8 @@ subscribed.each { |member| Fabricate(:subscription, member: member) } subscribed[0...3].each { |member| Fabricate(:subscription, member: member) } - newslettter = MailingList.new(:id) - expect(MailingList).to receive(:new).and_return(newslettter) + newslettter = Services::MailingList.new(:id) + expect(Services::MailingList).to receive(:new).and_return(newslettter) subscribed.each do |subscriber| expect(newslettter).to receive(:subscribe).with(subscriber.email, From b8f142fbb6992f97e2596c738cc35222142264d2 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 17:14:13 +0200 Subject: [PATCH 06/13] fix: name the Services module before using it --- db/schema.rb | 2 +- lib/services/mailing_list.rb | 58 +++++++++++++++++++----------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 52d7df7be..192b8fd69 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2025_08_06_181500) do +ActiveRecord::Schema[7.1].define(version: 2025_08_06_181500) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" diff --git a/lib/services/mailing_list.rb b/lib/services/mailing_list.rb index 98d0dc631..0755d5fb5 100644 --- a/lib/services/mailing_list.rb +++ b/lib/services/mailing_list.rb @@ -1,39 +1,41 @@ -class Services::MailingList - attr_reader :list_id +module Services + class MailingList + attr_reader :list_id - def initialize(list_id) - @list_id = list_id - end + def initialize(list_id) + @list_id = list_id + end - def subscribe(email, first_name, last_name) - return if client.disabled? + def subscribe(email, first_name, last_name) + return if client.disabled? - client.subscribe(email:, first_name:, last_name:, segment_ids: [@list_id]) - rescue Flodesk::FlodeskError - false - end - handle_asynchronously :subscribe + client.subscribe(email:, first_name:, last_name:, segment_ids: [@list_id]) + rescue Flodesk::FlodeskError + false + end + handle_asynchronously :subscribe - def unsubscribe(email) - return if client.disabled? + def unsubscribe(email) + return if client.disabled? - client.unsubscribe(email:, segment_ids: [@list_id]) - rescue Flodesk::FlodeskError - false - end - handle_asynchronously :unsubscribe + client.unsubscribe(email:, segment_ids: [@list_id]) + rescue Flodesk::FlodeskError + false + end + handle_asynchronously :unsubscribe - def subscribed?(email) - return if client.disabled? + def subscribed?(email) + return if client.disabled? - client.subscribed?(email:, segment_ids: [@list_id]) - rescue Flodesk::FlodeskError - false - end + client.subscribed?(email:, segment_ids: [@list_id]) + rescue Flodesk::FlodeskError + false + end - private + private - def client - @client ||= Flodesk::Client.new + def client + @client ||= Flodesk::Client.new + end end end From 857755419129751f6a2390c64310a99fd196afaa Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 17:17:17 +0200 Subject: [PATCH 07/13] chore: namespace "Ticket" for Zeitwerk --- app/controllers/events_controller.rb | 11 ++++---- app/mailers/event_invitation_mailer.rb | 2 +- lib/services/ticket.rb | 28 ++++++++++--------- .../subscribing_to_newsletter_spec.rb | 12 ++++---- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 1736eb6ca..31030f266 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -13,16 +13,17 @@ def index events << Event.past.includes(:venue, :sponsors).limit(RECENT_EVENTS_DISPLAY_LIMIT) events = events.compact.flatten.sort_by(&:date_and_time).reverse.first(RECENT_EVENTS_DISPLAY_LIMIT) events_hash_grouped_by_date = events.group_by(&:date) - @past_events = events_hash_grouped_by_date.map.inject({}) do |hash, (key, value)| + @past_events = events_hash_grouped_by_date.map.each_with_object({}) do |(key, value), hash| hash[key] = EventPresenter.decorate_collection(value) - hash end events = [Workshop.includes(:chapter).upcoming.joins(:chapter).merge(Chapter.active)] events << Meeting.upcoming.all events << Event.upcoming.includes(:venue, :sponsors).all events = events.compact.flatten.sort_by(&:date_and_time).group_by(&:date) - @events = events.map.inject({}) { |hash, (key, value)| hash[key] = EventPresenter.decorate_collection(value); hash } + @events = events.map.each_with_object({}) do |(key, value), hash| + hash[key] = EventPresenter.decorate_collection(value) + end end def show @@ -34,7 +35,7 @@ def show return unless logged_in? invitation = Invitation.find_by(member: current_user, event: event, attending: true) - return redirect_to event_invitation_path(@event, invitation) if invitation + redirect_to event_invitation_path(@event, invitation) if invitation end def student @@ -47,7 +48,7 @@ def coach def rsvp set_event - ticket = Ticket.new(request, params) + ticket = Services::Ticket.new(request, params) member = Member.find_by(email: ticket.email) invitation = member.invitations.where(event: @event, role: 'Student').try(:first) invitation ||= Invitation.create(event: @event, member: member, role: 'Student') diff --git a/app/mailers/event_invitation_mailer.rb b/app/mailers/event_invitation_mailer.rb index 0587bf43a..a46d7e9d3 100644 --- a/app/mailers/event_invitation_mailer.rb +++ b/app/mailers/event_invitation_mailer.rb @@ -34,7 +34,7 @@ def attending(event, member, invitation) require 'services/event_calendar' attachments['codebar.ics'] = { mime_type: 'text/calendar', - content: ServicesEventCalendar.new(@event).calendar.to_ical } + content: Services::EventCalendar.new(@event).calendar.to_ical } subject = "Your spot to #{@event.name} has been confirmed." diff --git a/lib/services/ticket.rb b/lib/services/ticket.rb index 0f82fe1a6..eedb31138 100644 --- a/lib/services/ticket.rb +++ b/lib/services/ticket.rb @@ -1,19 +1,21 @@ -class Ticket - def initialize(request, params) - authorise(request) - @params = params - end +module Services + class Ticket + def initialize(request, params) + authorise(request) + @params = params + end - def email - @email ||= params[:email] - end + def email + @email ||= params[:email] + end - private + private - attr_reader :params + attr_reader :params - def authorise(request) - # TODO - # verify referer + def authorise(request) + # TODO + # verify referer + end end end diff --git a/spec/features/subscribing_to_newsletter_spec.rb b/spec/features/subscribing_to_newsletter_spec.rb index 6474c086d..38c24b940 100644 --- a/spec/features/subscribing_to_newsletter_spec.rb +++ b/spec/features/subscribing_to_newsletter_spec.rb @@ -14,7 +14,7 @@ context 'A new member' do scenario 'is subscribed to the newsletter by default' do mailing_list = double(:mailing_list) - expect(MailingList).to receive(:new).and_return(mailing_list) + expect(Services::MailingList).to receive(:new).and_return(mailing_list) expect(mailing_list).to receive(:subscribe).with('jane@codebar.io', 'Jane', 'Doe') visit new_member_path @@ -33,7 +33,7 @@ scenario 'can opt out of the newsletter' do mailing_list = double(:mailing_list) - expect(MailingList).to receive(:new).and_return(mailing_list) + expect(Services::MailingList).to receive(:new).and_return(mailing_list) expect(mailing_list).to receive(:unsubscribe).with('jane@codebar.io') visit new_member_path @@ -60,7 +60,7 @@ login member mailing_list = double(:mailing_list) - expect(MailingList).to receive(:new).and_return(mailing_list) + expect(Services::MailingList).to receive(:new).and_return(mailing_list) expect(mailing_list).to receive(:subscribe) visit subscriptions_path @@ -75,7 +75,7 @@ login member mailing_list = double(:mailing_list) - expect(MailingList).to receive(:new).and_return(mailing_list) + expect(Services::MailingList).to receive(:new).and_return(mailing_list) expect(mailing_list).to receive(:unsubscribe) visit subscriptions_path @@ -90,7 +90,7 @@ login member mailing_list = double(:mailing_list) - expect(MailingList).to receive(:new).and_return(mailing_list) + expect(Services::MailingList).to receive(:new).and_return(mailing_list) expect(mailing_list).to receive(:subscribe) visit subscriptions_path @@ -98,7 +98,7 @@ expect(page).to have_content('You have subscribed to codebar\'s newsletter') - expect(MailingList).to receive(:new).and_return(mailing_list) + expect(Services::MailingList).to receive(:new).and_return(mailing_list) expect(mailing_list).to receive(:unsubscribe) click_on 'Unsubscribe from newsletter' From 6e6ea3373f7919b37e78687fcad58f10157a4dec Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 17:27:03 +0200 Subject: [PATCH 08/13] Try avoiding an unknown constant error Workaround from https://github.com/hotwired/turbo-rails/issues/512#issuecomment-1806575923' --- config/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/application.rb b/config/application.rb index fd42b8120..975bc046d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -11,7 +11,7 @@ require "action_mailbox/engine" require "action_text/engine" require "action_view/railtie" -# require "action_cable/engine" +require "action_cable/engine" require "sprockets/railtie" require "rails/test_unit/railtie" From d3f1645b12e4f2b11c3d7ad4aa1ade094c1e308e Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 18:02:58 +0200 Subject: [PATCH 09/13] chore: drop unused Rails 5.2 defaults temp file These files are meant to be used during upgrades, not kept around. --- .../new_framework_defaults_5_2.rb | 38 ------------------- 1 file changed, 38 deletions(-) delete mode 100644 config/initializers/new_framework_defaults_5_2.rb diff --git a/config/initializers/new_framework_defaults_5_2.rb b/config/initializers/new_framework_defaults_5_2.rb deleted file mode 100644 index c383d072b..000000000 --- a/config/initializers/new_framework_defaults_5_2.rb +++ /dev/null @@ -1,38 +0,0 @@ -# Be sure to restart your server when you modify this file. -# -# This file contains migration options to ease your Rails 5.2 upgrade. -# -# Once upgraded flip defaults one by one to migrate to the new default. -# -# Read the Guide for Upgrading Ruby on Rails for more info on each option. - -# Make Active Record use stable #cache_key alongside new #cache_version method. -# This is needed for recyclable cache keys. -# Rails.application.config.active_record.cache_versioning = true - -# Use AES-256-GCM authenticated encryption for encrypted cookies. -# Also, embed cookie expiry in signed or encrypted cookies for increased security. -# -# This option is not backwards compatible with earlier Rails versions. -# It's best enabled when your entire app is migrated and stable on 5.2. -# -# Existing cookies will be converted on read then written with the new scheme. -# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true - -# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages -# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true. -# Rails.application.config.active_support.use_authenticated_message_encryption = true - -# Add default protection from forgery to ActionController::Base instead of in -# ApplicationController. -# Rails.application.config.action_controller.default_protect_from_forgery = true - -# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and -# 'f' after migrating old data. -# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true - -# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. -# Rails.application.config.active_support.use_sha1_digests = true - -# Make `form_with` generate id attributes for any generated HTML tags. -# Rails.application.config.action_view.form_with_generates_ids = true From c4c16c1b00e844a7e3fad2418c1ada5aee10450a Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Wed, 6 Aug 2025 18:03:09 +0200 Subject: [PATCH 10/13] Rails 7.1: Drop Rails 7.0 temp defaults config file These are meant to be dropped after updating to a version. We are currently setting all of these defaults, using a defaults setting in config/application.rb, so the file no longer does anything. --- .../new_framework_defaults_7_0.rb | 148 ------------------ 1 file changed, 148 deletions(-) delete mode 100644 config/initializers/new_framework_defaults_7_0.rb diff --git a/config/initializers/new_framework_defaults_7_0.rb b/config/initializers/new_framework_defaults_7_0.rb deleted file mode 100644 index 0f8d42054..000000000 --- a/config/initializers/new_framework_defaults_7_0.rb +++ /dev/null @@ -1,148 +0,0 @@ -# Be sure to restart your server when you modify this file. -# -# This file eases your Rails 7.0 framework defaults upgrade. -# -# Uncomment each configuration one by one to switch to the new default. -# Once your application is ready to run with all new defaults, you can remove -# this file and set the `config.load_defaults` to `7.0`. -# -# Read the Guide for Upgrading Ruby on Rails for more info on each option. -# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html - -# `button_to` view helper will render `