diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3b4ef7c..1dfda55 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,15 +10,23 @@ jobs: - '3.0' - '3.1' - '3.2' + - '3.3' gemfile: - - gemfiles/Gemfile.rails61 - gemfiles/Gemfile.rails70 - gemfiles/Gemfile.rails71 + - gemfiles/Gemfile.rails72 + - gemfiles/Gemfile.rails80 exclude: - # rails 7.0 requires ruby >= 2.7 + # rails 7.2 requires ruby >= 3.1 # https://www.fastruby.io/blog/ruby/rails/versions/compatibility-table.html - - ruby-version: '2.6' - gemfile: 'gemfiles/Gemfile.rails70' + - ruby-version: '3.0' + gemfile: 'gemfiles/Gemfile.rails72' + # rails 8.0 requires ruby >= 3.2 + # https://www.fastruby.io/blog/ruby/rails/versions/compatibility-table.html + - ruby-version: '3.0' + gemfile: 'gemfiles/Gemfile.rails80' + - ruby-version: '3.1' + gemfile: 'gemfiles/Gemfile.rails80' name: Ruby ${{ matrix.ruby-version }} / Bundle ${{ matrix.gemfile }} diff --git a/CHANGELOG.md b/CHANGELOG.md index b042d37..73c18e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## [Unreleased] -* no unreleased changes +### Added +* Support Rails 7.1, 7.2, 8.0, Ruby 3.2, 3.3. Drop support for Rails 6.1 ## 5.10.3 / 2023-02-12 ## Fixed diff --git a/gemfiles/Gemfile.rails61 b/gemfiles/Gemfile.rails61 deleted file mode 100644 index 5763acd..0000000 --- a/gemfiles/Gemfile.rails61 +++ /dev/null @@ -1,6 +0,0 @@ -source 'https://rubygems.org' - -gemspec path: '..' - -gem 'activerecord', '~> 6.1.0' -gem 'activesupport', '~> 6.1.0' diff --git a/gemfiles/Gemfile.rails72 b/gemfiles/Gemfile.rails72 new file mode 100644 index 0000000..f0d108a --- /dev/null +++ b/gemfiles/Gemfile.rails72 @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gemspec path: '..' + +gem 'activerecord', '~> 7.2.0' +gem 'activesupport', '~> 7.2.0' diff --git a/gemfiles/Gemfile.rails80 b/gemfiles/Gemfile.rails80 new file mode 100644 index 0000000..21062d3 --- /dev/null +++ b/gemfiles/Gemfile.rails80 @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gemspec path: '..' + +gem 'activerecord', '~> 8.0.0' +gem 'activesupport', '~> 8.0.0' diff --git a/lib/ndr_support/date_and_time_extensions.rb b/lib/ndr_support/date_and_time_extensions.rb index 04be7ac..dd1465e 100644 --- a/lib/ndr_support/date_and_time_extensions.rb +++ b/lib/ndr_support/date_and_time_extensions.rb @@ -2,6 +2,7 @@ require 'date' require 'ndr_support/working_days' +# Extend standard Date class with our custom to_s overrides class Date # to_iso output must be SQL safe for security reasons def to_iso @@ -12,11 +13,7 @@ def to_iso def to_datetime # Default timezone for Date is GMT, not local timezone - default_timezone = if ActiveRecord.respond_to?(:default_timezone) - ActiveRecord.default_timezone - else - ActiveRecord::Base.default_timezone # Rails <= 6.1 - end + default_timezone = ActiveRecord.default_timezone return in_time_zone.to_datetime if default_timezone == :local orig_to_datetime @@ -29,7 +26,7 @@ def to_datetime # We keep overriding this for compatibility def to_s(format = :default) if format == :default - to_formatted_s(:default) + DATE_FORMATS.key?(:default) ? to_fs(:default) : orig_to_s else orig_to_s(format) end @@ -38,6 +35,7 @@ def to_s(format = :default) #------------------------------------------------------------------------------- +# Extend standard Time class with our custom to_s overrides class Time # to_iso output must be SQL safe for security reasons def to_iso @@ -51,7 +49,7 @@ def to_iso # We keep overriding this for compatibility def to_s(format = :default) if format == :default - to_formatted_s(:default) + DATE_FORMATS.key?(:default) ? to_fs(:default) : orig_to_s else orig_to_s(format) end @@ -60,6 +58,7 @@ def to_s(format = :default) #------------------------------------------------------------------------------- +# Extend standard DateTime class with our custom to_s overrides class DateTime alias orig_to_s to_s @@ -68,7 +67,7 @@ class DateTime # We keep overriding this for compatibility def to_s(format = :default) if format == :default - to_formatted_s(:default) + Time::DATE_FORMATS.key?(:default) ? to_fs(:default) : orig_to_s else orig_to_s(format) end @@ -78,6 +77,7 @@ def to_s(format = :default) #------------------------------------------------------------------------------- module ActiveSupport + # Extend ActiveSupport::TimeWithZone with our custom to_s overrides class TimeWithZone alias orig_to_s to_s @@ -86,7 +86,7 @@ class TimeWithZone # We keep overriding this for compatibility def to_s(format = :default) if format == :default - to_formatted_s(:default) + Time::DATE_FORMATS.key?(:default) ? to_fs(:default) : orig_to_s else orig_to_s(format) end @@ -96,6 +96,7 @@ def to_s(format = :default) #------------------------------------------------------------------------------- +# NdrSupport module module NdrSupport class << self # Within the NDR, we change default date formatting, as below. @@ -120,8 +121,8 @@ def attempt_date_patch! def apply_date_patch! # Ensure we emit "yaml-formatted" string, instead of the revised default format. Psych::Visitors::YAMLTree.class_eval do - def visit_Date(o) - @emitter.scalar o.to_formatted_s(:yaml), nil, nil, true, false, Psych::Nodes::Scalar::ANY + def visit_Date(o) # rubocop:disable Naming/MethodName, Naming/MethodParameterName + @emitter.scalar o.to_fs(:yaml), nil, nil, true, false, Psych::Nodes::Scalar::ANY end end end diff --git a/lib/ndr_support/ourdate.rb b/lib/ndr_support/ourdate.rb index 1cd9b17..0264847 100644 --- a/lib/ndr_support/ourdate.rb +++ b/lib/ndr_support/ourdate.rb @@ -15,11 +15,7 @@ def self.today #-- # TODO: Use Ourdate.build_datetime everywhere below: #++ - default_timezone = if ActiveRecord.respond_to?(:default_timezone) - ActiveRecord.default_timezone - else - ActiveRecord::Base.default_timezone # Rails <= 6.1 - end + default_timezone = ActiveRecord.default_timezone if default_timezone == :local build_datetime(current_time.year, current_time.month, current_time.day) else diff --git a/lib/ndr_support/ourdate/build_datetime.rb b/lib/ndr_support/ourdate/build_datetime.rb index 613d533..86694d8 100644 --- a/lib/ndr_support/ourdate/build_datetime.rb +++ b/lib/ndr_support/ourdate/build_datetime.rb @@ -10,11 +10,7 @@ class Ourdate def self.build_datetime(year, month = 1, day = 1, hour = 0, min = 0, sec = 0, usec = 0) return nil if year.nil? - default_timezone = if ActiveRecord.respond_to?(:default_timezone) - ActiveRecord.default_timezone - else - ActiveRecord::Base.default_timezone # Rails <= 6.1 - end + default_timezone = ActiveRecord.default_timezone if default_timezone == :local # Time.local_time(year, month, day, hour, min, sec, usec).to_datetime # Behave like oracle_adapter.rb diff --git a/lib/ndr_support/string/conversions.rb b/lib/ndr_support/string/conversions.rb index 1668e52..6e4b3d8 100644 --- a/lib/ndr_support/string/conversions.rb +++ b/lib/ndr_support/string/conversions.rb @@ -129,11 +129,7 @@ def truncate_hellip(n) def to_datetime # Default timezone for to_datetime conversion is GMT, not local timezone - default_timezone = if ActiveRecord.respond_to?(:default_timezone) - ActiveRecord.default_timezone - else - ActiveRecord::Base.default_timezone # Rails <= 6.1 - end + default_timezone = ActiveRecord.default_timezone return to_time.to_datetime if default_timezone == :local orig_to_datetime diff --git a/ndr_support.gemspec b/ndr_support.gemspec index daa5ce4..008c4da 100644 --- a/ndr_support.gemspec +++ b/ndr_support.gemspec @@ -18,8 +18,8 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] - spec.add_dependency 'activerecord', '>= 6.1', '< 7.2' - spec.add_dependency 'activesupport', '>= 6.1', '< 7.2' + spec.add_dependency 'activerecord', '>= 7.0', '< 8.1' + spec.add_dependency 'activesupport', '>= 7.0', '< 8.1' spec.add_development_dependency 'bundler' spec.add_development_dependency 'rake', '>= 12.3.3' diff --git a/test/date_and_time_extensions_test.rb b/test/date_and_time_extensions_test.rb index d201320..d7aa0d7 100644 --- a/test/date_and_time_extensions_test.rb +++ b/test/date_and_time_extensions_test.rb @@ -6,7 +6,11 @@ class DateAndTimeExtensionsTest < Minitest::Test def test_date_to_s d = Date.new(2000, 2, 1) - assert_equal '2000-02-01', d.to_default_s, 'Rails 7 default to_s' + if d.respond_to?(:to_default_s) # Only defined on Rails <= 7.1 + assert_equal '2000-02-01', d.to_default_s, 'Rails 7 default to_s' + else + assert_equal '2000-02-01', d.orig_to_s, 'Rails 7 default to_s (via our shim)' + end assert_equal '01.02.2000', d.to_formatted_s(:default), 'Rails 6 default to_s' assert_equal d.to_formatted_s(:default), d.to_s, 'We plan to change default to_s behaviour in a major version bump' @@ -14,20 +18,33 @@ def test_date_to_s def test_datetime_to_s bst_datetime = DateTime.new(2014, 4, 1, 0, 0, 0, '+1') - assert_equal '2014-04-01T00:00:00+01:00', bst_datetime.to_default_s, 'Rails 7 default to_s' + if bst_datetime.respond_to?(:to_default_s) # Only defined on Rails <= 7.1 + assert_equal '2014-04-01T00:00:00+01:00', bst_datetime.to_default_s, 'Rails 7 default to_s' + else + assert_equal '2014-04-01T00:00:00+01:00', bst_datetime.orig_to_s, 'Rails 7 default to_s (via our shim)' + end assert_equal '01.04.2014', bst_datetime.to_formatted_s(:default), 'Rails 6 default to_s' assert_equal bst_datetime.to_formatted_s(:default), bst_datetime.to_s, 'We plan to change default to_s behaviour in a major version bump' gmt_datetime = DateTime.new(2014, 3, 1, 0, 0, 0, '+0') - assert_equal '2014-03-01T00:00:00+00:00', gmt_datetime.to_default_s, 'Rails 7 default to_s' + if gmt_datetime.respond_to?(:to_default_s) # Only defined on Rails <= 7.1 + assert_equal '2014-03-01T00:00:00+00:00', gmt_datetime.to_default_s, 'Rails 7 default to_s' + else + assert_equal '2014-03-01T00:00:00+00:00', gmt_datetime.orig_to_s, 'Rails 7 default to_s (via our shim)' + end assert_equal '01.03.2014', gmt_datetime.to_formatted_s(:default), 'Rails 6 default to_s' assert_equal gmt_datetime.to_formatted_s(:default), gmt_datetime.to_s, 'We plan to change default to_s behaviour in a major version bump' datetime_with_hhmmss = DateTime.new(2014, 4, 1, 12, 35, 11, '+0') - assert_equal '2014-04-01T12:35:11+00:00', datetime_with_hhmmss.to_default_s, - 'Rails 7 default to_s' + if datetime_with_hhmmss.respond_to?(:to_default_s) # Only defined on Rails <= 7.1 + assert_equal '2014-04-01T12:35:11+00:00', datetime_with_hhmmss.to_default_s, + 'Rails 7 default to_s' + else + assert_equal '2014-04-01T12:35:11+00:00', datetime_with_hhmmss.orig_to_s, + 'Rails 7 default to_s (via our shim)' + end assert_equal '01.04.2014 12:35', datetime_with_hhmmss.to_formatted_s(:default), 'Rails 6 default to_s' assert_equal datetime_with_hhmmss.to_formatted_s(:default), datetime_with_hhmmss.to_s, @@ -36,7 +53,11 @@ def test_datetime_to_s def test_time_to_s time = Time.new(2014, 4, 1, 12, 35, 11.5, '+01:00') - assert_equal '2014-04-01 12:35:11 +0100', time.to_default_s, 'Rails 7 default to_s' + if time.respond_to?(:to_default_s) # Only defined on Rails <= 7.1 + assert_equal '2014-04-01 12:35:11 +0100', time.to_default_s, 'Rails 7 default to_s' + else + assert_equal '2014-04-01 12:35:11 +0100', time.orig_to_s, 'Rails 7 default to_s (via our shim)' + end assert_equal '01.04.2014 12:35', time.to_formatted_s(:default), 'Rails 6 default to_s' assert_equal time.to_formatted_s(:default), time.to_s, 'We plan to change default to_s behaviour in a major version bump' @@ -47,8 +68,13 @@ def test_time_with_zone_to_s assert_equal 'BST', time_with_zone.zone # Without ndr_support extensions, we'd expect "2014-04-01 12:35:11 +0100" # but we have to trick the database into assuming all times are UTC to retain local time - assert_equal '2014-04-01 12:35:11 UTC', time_with_zone.to_default_s, - 'Rails 7 default to_s with our date and time formatting' + if time_with_zone.respond_to?(:to_default_s) # Only defined on Rails <= 7.1 + assert_equal '2014-04-01 12:35:11 UTC', time_with_zone.to_default_s, + 'Rails 7 default to_s with our date and time formatting' + else + assert_equal '2014-04-01 12:35:11 +0100', time_with_zone.orig_to_s, + 'Rails 7 default to_s with our date and time formatting (via our shim)' + end assert_equal '01.04.2014 12:35', time_with_zone.to_formatted_s(:default), 'Rails 6 default to_s' assert_equal time_with_zone.to_formatted_s(:default), time_with_zone.to_s, 'We plan to change default to_s behaviour in a major version bump' diff --git a/test/daterange_test.rb b/test/daterange_test.rb index 01520da..fefc001 100644 --- a/test/daterange_test.rb +++ b/test/daterange_test.rb @@ -166,11 +166,7 @@ def test_spen_daylight_saving def test_date_with_daylight_saving dr = Daterange.new(Date.new(2017, 9, 2)) # During daylight saving assert_equal '02.09.2017', dr.to_s - default_timezone = if ActiveRecord.respond_to?(:default_timezone) - ActiveRecord.default_timezone - else - ActiveRecord::Base.default_timezone # Rails <= 6.1 - end + default_timezone = ActiveRecord.default_timezone return unless default_timezone == :local assert_equal Date.new(2017, 9, 2).in_time_zone.utc_offset, dr.date1.utc_offset, 'Expect consistent offset' diff --git a/test/string/conversions_test.rb b/test/string/conversions_test.rb index 1ee9cbd..31c7ebb 100644 --- a/test/string/conversions_test.rb +++ b/test/string/conversions_test.rb @@ -84,11 +84,7 @@ class String::ConversionsTest < Minitest::Test test 'should convert strings to DateTime correctly' do assert_equal 0, '2018-01-02'.to_datetime.utc_offset - default_timezone = if ActiveRecord.respond_to?(:default_timezone) - ActiveRecord.default_timezone - else - ActiveRecord::Base.default_timezone # Rails <= 6.1 - end + default_timezone = ActiveRecord.default_timezone return unless default_timezone == :local assert_equal Time.new(2017, 9, 2).utc_offset, '2017-09-02'.to_datetime.utc_offset, 'Expect consistent offset' diff --git a/test/test_helper.rb b/test/test_helper.rb index cd9996b..9d327cb 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -16,11 +16,7 @@ # require all dates to be stored in UTC in the database. # Thus a birth date of 1975-06-01 would be stored as 1975-05-31 23.00.00. # Instead, we want to store all times in local time. -if ActiveRecord.respond_to?(:default_timezone=) - ActiveRecord.default_timezone = :local -else - ActiveRecord::Base.default_timezone = :local # Rails <= 6.1 -end +ActiveRecord.default_timezone = :local ActiveRecord::Base.time_zone_aware_attributes = false Time.zone = 'London'