From f547cd2fe8fcb66ab4ef8b3b18626d1e63ad338e Mon Sep 17 00:00:00 2001 From: Radu Cugut Date: Thu, 6 Jan 2022 13:13:01 -0500 Subject: [PATCH 01/19] handle ruby 3.x keyword arguments delegation https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/ --- lib/polymorphic_integer_type/extensions.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/polymorphic_integer_type/extensions.rb b/lib/polymorphic_integer_type/extensions.rb index 97bea34..9d43529 100644 --- a/lib/polymorphic_integer_type/extensions.rb +++ b/lib/polymorphic_integer_type/extensions.rb @@ -87,7 +87,7 @@ def has_many(name, scope = nil, **options, &extension) end remove_type_and_establish_mapping(name, options, scope) - super(name, options.delete(:scope), options, &extension) + super(name, options.delete(:scope), **options, &extension) end def has_one(name, scope = nil, **options) @@ -97,7 +97,7 @@ def has_one(name, scope = nil, **options) end remove_type_and_establish_mapping(name, options, scope) - super(name, options.delete(:scope), options) + super(name, options.delete(:scope), **options) end From 46cdaa478d09b12de96ea1d566a2339a03c4e264 Mon Sep 17 00:00:00 2001 From: Oleg Antonyan Date: Fri, 21 Jan 2022 23:09:22 +0200 Subject: [PATCH 02/19] unlock activerecord < 7 dependency --- polymorphic_integer_type.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polymorphic_integer_type.gemspec b/polymorphic_integer_type.gemspec index 827a846..7692e32 100644 --- a/polymorphic_integer_type.gemspec +++ b/polymorphic_integer_type.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] - spec.add_dependency "activerecord", "< 7" + spec.add_dependency "activerecord" spec.add_development_dependency "bundler" spec.add_development_dependency "rake" spec.add_development_dependency "rspec" From c01f473d3010dcd512e043791268765f7a305a37 Mon Sep 17 00:00:00 2001 From: Oleg Antonyan Date: Wed, 2 Feb 2022 14:32:29 +0200 Subject: [PATCH 03/19] fix non-integer relation --- .../activerecord_5_0_0/polymorphic_array_value_extension.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb b/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb index 7f1fc5e..df57836 100644 --- a/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb +++ b/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb @@ -29,7 +29,7 @@ def type_to_ids_mapping hash[key] << convert_to_id(value) else - hash[klass.polymorphic_name] << convert_to_id(value) + hash[klass(value)&.polymorphic_name] << convert_to_id(value) end end end From a74a8ea6bcf2d82a3f6adcecb1cb138edfb263c6 Mon Sep 17 00:00:00 2001 From: Peer Allan Date: Fri, 9 Jun 2023 07:46:52 -0500 Subject: [PATCH 04/19] Update Actions for Rails v7 and Ruby 3 --- .github/workflows/ci.yml | 7 +++---- .github/workflows/gem-push.yml | 6 +++--- gemfiles/Gemfile.rails-7.0-stable | 7 +++++++ polymorphic_integer_type.gemspec | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 gemfiles/Gemfile.rails-7.0-stable diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5fcb0b..8ad2f97 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,19 +14,18 @@ jobs: fail-fast: false matrix: gemfile: - - Gemfile.rails-5.0-stable - - Gemfile.rails-5.1-stable - Gemfile.rails-5.2-stable - Gemfile.rails-6.0-stable - Gemfile.rails-6.1-stable + - Gemfile.rails-7.0-stable env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: "2.6" + ruby-version: ["2.7", "3.0", "3.1"] - name: Install dependencies run: bundle install - name: Run tests diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 1142a5d..5df0db5 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -12,11 +12,11 @@ jobs: contents: read steps: - - uses: actions/checkout@v2 - - name: Set up Ruby 2.7 + - uses: actions/checkout@v3 + - name: Set up Ruby 3.0 uses: actions/setup-ruby@v1 with: - ruby-version: 2.7.x + ruby-version: 3.0.x - name: Publish to RubyGems env: diff --git a/gemfiles/Gemfile.rails-7.0-stable b/gemfiles/Gemfile.rails-7.0-stable new file mode 100644 index 0000000..8fb8ab2 --- /dev/null +++ b/gemfiles/Gemfile.rails-7.0-stable @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gemspec path: ".." + +gem "activerecord", github: "rails/rails", branch: "7-0-stable" diff --git a/polymorphic_integer_type.gemspec b/polymorphic_integer_type.gemspec index 7692e32..a33401e 100644 --- a/polymorphic_integer_type.gemspec +++ b/polymorphic_integer_type.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] - spec.add_dependency "activerecord" + spec.add_dependency "activerecord", "< 7.1" spec.add_development_dependency "bundler" spec.add_development_dependency "rake" spec.add_development_dependency "rspec" From 1ee36f129a7de95dc06d478e9e39fe427caa0ab7 Mon Sep 17 00:00:00 2001 From: Peer Allan Date: Fri, 9 Jun 2023 07:48:27 -0500 Subject: [PATCH 05/19] Update gitignore to ignore lockfiles --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fb6abe9..35bf47d 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ test/version_tmp tmp .byebug_history polymorphic_integer_type_test +gemfiles/*.lock From 957826ddd5e1c1b8d0fd39bdd2ddc49a45c579af Mon Sep 17 00:00:00 2001 From: Peer Allan Date: Fri, 9 Jun 2023 07:55:26 -0500 Subject: [PATCH 06/19] Fix incorrect format for CI with multiple Rubys --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ad2f97..890c696 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,14 +18,15 @@ jobs: - Gemfile.rails-6.0-stable - Gemfile.rails-6.1-stable - Gemfile.rails-7.0-stable + ruby-version: ['3.1', '3.0', '2.7'] env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }} steps: - uses: actions/checkout@v3 - - name: Set up Ruby + - name: Set up Ruby ${{ matrix.ruby-version }} uses: ruby/setup-ruby@v1 with: - ruby-version: ["2.7", "3.0", "3.1"] + ruby-version: ${{ matrix.ruby-version }} - name: Install dependencies run: bundle install - name: Run tests From 1172e9c8c0e340cde4e26f0bc642e3ad3cef55f5 Mon Sep 17 00:00:00 2001 From: Peer Allan Date: Fri, 9 Jun 2023 08:02:01 -0500 Subject: [PATCH 07/19] Add Ruby 3 CI exclustions --- .github/workflows/ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 890c696..acbe4ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,15 @@ jobs: - Gemfile.rails-6.1-stable - Gemfile.rails-7.0-stable ruby-version: ['3.1', '3.0', '2.7'] + exclude: + - gemfile: Gemfile.rails-6.0-stable + ruby-version: "3.0" + - gemfile: Gemfile.rails-6.0-stable + ruby-version: "3.1" + - gemfile: Gemfile.rails-5.2-stable + ruby-version: "3.0" + - gemfile: Gemfile.rails-5.2-stable + ruby-version: "3.1" env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }} steps: From ef12e691c23ced9124072f4369d9546e924cb385 Mon Sep 17 00:00:00 2001 From: Peer Allan Date: Fri, 9 Jun 2023 08:07:27 -0500 Subject: [PATCH 08/19] Bump to v3.2.0 --- lib/polymorphic_integer_type/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/polymorphic_integer_type/version.rb b/lib/polymorphic_integer_type/version.rb index 2407f66..7bd53b6 100644 --- a/lib/polymorphic_integer_type/version.rb +++ b/lib/polymorphic_integer_type/version.rb @@ -1,3 +1,3 @@ module PolymorphicIntegerType - VERSION = "3.1.1" + VERSION = "3.2.0" end From 9200eb4301570722ad5df9504b014acd51962329 Mon Sep 17 00:00:00 2001 From: Peer Allan Date: Fri, 9 Jun 2023 09:35:01 -0500 Subject: [PATCH 09/19] Fix gem publish action --- .github/workflows/gem-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 5df0db5..44c257a 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Ruby 3.0 - uses: actions/setup-ruby@v1 + uses: ruby/setup-ruby@v1 with: ruby-version: 3.0.x From 498a58438c52055e00d798be20d5363e5bc1078b Mon Sep 17 00:00:00 2001 From: Peer Allan Date: Fri, 9 Jun 2023 09:42:36 -0500 Subject: [PATCH 10/19] Another pipeline fix for publishing --- .github/workflows/gem-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 44c257a..db3aa27 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Ruby 3.0 uses: ruby/setup-ruby@v1 with: - ruby-version: 3.0.x + ruby-version: 3.0 - name: Publish to RubyGems env: From f77fc1ef9810788803e6d9d23d2f6fd40fb8dd90 Mon Sep 17 00:00:00 2001 From: Wendy Chen Date: Tue, 12 Dec 2023 14:16:02 -0500 Subject: [PATCH 11/19] write attribute with polymorphic integer type --- lib/polymorphic_integer_type.rb | 1 + lib/polymorphic_integer_type/extensions.rb | 29 +++++++++++++++++-- ...lymorphic_foreign_association_extension.rb | 13 +++++++++ spec/polymorphic_integer_type_spec.rb | 26 +++++++++++++++++ spec/support/animal.rb | 2 +- 5 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb diff --git a/lib/polymorphic_integer_type.rb b/lib/polymorphic_integer_type.rb index a68099c..b5bf33d 100644 --- a/lib/polymorphic_integer_type.rb +++ b/lib/polymorphic_integer_type.rb @@ -6,6 +6,7 @@ require "polymorphic_integer_type/module_generator" require "polymorphic_integer_type/belongs_to_polymorphic_association_extension" require "polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension" +require "polymorphic_integer_type/polymorphic_foreign_association_extension" if ACTIVE_RECORD_VERSION < Gem::Version.new("5.2.0") require "polymorphic_integer_type/activerecord_5_0_0/association_query_handler_extension" diff --git a/lib/polymorphic_integer_type/extensions.rb b/lib/polymorphic_integer_type/extensions.rb index 9d43529..64f3999 100644 --- a/lib/polymorphic_integer_type/extensions.rb +++ b/lib/polymorphic_integer_type/extensions.rb @@ -58,6 +58,8 @@ def remove_type_and_establish_mapping(name, options, scope) options[:foreign_key] ||= "#{poly_type}_id" foreign_type = options.delete(:foreign_type) || "#{poly_type}_type" + options[:foreign_integer_type] = foreign_type + options[:integer_type] = klass_mapping.to_i options[:scope] ||= -> { condition = where(foreign_type => klass_mapping.to_i) @@ -87,7 +89,9 @@ def has_many(name, scope = nil, **options, &extension) end remove_type_and_establish_mapping(name, options, scope) - super(name, options.delete(:scope), **options, &extension) + super(name, options.delete(:scope), **options.except(:foreign_integer_type, :integer_type), &extension).tap do |_| + remove_integer_type_and_set_attributes_and_extension(options, ActiveRecord::Reflection::HasManyReflection, reflections[name.to_s]) + end end def has_one(name, scope = nil, **options) @@ -97,7 +101,28 @@ def has_one(name, scope = nil, **options) end remove_type_and_establish_mapping(name, options, scope) - super(name, options.delete(:scope), **options) + super(name, options.delete(:scope), **options.except(:foreign_integer_type, :integer_type)).tap do |_| + remove_integer_type_and_set_attributes_and_extension(options, ActiveRecord::Reflection::HasOneReflection, reflections[name.to_s]) + end + end + + def remove_integer_type_and_set_attributes_and_extension(options, klass, reflection) + foreign_integer_type = options.delete :foreign_integer_type + integer_type = options.delete :integer_type + is_polymorphic_integer = foreign_integer_type && integer_type + + if is_polymorphic_integer + klass.attr_accessor(:foreign_integer_type) + klass.attr_accessor(:integer_type) + reflection.foreign_integer_type = foreign_integer_type + reflection.integer_type = integer_type + + if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("6.1") + ActiveRecord::Associations::Association.prepend(ActiveRecord::Associations::PolymorphicForeignAssociationExtension) + else + ActiveRecord::Associations::ForeignAssociation.prepend(ActiveRecord::Associations::PolymorphicForeignAssociationExtension) + end + end end diff --git a/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb b/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb new file mode 100644 index 0000000..18610f7 --- /dev/null +++ b/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb @@ -0,0 +1,13 @@ +module ActiveRecord + module Associations + module PolymorphicForeignAssociationExtension + + def set_owner_attributes(record) + super + if reflection.foreign_integer_type && reflection.integer_type + record._write_attribute(reflection.foreign_integer_type, reflection.integer_type) + end + end + end + end +end diff --git a/spec/polymorphic_integer_type_spec.rb b/spec/polymorphic_integer_type_spec.rb index 563fa49..c12f8d0 100644 --- a/spec/polymorphic_integer_type_spec.rb +++ b/spec/polymorphic_integer_type_spec.rb @@ -26,6 +26,28 @@ expect(link.target_type).to eq("Food") end + context "from HasManyReflection" do + it "sets the source properly from HasManyReflection" do + link_1 = Link.create() + link_2 = Link.create() + dog.source_links = [link_1, link_2] + expect(link_1.source_type).to eq("Animal") + expect(link_1.source_id).to eq(dog.id) + expect(link_2.source_type).to eq("Animal") + expect(link_1.source_id).to eq(dog.id) + end + end + + context "from HasOneReflection" do + it "sets the source properly from HasManyReflection" do + link = Link.create() + dog.source_link = link + + expect(link.source_type).to eq("Animal") + expect(link.source_id).to eq(dog.id) + end + end + context "when models are namespaced" do context "and mappings include namespaces" do it "sets the source_type" do @@ -340,6 +362,10 @@ class InlineDrink2 < ActiveRecord::Base expect(link[:target_type]).to eq(13) end + it "pulls mapping from given hash" do + animal.source_links.new + end + it "doesn't break string type polymorphic associations" do expect(link.normal_target).to eq(drink) expect(link.normal_target_type).to eq("InlineDrink2") diff --git a/spec/support/animal.rb b/spec/support/animal.rb index ca7db21..3a83839 100644 --- a/spec/support/animal.rb +++ b/spec/support/animal.rb @@ -3,5 +3,5 @@ class Animal < ActiveRecord::Base belongs_to :owner, class_name: "Person" has_many :source_links, as: :source, integer_type: true, class_name: "Link" - + has_one :source_link, as: :source, integer_type: true, class_name: "Link" end \ No newline at end of file From 2164bf3e7bb286a738f998a9beb65d6617ec923d Mon Sep 17 00:00:00 2001 From: Wendy Chen Date: Wed, 13 Dec 2023 10:52:47 -0500 Subject: [PATCH 12/19] comments' refactor --- .gitignore | 1 + CHANGELOG.md | 13 ++++++++ lib/polymorphic_integer_type/extensions.rb | 32 ++++++++++--------- ...lymorphic_foreign_association_extension.rb | 14 ++++---- lib/polymorphic_integer_type/version.rb | 2 +- spec/polymorphic_integer_type_spec.rb | 4 +-- 6 files changed, 40 insertions(+), 26 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.gitignore b/.gitignore index 35bf47d..1abc64e 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ tmp .byebug_history polymorphic_integer_type_test gemfiles/*.lock +.idea/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e7cb58e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +### Changed + +## v3.2.1 (2023-12-14) + +### Fixed + +- Not proper assigning polymorphic value with `has_many` and `has_one` reflection. + +### Added + +- Added .idea/ folder to .gitignore + +### Changed \ No newline at end of file diff --git a/lib/polymorphic_integer_type/extensions.rb b/lib/polymorphic_integer_type/extensions.rb index 64f3999..c6c1389 100644 --- a/lib/polymorphic_integer_type/extensions.rb +++ b/lib/polymorphic_integer_type/extensions.rb @@ -2,6 +2,10 @@ module PolymorphicIntegerType module Extensions module ClassMethods + ActiveRecord::Reflection::HasManyReflection.attr_accessor(:foreign_integer_type) + ActiveRecord::Reflection::HasManyReflection.attr_accessor(:integer_type) + ActiveRecord::Reflection::HasOneReflection.attr_accessor(:foreign_integer_type) + ActiveRecord::Reflection::HasOneReflection.attr_accessor(:integer_type) def belongs_to(name, scope = nil, **options) options = scope if scope.kind_of? Hash @@ -58,16 +62,16 @@ def remove_type_and_establish_mapping(name, options, scope) options[:foreign_key] ||= "#{poly_type}_id" foreign_type = options.delete(:foreign_type) || "#{poly_type}_type" - options[:foreign_integer_type] = foreign_type - options[:integer_type] = klass_mapping.to_i options[:scope] ||= -> { condition = where(foreign_type => klass_mapping.to_i) condition = instance_exec(&scope).merge(condition) if scope.is_a?(Proc) condition } + return foreign_type, klass_mapping.to_i else options[:scope] ||= scope + return nil, nil end end @@ -88,9 +92,9 @@ def has_many(name, scope = nil, **options, &extension) scope = nil end - remove_type_and_establish_mapping(name, options, scope) - super(name, options.delete(:scope), **options.except(:foreign_integer_type, :integer_type), &extension).tap do |_| - remove_integer_type_and_set_attributes_and_extension(options, ActiveRecord::Reflection::HasManyReflection, reflections[name.to_s]) + integer_type_values = remove_type_and_establish_mapping(name, options, scope) + super(name, options.delete(:scope), **options, &extension).tap do + remove_integer_type_and_set_attributes_and_extension(integer_type_values, reflections[name.to_s]) end end @@ -100,27 +104,25 @@ def has_one(name, scope = nil, **options) scope = nil end - remove_type_and_establish_mapping(name, options, scope) - super(name, options.delete(:scope), **options.except(:foreign_integer_type, :integer_type)).tap do |_| - remove_integer_type_and_set_attributes_and_extension(options, ActiveRecord::Reflection::HasOneReflection, reflections[name.to_s]) + integer_type_values = remove_type_and_establish_mapping(name, options, scope) + super(name, options.delete(:scope), **options).tap do + remove_integer_type_and_set_attributes_and_extension(integer_type_values, reflections[name.to_s]) end end - def remove_integer_type_and_set_attributes_and_extension(options, klass, reflection) - foreign_integer_type = options.delete :foreign_integer_type - integer_type = options.delete :integer_type + def remove_integer_type_and_set_attributes_and_extension(integer_type_values, reflection) + foreign_integer_type = integer_type_values[0] + integer_type = integer_type_values[1] is_polymorphic_integer = foreign_integer_type && integer_type if is_polymorphic_integer - klass.attr_accessor(:foreign_integer_type) - klass.attr_accessor(:integer_type) reflection.foreign_integer_type = foreign_integer_type reflection.integer_type = integer_type if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("6.1") - ActiveRecord::Associations::Association.prepend(ActiveRecord::Associations::PolymorphicForeignAssociationExtension) + ActiveRecord::Associations::Association.prepend(PolymorphicIntegerType::PolymorphicForeignAssociationExtension) else - ActiveRecord::Associations::ForeignAssociation.prepend(ActiveRecord::Associations::PolymorphicForeignAssociationExtension) + ActiveRecord::Associations::ForeignAssociation.prepend(PolymorphicIntegerType::PolymorphicForeignAssociationExtension) end end end diff --git a/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb b/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb index 18610f7..2b18d05 100644 --- a/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb +++ b/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb @@ -1,12 +1,10 @@ -module ActiveRecord - module Associations - module PolymorphicForeignAssociationExtension +module PolymorphicIntegerType + module PolymorphicForeignAssociationExtension - def set_owner_attributes(record) - super - if reflection.foreign_integer_type && reflection.integer_type - record._write_attribute(reflection.foreign_integer_type, reflection.integer_type) - end + def set_owner_attributes(record) + super + if reflection.foreign_integer_type && reflection.integer_type + record._write_attribute(reflection.foreign_integer_type, reflection.integer_type) end end end diff --git a/lib/polymorphic_integer_type/version.rb b/lib/polymorphic_integer_type/version.rb index 7bd53b6..28ec6e3 100644 --- a/lib/polymorphic_integer_type/version.rb +++ b/lib/polymorphic_integer_type/version.rb @@ -1,3 +1,3 @@ module PolymorphicIntegerType - VERSION = "3.2.0" + VERSION = "3.2.1" end diff --git a/spec/polymorphic_integer_type_spec.rb b/spec/polymorphic_integer_type_spec.rb index c12f8d0..3d56eb2 100644 --- a/spec/polymorphic_integer_type_spec.rb +++ b/spec/polymorphic_integer_type_spec.rb @@ -27,7 +27,7 @@ end context "from HasManyReflection" do - it "sets the source properly from HasManyReflection" do + it "sets the source properly HasManyReflection" do link_1 = Link.create() link_2 = Link.create() dog.source_links = [link_1, link_2] @@ -39,7 +39,7 @@ end context "from HasOneReflection" do - it "sets the source properly from HasManyReflection" do + it "sets the source properly HasOneReflection" do link = Link.create() dog.source_link = link From c9ad3773866e87c237842c19ab989434540909ed Mon Sep 17 00:00:00 2001 From: Wendy Chen Date: Tue, 19 Dec 2023 16:17:48 -0500 Subject: [PATCH 13/19] should still able to set other reflection successfully --- .../polymorphic_foreign_association_extension.rb | 2 +- spec/polymorphic_integer_type_spec.rb | 9 +++++++++ spec/spec_helper.rb | 2 ++ .../support/migrations/8_create_profile_table.rb | 16 ++++++++++++++++ .../migrations/9_create_profile_history_table.rb | 14 ++++++++++++++ spec/support/person.rb | 2 ++ spec/support/profile.rb | 4 ++++ spec/support/profile_history.rb | 3 +++ 8 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 spec/support/migrations/8_create_profile_table.rb create mode 100644 spec/support/migrations/9_create_profile_history_table.rb create mode 100644 spec/support/profile.rb create mode 100644 spec/support/profile_history.rb diff --git a/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb b/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb index 2b18d05..cd9cb87 100644 --- a/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb +++ b/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb @@ -3,7 +3,7 @@ module PolymorphicForeignAssociationExtension def set_owner_attributes(record) super - if reflection.foreign_integer_type && reflection.integer_type + if reflection.try(:foreign_integer_type) && reflection.try(:integer_type) record._write_attribute(reflection.foreign_integer_type, reflection.integer_type) end end diff --git a/spec/polymorphic_integer_type_spec.rb b/spec/polymorphic_integer_type_spec.rb index 3d56eb2..4af7d30 100644 --- a/spec/polymorphic_integer_type_spec.rb +++ b/spec/polymorphic_integer_type_spec.rb @@ -371,4 +371,13 @@ class InlineDrink2 < ActiveRecord::Base expect(link.normal_target_type).to eq("InlineDrink2") end end + + context "when using other reflection" do + it "owner able to association ActiveRecord::Reflection::ThroughReflection successfully" do + profile_history = ProfileHistory.new + owner.profile_histories << profile_history + + expect(owner.profile_histories).to eq([profile_history]) + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9e7ce1f..fb6e13d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -10,6 +10,8 @@ require 'support/person' require 'support/food' require 'support/drink' +require 'support/profile' +require 'support/profile_history' require 'support/namespaced_activity' require 'byebug' require 'pry' diff --git a/spec/support/migrations/8_create_profile_table.rb b/spec/support/migrations/8_create_profile_table.rb new file mode 100644 index 0000000..97add18 --- /dev/null +++ b/spec/support/migrations/8_create_profile_table.rb @@ -0,0 +1,16 @@ +class CreateProfileTable < ActiveRecord::Migration[5.0] + + def up + create_table :profiles do |t| + t.integer :person_id + t.integer :profile_history_id + end + end + + def down + drop_table :profiles + end + +end + + diff --git a/spec/support/migrations/9_create_profile_history_table.rb b/spec/support/migrations/9_create_profile_history_table.rb new file mode 100644 index 0000000..6eb3054 --- /dev/null +++ b/spec/support/migrations/9_create_profile_history_table.rb @@ -0,0 +1,14 @@ +class CreateProfileHistoryTable < ActiveRecord::Migration[5.0] + + def up + create_table :profile_histories do |t| + end + end + + def down + drop_table :profile_histories + end + +end + + diff --git a/spec/support/person.rb b/spec/support/person.rb index 59f5985..981a880 100644 --- a/spec/support/person.rb +++ b/spec/support/person.rb @@ -5,4 +5,6 @@ class Person < ActiveRecord::Base has_many :source_links, as: :source, integer_type: true, class_name: "Link" has_many :pet_source_links, class_name: "Link", through: :pets, source: :source_links + has_many :profiles + has_many :profile_histories, class_name: "ProfileHistory", through: :profiles end diff --git a/spec/support/profile.rb b/spec/support/profile.rb new file mode 100644 index 0000000..c669bd1 --- /dev/null +++ b/spec/support/profile.rb @@ -0,0 +1,4 @@ +class Profile < ActiveRecord::Base + belongs_to :person + belongs_to :profile_history +end diff --git a/spec/support/profile_history.rb b/spec/support/profile_history.rb new file mode 100644 index 0000000..bf55ee6 --- /dev/null +++ b/spec/support/profile_history.rb @@ -0,0 +1,3 @@ +class ProfileHistory < ActiveRecord::Base + has_many :profiles +end From 6f9bfc3b15f23d7abe216e157c2a44738cdb1e1a Mon Sep 17 00:00:00 2001 From: Wendy Chen Date: Thu, 21 Dec 2023 10:04:47 -0500 Subject: [PATCH 14/19] bump the version to 3.2.2 --- CHANGELOG.md | 6 ++++++ lib/polymorphic_integer_type/version.rb | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7cb58e..24c5106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,4 +10,10 @@ - Added .idea/ folder to .gitignore +## v3.2.2 (2023-12-21) + +### Fixed + +- Fixed polymorphic_foreign_association_extension.rb to be compatible with other reflection than `has_many` and `has_one`. + ### Changed \ No newline at end of file diff --git a/lib/polymorphic_integer_type/version.rb b/lib/polymorphic_integer_type/version.rb index 28ec6e3..1d194fe 100644 --- a/lib/polymorphic_integer_type/version.rb +++ b/lib/polymorphic_integer_type/version.rb @@ -1,3 +1,3 @@ module PolymorphicIntegerType - VERSION = "3.2.1" + VERSION = "3.2.2" end From 6253f679dcc3772740f1caf15b2ae916909fe0b4 Mon Sep 17 00:00:00 2001 From: Wendy Chen Date: Tue, 29 Oct 2024 10:54:53 -0400 Subject: [PATCH 15/19] upgrade rails to 7.2.x version; clean up unsupported rails and ruby version --- .github/workflows/ci.yml | 13 +++---------- .github/workflows/gem-push.yml | 4 ++-- .gitignore | 3 +++ CHANGELOG.md | 13 +++++++++++-- gemfiles/Gemfile.rails-5.0-stable | 8 -------- gemfiles/Gemfile.rails-5.2-stable | 7 ------- gemfiles/Gemfile.rails-6.0-stable | 7 ------- gemfiles/Gemfile.rails-6.1-stable | 1 + gemfiles/Gemfile.rails-7.0-stable | 1 + ...e.rails-5.1-stable => Gemfile.rails-7.2-stable} | 2 +- lib/polymorphic_integer_type/version.rb | 2 +- polymorphic_integer_type.gemspec | 2 +- spec/polymorphic_integer_type_spec.rb | 2 +- spec/spec_helper.rb | 14 +++++--------- 14 files changed, 30 insertions(+), 49 deletions(-) delete mode 100644 gemfiles/Gemfile.rails-5.0-stable delete mode 100644 gemfiles/Gemfile.rails-5.2-stable delete mode 100644 gemfiles/Gemfile.rails-6.0-stable rename gemfiles/{Gemfile.rails-5.1-stable => Gemfile.rails-7.2-stable} (56%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index acbe4ef..4523ebb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,20 +14,13 @@ jobs: fail-fast: false matrix: gemfile: - - Gemfile.rails-5.2-stable - - Gemfile.rails-6.0-stable - Gemfile.rails-6.1-stable - Gemfile.rails-7.0-stable - ruby-version: ['3.1', '3.0', '2.7'] + - Gemfile.rails-7.2-stable + ruby-version: ['3.1', '3.0'] exclude: - - gemfile: Gemfile.rails-6.0-stable + - gemfile: Gemfile.rails-7.2-stable ruby-version: "3.0" - - gemfile: Gemfile.rails-6.0-stable - ruby-version: "3.1" - - gemfile: Gemfile.rails-5.2-stable - ruby-version: "3.0" - - gemfile: Gemfile.rails-5.2-stable - ruby-version: "3.1" env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }} steps: diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index db3aa27..5c8d227 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up Ruby 3.0 + - name: Set up Ruby 3.1 uses: ruby/setup-ruby@v1 with: - ruby-version: 3.0 + ruby-version: 3.1 - name: Publish to RubyGems env: diff --git a/.gitignore b/.gitignore index 1abc64e..d0342bd 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ tmp polymorphic_integer_type_test gemfiles/*.lock .idea/ +.ruby-version +mysql +polymorphic_integer_type_test-* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 24c5106..7e66bf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### Changed +# Changelog ## v3.2.1 (2023-12-14) @@ -16,4 +16,13 @@ - Fixed polymorphic_foreign_association_extension.rb to be compatible with other reflection than `has_many` and `has_one`. -### Changed \ No newline at end of file +## v3.3.0 (2024-10-29) + +### Changed + +- Upgrade rails support version to be compatible with 7.2 + +### Removed + +- Remove unsupported rails versions(5.0, 5.2, 6.0) and ruby version(2.7) + diff --git a/gemfiles/Gemfile.rails-5.0-stable b/gemfiles/Gemfile.rails-5.0-stable deleted file mode 100644 index 9d07146..0000000 --- a/gemfiles/Gemfile.rails-5.0-stable +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" - -gemspec path: ".." - -gem "activerecord", github: "rails/rails", branch: "5-0-stable" -gem "sqlite3", "~> 1.3.6" diff --git a/gemfiles/Gemfile.rails-5.2-stable b/gemfiles/Gemfile.rails-5.2-stable deleted file mode 100644 index 5882b02..0000000 --- a/gemfiles/Gemfile.rails-5.2-stable +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" - -gemspec path: ".." - -gem "activerecord", github: "rails/rails", branch: "5-2-stable" diff --git a/gemfiles/Gemfile.rails-6.0-stable b/gemfiles/Gemfile.rails-6.0-stable deleted file mode 100644 index 8b85563..0000000 --- a/gemfiles/Gemfile.rails-6.0-stable +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" - -gemspec path: ".." - -gem "activerecord", github: "rails/rails", branch: "6-0-stable" diff --git a/gemfiles/Gemfile.rails-6.1-stable b/gemfiles/Gemfile.rails-6.1-stable index a50681f..5056859 100644 --- a/gemfiles/Gemfile.rails-6.1-stable +++ b/gemfiles/Gemfile.rails-6.1-stable @@ -5,3 +5,4 @@ source "https://rubygems.org" gemspec path: ".." gem "activerecord", github: "rails/rails", branch: "6-1-stable" +gem "sqlite3", "~> 1.4" diff --git a/gemfiles/Gemfile.rails-7.0-stable b/gemfiles/Gemfile.rails-7.0-stable index 8fb8ab2..83cc5c2 100644 --- a/gemfiles/Gemfile.rails-7.0-stable +++ b/gemfiles/Gemfile.rails-7.0-stable @@ -5,3 +5,4 @@ source "https://rubygems.org" gemspec path: ".." gem "activerecord", github: "rails/rails", branch: "7-0-stable" +gem "sqlite3", "~> 1.4" diff --git a/gemfiles/Gemfile.rails-5.1-stable b/gemfiles/Gemfile.rails-7.2-stable similarity index 56% rename from gemfiles/Gemfile.rails-5.1-stable rename to gemfiles/Gemfile.rails-7.2-stable index 7c93bab..84c3c79 100644 --- a/gemfiles/Gemfile.rails-5.1-stable +++ b/gemfiles/Gemfile.rails-7.2-stable @@ -4,4 +4,4 @@ source "https://rubygems.org" gemspec path: ".." -gem "activerecord", github: "rails/rails", branch: "5-1-stable" +gem "activerecord", github: "rails/rails", branch: "7-2-stable" diff --git a/lib/polymorphic_integer_type/version.rb b/lib/polymorphic_integer_type/version.rb index 1d194fe..febae78 100644 --- a/lib/polymorphic_integer_type/version.rb +++ b/lib/polymorphic_integer_type/version.rb @@ -1,3 +1,3 @@ module PolymorphicIntegerType - VERSION = "3.2.2" + VERSION = "3.3.0" end diff --git a/polymorphic_integer_type.gemspec b/polymorphic_integer_type.gemspec index a33401e..52bb61a 100644 --- a/polymorphic_integer_type.gemspec +++ b/polymorphic_integer_type.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] - spec.add_dependency "activerecord", "< 7.1" + spec.add_dependency "activerecord", "< 8" spec.add_development_dependency "bundler" spec.add_development_dependency "rake" spec.add_development_dependency "rspec" diff --git a/spec/polymorphic_integer_type_spec.rb b/spec/polymorphic_integer_type_spec.rb index 4af7d30..6e426cf 100644 --- a/spec/polymorphic_integer_type_spec.rb +++ b/spec/polymorphic_integer_type_spec.rb @@ -175,7 +175,7 @@ before { link } it "should have the proper source" do - expect(source.source_links[0].source).to eql source + expect(source.reload.source_links[0].source).to eql source end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index fb6e13d..fdcbd3d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -23,18 +23,14 @@ active_record_version = Gem::Version.new(ActiveRecord::VERSION::STRING) ActiveRecord::Base.establish_connection(database_config) - - if active_record_version < Gem::Version.new("5.2") - ActiveRecord::Migrator.migrate(migrations_path) - end - - if active_record_version >= Gem::Version.new("5.2") && active_record_version < Gem::Version.new("6.0") - ActiveRecord::MigrationContext.new(migrations_path).migrate - end - if active_record_version >= Gem::Version.new("6.0") + if active_record_version >= Gem::Version.new("6.1") && active_record_version < Gem::Version.new("7.0") ActiveRecord::MigrationContext.new(migrations_path, ActiveRecord::SchemaMigration).migrate end + + if active_record_version >= Gem::Version.new("7.0") + ActiveRecord::MigrationContext.new(migrations_path).migrate + end end config.around do |example| From ced3ea074752f6221ae0c45dab28df93bae51ce7 Mon Sep 17 00:00:00 2001 From: Parsa Honarmand <170973799+parsahonarmand99@users.noreply.github.com> Date: Fri, 25 Jul 2025 10:41:19 -0600 Subject: [PATCH 16/19] Rails 8 support (#67) * Update to allow for rails 8 compatibility * update gem version * modify rakefile to support both sqlite3 and mysql * modify the test matrix * cleanup Rakefile * Use sqlite3 for tests * update readme * set version to 3.4 * remove rails 6.x support * Test rails 7 with ruby 3.0 --- .github/workflows/ci.yml | 12 +++-- CHANGELOG.md | 8 +++ README.md | 11 +++- Rakefile | 50 ++++++++++--------- gemfiles/Gemfile.rails-6.1-stable | 8 --- gemfiles/Gemfile.rails-8.0-stable | 7 +++ .../polymorphic_array_value_extension.rb | 6 +-- ...gs_to_polymorphic_association_extension.rb | 13 ++--- lib/polymorphic_integer_type/extensions.rb | 7 +-- lib/polymorphic_integer_type/version.rb | 4 +- polymorphic_integer_type.gemspec | 35 +++++++------ spec/spec_helper.rb | 9 +--- 12 files changed, 88 insertions(+), 82 deletions(-) delete mode 100644 gemfiles/Gemfile.rails-6.1-stable create mode 100644 gemfiles/Gemfile.rails-8.0-stable diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4523ebb..5d13f30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,13 +14,19 @@ jobs: fail-fast: false matrix: gemfile: - - Gemfile.rails-6.1-stable - Gemfile.rails-7.0-stable - Gemfile.rails-7.2-stable - ruby-version: ['3.1', '3.0'] + - Gemfile.rails-8.0-stable + ruby-version: ['3.0', '3.1', '3.2', '3.3'] exclude: + # Rails 7.2 doesn't work with Ruby 3.0 (requires Ruby 3.1+) - gemfile: Gemfile.rails-7.2-stable - ruby-version: "3.0" + ruby-version: '3.0' + # Rails 8.0 doesn't work with Ruby 3.0 or 3.1 (requires Ruby 3.2+) + - gemfile: Gemfile.rails-8.0-stable + ruby-version: '3.0' + - gemfile: Gemfile.rails-8.0-stable + ruby-version: '3.1' env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }} steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e66bf5..47b6efe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,3 +26,11 @@ - Remove unsupported rails versions(5.0, 5.2, 6.0) and ruby version(2.7) +## v3.4.0 (2024-XX-XX) + +### Added + +- Add Rails 8.0 compatibility (requires Ruby 3.2+) + +### Removed +- Remove unsupported rails versions 6.x \ No newline at end of file diff --git a/README.md b/README.md index 5d72bd9..14573c1 100644 --- a/README.md +++ b/README.md @@ -138,16 +138,23 @@ Lastly, you will need to be careful of any place where you are doing raw SQL que ## Setup -You'll need to have git, Ruby, and MySQL. Then get up and running with a few commands: +You'll need to have git and Ruby. Then get up and running with a few commands: ```bash $ git clone ... $ bundle install $ vim spec/support/database.yml # Update username and password -$ bin/setup +$ bin/setup # Uses SQLite3 for testing (no additional setup required) $ bundle exec rspec ``` +## Database Compatibility + +This gem works with any database supported by ActiveRecord (SQLite3, MySQL, PostgreSQL, etc.). +The gem extends ActiveRecord's polymorphic associations and doesn't use database-specific features. + +Development and testing uses SQLite3 for simplicity. + ## Contributing 1. Fork it diff --git a/Rakefile b/Rakefile index cb6b440..39eb26e 100644 --- a/Rakefile +++ b/Rakefile @@ -1,48 +1,52 @@ -require "bundler/gem_tasks" -require "yaml" -require "active_record" +# frozen_string_literal: true + +require 'bundler/gem_tasks' +require 'yaml' +require 'active_record' namespace :test do task :all do - Dir.glob("./gemfiles/Gemfile*").each do |gemfile| - next if gemfile.end_with?(".lock") + Dir.glob('./gemfiles/Gemfile*').each do |gemfile| + next if gemfile.end_with?('.lock') + puts "Running specs for #{Pathname.new(gemfile).basename}" system("BUNDLE_GEMFILE=#{gemfile} bundle install > /dev/null && BUNDLE_GEMFILE=#{gemfile} bundle exec rspec") - puts "" + puts '' end end end namespace :db do - database_config = YAML.load(File.open("./spec/support/database.yml")) - admin_database_config = database_config.merge(database: "mysql") - migration_path = File.expand_path("./spec/support/migrations") + database_config = YAML.load(File.open('./spec/support/database.yml')) + migration_path = File.expand_path('./spec/support/migrations') - desc "Create the database" + desc 'Create the database' task :create do - ActiveRecord::Base.establish_connection(admin_database_config) - ActiveRecord::Base.connection.create_database(database_config.fetch(:database)) - puts "Database created." + # SQLite3 creates the database file automatically, just ensure directory exists + db_file = database_config.fetch(:database) + FileUtils.mkdir_p(File.dirname(db_file)) unless File.dirname(db_file) == '.' + puts 'Database ready (SQLite3).' end - desc "Migrate the database" + desc 'Migrate the database' task :migrate do ActiveRecord::Base.establish_connection(database_config) - ActiveRecord::Migrator.migrate(migration_path) - Rake::Task["db:schema"].invoke - puts "Database migrated." + ActiveRecord::MigrationContext.new(migration_path).migrate + Rake::Task['db:schema'].invoke + puts 'Database migrated.' end - desc "Drop the database" + desc 'Drop the database' task :drop do - ActiveRecord::Base.establish_connection(admin_database_config) - ActiveRecord::Base.connection.drop_database(database_config.fetch(:database)) - puts "Database deleted." + # For SQLite3, just delete the file + db_file = database_config.fetch(:database) + File.delete(db_file) if File.exist?(db_file) + puts 'Database deleted.' end - desc "Reset the database" + desc 'Reset the database' task reset: [:drop, :create, :migrate] - desc 'Create a db/schema.rb file that is portable against any DB supported by AR' + desc 'Create a db/schema.rb file that is portable against any DB supported by AR' task :schema do # Noop to make ActiveRecord happy diff --git a/gemfiles/Gemfile.rails-6.1-stable b/gemfiles/Gemfile.rails-6.1-stable deleted file mode 100644 index 5056859..0000000 --- a/gemfiles/Gemfile.rails-6.1-stable +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" - -gemspec path: ".." - -gem "activerecord", github: "rails/rails", branch: "6-1-stable" -gem "sqlite3", "~> 1.4" diff --git a/gemfiles/Gemfile.rails-8.0-stable b/gemfiles/Gemfile.rails-8.0-stable new file mode 100644 index 0000000..c486345 --- /dev/null +++ b/gemfiles/Gemfile.rails-8.0-stable @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gemspec path: ".." + +gem "activerecord", github: "rails/rails", branch: "8-0-stable" diff --git a/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb b/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb index df57836..1f44ce2 100644 --- a/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb +++ b/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb @@ -10,11 +10,7 @@ module PolymorphicArrayValueExtension # end def type_to_ids_mapping - if ACTIVE_RECORD_VERSION < Gem::Version.new("6.1") - association = @associated_table.send(:association) - else - association = @associated_table.send(:reflection) - end + association = @associated_table.send(:reflection) name = association.name default_hash = Hash.new { |hsh, key| hsh[key] = [] } diff --git a/lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb b/lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb index 8840fc2..5671294 100644 --- a/lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb +++ b/lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb @@ -3,16 +3,9 @@ module Associations class BelongsToPolymorphicAssociation < BelongsToAssociation private - if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("6.1") - def replace_keys(record) - super - owner[reflection.foreign_type] = record.class.base_class unless record.nil? - end - elsif - def replace_keys(record, force: false) - super - owner[reflection.foreign_type] = record.class.base_class unless record.nil? - end + def replace_keys(record, force: false) + super + owner[reflection.foreign_type] = record.class.base_class unless record.nil? end end end diff --git a/lib/polymorphic_integer_type/extensions.rb b/lib/polymorphic_integer_type/extensions.rb index c6c1389..8e2144f 100644 --- a/lib/polymorphic_integer_type/extensions.rb +++ b/lib/polymorphic_integer_type/extensions.rb @@ -118,12 +118,7 @@ def remove_integer_type_and_set_attributes_and_extension(integer_type_values, re if is_polymorphic_integer reflection.foreign_integer_type = foreign_integer_type reflection.integer_type = integer_type - - if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("6.1") - ActiveRecord::Associations::Association.prepend(PolymorphicIntegerType::PolymorphicForeignAssociationExtension) - else - ActiveRecord::Associations::ForeignAssociation.prepend(PolymorphicIntegerType::PolymorphicForeignAssociationExtension) - end + ActiveRecord::Associations::ForeignAssociation.prepend(PolymorphicIntegerType::PolymorphicForeignAssociationExtension) end end diff --git a/lib/polymorphic_integer_type/version.rb b/lib/polymorphic_integer_type/version.rb index febae78..c1e9c4d 100644 --- a/lib/polymorphic_integer_type/version.rb +++ b/lib/polymorphic_integer_type/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module PolymorphicIntegerType - VERSION = "3.3.0" + VERSION = '3.4.0' end diff --git a/polymorphic_integer_type.gemspec b/polymorphic_integer_type.gemspec index 52bb61a..babacda 100644 --- a/polymorphic_integer_type.gemspec +++ b/polymorphic_integer_type.gemspec @@ -1,27 +1,30 @@ -# coding: utf-8 -lib = File.expand_path('../lib', __FILE__) +# frozen_string_literal: true + +lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'polymorphic_integer_type/version' Gem::Specification.new do |spec| - spec.name = "polymorphic_integer_type" + spec.name = 'polymorphic_integer_type' spec.version = PolymorphicIntegerType::VERSION - spec.authors = ["Kyle d'Oliveira"] - spec.email = ["kyle@goclio.com"] - spec.description = %q{Allows the *_type field in the DB to be an integer rather than a string} - spec.summary = %q{Use integers rather than strings for the _type field} - spec.homepage = "" - spec.license = "MIT" + spec.authors = ['Kyle d\'Oliveira'] + spec.email = ['kyle@goclio.com'] + spec.description = 'Allows the *_type field in the DB to be an integer rather than a string' + spec.summary = 'Use integers rather than strings for the _type field' + spec.homepage = '' + spec.license = 'MIT' + + spec.required_ruby_version = '>= 3.0' spec.files = `git ls-files -- . ':!.github/'`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) - spec.require_paths = ["lib"] + spec.require_paths = ['lib'] - spec.add_dependency "activerecord", "< 8" - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "rspec" - spec.add_development_dependency "sqlite3" - spec.add_development_dependency "pry-byebug" + spec.add_dependency 'activerecord', '< 9.0' + spec.add_development_dependency 'bundler' + spec.add_development_dependency 'pry-byebug' + spec.add_development_dependency 'rake' + spec.add_development_dependency 'rspec' + spec.add_development_dependency 'sqlite3' end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index fdcbd3d..192de66 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -20,17 +20,10 @@ config.before(:suite) do database_config = YAML.load(File.open("#{File.dirname(__FILE__)}/support/database.yml")) migrations_path = "#{File.dirname(__FILE__)}/support/migrations" - active_record_version = Gem::Version.new(ActiveRecord::VERSION::STRING) ActiveRecord::Base.establish_connection(database_config) - - if active_record_version >= Gem::Version.new("6.1") && active_record_version < Gem::Version.new("7.0") - ActiveRecord::MigrationContext.new(migrations_path, ActiveRecord::SchemaMigration).migrate - end - if active_record_version >= Gem::Version.new("7.0") - ActiveRecord::MigrationContext.new(migrations_path).migrate - end + ActiveRecord::MigrationContext.new(migrations_path).migrate end config.around do |example| From c5f33191070666af831f0e9d204209481216a178 Mon Sep 17 00:00:00 2001 From: Ray Masiclat Date: Thu, 30 Apr 2026 13:30:57 -0600 Subject: [PATCH 17/19] feat: support Rails 8.1 in PolymorphicArrayValueExtension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rails 8.1 changed `ActiveRecord::PredicateBuilder::PolymorphicArrayValue#initialize` from `(associated_table, values)` to `(reflection, values)`, dropping the `@associated_table` ivar that this gem reads via `@associated_table.send(:reflection)` in `type_to_ids_mapping`. Without an update, every polymorphic-array predicate query (e.g. `Model.where(thing: [a, b])`) raises `NoMethodError: undefined method 'reflection' for nil` on Rails 8.1. The minimal fix: read `@reflection` directly when set (Rails 8.1+), fall back to `@associated_table.send(:reflection)` for older Rails versions. The rest of the method runs unchanged. This also adds Gemfile.rails-8.1-stable to the CI matrix so future regressions are caught upstream rather than in downstream apps. ## Verification The existing spec at `polymorphic_integer_type_spec.rb:135` ("properly finds the object when passing an array of sources") exercises exactly this code path: Link.where(source: [source]) Verified locally: - Rails 8.0: 41/41 passing - Rails 8.1: 41/41 passing - Rails 8.1 *without* this fix: 1 failure (the array-of-sources test) — proves the test catches the regression and the fix resolves it. Downstream apps (clio/accounting, clio/manage, clio/themis, etc.) currently maintain in-app monkey patches for this; bumping to 3.5.0 lets them delete those. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 6 ++++++ CHANGELOG.md | 6 ++++++ gemfiles/Gemfile.rails-8.1-stable | 7 +++++++ .../polymorphic_array_value_extension.rb | 10 +++++++++- lib/polymorphic_integer_type/version.rb | 2 +- 5 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 gemfiles/Gemfile.rails-8.1-stable diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d13f30..4237833 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ jobs: - Gemfile.rails-7.0-stable - Gemfile.rails-7.2-stable - Gemfile.rails-8.0-stable + - Gemfile.rails-8.1-stable ruby-version: ['3.0', '3.1', '3.2', '3.3'] exclude: # Rails 7.2 doesn't work with Ruby 3.0 (requires Ruby 3.1+) @@ -27,6 +28,11 @@ jobs: ruby-version: '3.0' - gemfile: Gemfile.rails-8.0-stable ruby-version: '3.1' + # Rails 8.1 requires Ruby 3.2+ + - gemfile: Gemfile.rails-8.1-stable + ruby-version: '3.0' + - gemfile: Gemfile.rails-8.1-stable + ruby-version: '3.1' env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }} steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 47b6efe..517b404 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v3.5.0 (2026-04-30) + +### Added + +- Add Rails 8.1 compatibility. Rails 8.1 changed `PredicateBuilder::PolymorphicArrayValue#initialize` from `(associated_table, values)` to `(reflection, values)`, dropping the `@associated_table` ivar. `type_to_ids_mapping` now reads `@reflection` when available and falls back to `@associated_table.send(:reflection)` for older Rails versions. + ## v3.2.1 (2023-12-14) ### Fixed diff --git a/gemfiles/Gemfile.rails-8.1-stable b/gemfiles/Gemfile.rails-8.1-stable new file mode 100644 index 0000000..b6f721a --- /dev/null +++ b/gemfiles/Gemfile.rails-8.1-stable @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gemspec path: ".." + +gem "activerecord", github: "rails/rails", branch: "8-1-stable" diff --git a/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb b/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb index 1f44ce2..b45df40 100644 --- a/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb +++ b/lib/polymorphic_integer_type/activerecord_5_0_0/polymorphic_array_value_extension.rb @@ -10,7 +10,15 @@ module PolymorphicArrayValueExtension # end def type_to_ids_mapping - association = @associated_table.send(:reflection) + # Rails 8.1 changed `PredicateBuilder::PolymorphicArrayValue#initialize` + # from `(associated_table, values)` to `(reflection, values)`, dropping + # the `@associated_table` ivar. Read whichever ivar is available so this + # gem works across Rails 6.1–8.1. + association = if instance_variable_defined?(:@reflection) && @reflection + @reflection + else + @associated_table.send(:reflection) + end name = association.name default_hash = Hash.new { |hsh, key| hsh[key] = [] } diff --git a/lib/polymorphic_integer_type/version.rb b/lib/polymorphic_integer_type/version.rb index c1e9c4d..27b1ad4 100644 --- a/lib/polymorphic_integer_type/version.rb +++ b/lib/polymorphic_integer_type/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module PolymorphicIntegerType - VERSION = '3.4.0' + VERSION = '3.5.0' end From 986cd98c6910e7d8a202dd75942e422538b85c00 Mon Sep 17 00:00:00 2001 From: Ray Masiclat Date: Thu, 30 Apr 2026 13:39:29 -0600 Subject: [PATCH 18/19] test: add multi-type polymorphic-array spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing array-of-sources test only exercises a single-type array (`Link.where(source: [cat])`). The fix's value also covers multi-type arrays (`Link.where(source: [cat, dog])`) — a broader branch of `type_to_ids_mapping` where the result hash spans multiple keys. Locks in coverage on both Rails 8.0 (backwards compat) and 8.1. Suggested by code review. Co-Authored-By: Claude Opus 4.7 (1M context) --- spec/polymorphic_integer_type_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/polymorphic_integer_type_spec.rb b/spec/polymorphic_integer_type_spec.rb index 6e426cf..73a4cdd 100644 --- a/spec/polymorphic_integer_type_spec.rb +++ b/spec/polymorphic_integer_type_spec.rb @@ -136,6 +136,11 @@ expect(Link.where(source: [source])).to eq [link] end + it "properly finds objects when passing an array of mixed-type sources" do + link_for_dog = Link.create(source: dog) + expect(Link.where(source: [cat, dog])).to match_array [link, link_for_dog] + end + it "properly finds the object with a find_by" do expect(Link.find_by(source: source, id: link.id)).to eql link end From 073022e00f1934ed09a405dc9bc641e170fe6253 Mon Sep 17 00:00:00 2001 From: Arman Harutyunyan Date: Thu, 23 Jul 2026 11:26:53 -0700 Subject: [PATCH 19/19] Track upstream v3.5.0; keep polymorphic_name guard for plain polymorphic used in `rma` --- README.md | 10 +++++ ...gs_to_polymorphic_association_extension.rb | 27 +++++++++++++- spec/fcm_polymorphic_name_guard_spec.rb | 37 +++++++++++++++++++ spec/spec_helper.rb | 1 + spec/support/country.rb | 12 ++++++ spec/support/link.rb | 11 ++++++ ...untry_table_and_legacy_source_reference.rb | 23 ++++++++++++ 7 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 spec/fcm_polymorphic_name_guard_spec.rb create mode 100644 spec/support/country.rb create mode 100644 spec/support/migrations/10_create_country_table_and_legacy_source_reference.rb diff --git a/README.md b/README.md index 14573c1..d01a0a4 100644 --- a/README.md +++ b/README.md @@ -162,3 +162,13 @@ Development and testing uses SQLite3 for simplicity. 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request + +# FCM Annotations + +This fork of `clio/polymorphic_integer_type` should stay in sync with upstream. As of the Rails 8 upgrade (FCM-8671) it is based on upstream **v3.5.0** with a single intentional difference. + +**The only change from the fork** is a guard in `lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb`. Upstream unconditionally rewrites a polymorphic association's stored `_type` to the target's `base_class`, which clobbers a model's custom `polymorphic_name` on plain `polymorphic: true` associations. We scope that rewrite to this gem's integer-type associations only, so plain polymorphic associations respect `polymorphic_name` (the `rma` app relies on this, for example: `Enrollment.polymorphic_name => 'Patient::Segment'`). + +Regression coverage is in `spec/fcm_polymorphic_name_guard_spec.rb`, along with the `Country` / `legacy_source` test fixtures. + +**When re-syncing with upstream, re-apply the guard after merging.** diff --git a/lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb b/lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb index 5671294..a7930ba 100644 --- a/lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb +++ b/lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb @@ -5,7 +5,32 @@ class BelongsToPolymorphicAssociation < BelongsToAssociation def replace_keys(record, force: false) super - owner[reflection.foreign_type] = record.class.base_class unless record.nil? + return if record.nil? + + # FCM fork delta -- RE-APPLY after any upstream sync! + # + # This gem *reopens* (does not prepend) `BelongsToPolymorphicAssociation`, + # so the `super` above is BelongsToAssociation#replace_keys, which sets + # the foreign key but NOT the polymorphic type, so this method is + # responsible for the `_type`. + # + # Upstream sets it unconditionally to the target's `base_class`, which + # clobbers a model's custom `polymorphic_name` on plain `polymorphic: true` + # associations. + # + # The rma app relies on custom `polymorphic_name` (e.g. + # Enrollment => 'Patient::Segment'), so use `base_class` ONLY for this + # gem's integer-type associations (detected via the generated + # `_mapping` class method) and fall back to Rails' + # `polymorphic_name` for plain polymorphic associations. + # + # Regression is tested in spec/fcm_polymorphic_name_guard_spec.rb. + owner[reflection.foreign_type] = + if owner.class.respond_to?("#{reflection.foreign_type}_mapping") + record.class.base_class + else + record.class.polymorphic_name + end end end end diff --git a/spec/fcm_polymorphic_name_guard_spec.rb b/spec/fcm_polymorphic_name_guard_spec.rb new file mode 100644 index 0000000..0fa94bf --- /dev/null +++ b/spec/fcm_polymorphic_name_guard_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +# FCM fork regression test +# +# This fork of clio/polymorphic_integer_type carries exactly ONE intentional +# difference over upstream (see the "FCM Annotations" section of README.md and +# the guard in lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb): +# +# Upstream unconditionally rewrites a polymorphic association's stored `_type` +# to the target's `base_class`. That clobbers a model's custom `polymorphic_name` +# on PLAIN `polymorphic: true` associations. The rma app depends on custom +# `polymorphic_name` (e.g. Enrollment.polymorphic_name => 'Patient::Segment'), +# so the guard restricts that rewrite to this gem's integer-type associations only. +# +# If a future upstream re-sync drops the guard, these specs fail - which is the point. +RSpec.describe 'FCM: polymorphic_name on plain polymorphic associations' do + let(:country) { Country.create!(name: 'Canada') } + + it "stores the target's polymorphic_name (not its base_class) on a plain polymorphic belongs_to" do + link = Link.create!(legacy_source: country) + + # Pure upstream (no guard) would store 'Country' (base_class) here. + expect(link.legacy_source_type).to eq('Nation') + end + + it 'reads the plain polymorphic association back via polymorphic_class_for' do + link = Link.create!(legacy_source: country) + + expect(link.reload.legacy_source).to eq(country) + end + + it 'guards plain polymorphic associations only, leaving integer-type ones to the gem' do + # `source` is integer-type (the gem defines `source_type_mapping`); `legacy_source` is plain. + expect(Link).to respond_to(:source_type_mapping) + expect(Link).not_to respond_to(:legacy_source_type_mapping) + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 192de66..26774ac 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,7 @@ require 'polymorphic_integer_type' require 'support/configuration' require 'support/link' +require 'support/country' require 'support/animal' require 'support/namespaced_animal' require 'support/namespaced_plant' diff --git a/spec/support/country.rb b/spec/support/country.rb new file mode 100644 index 0000000..15f36ac --- /dev/null +++ b/spec/support/country.rb @@ -0,0 +1,12 @@ +# FCM regression fixture (see spec/fcm_polymorphic_name_guard_spec.rb). +# +# A plain (non-integer-type) polymorphic target whose `polymorphic_name` differs +# from its class name. This mirrors the rma app's real case (Enrollment.polymorphic_name => +# 'Patient::Segment') and is used to prove the fork's guard leaves plain +# polymorphic associations to Rails so the custom polymorphic_name is stored - +# rather than upstream's unconditional base_class rewrite. +class Country < ActiveRecord::Base + def self.polymorphic_name + 'Nation' + end +end diff --git a/spec/support/link.rb b/spec/support/link.rb index f49bdd1..3be89ca 100644 --- a/spec/support/link.rb +++ b/spec/support/link.rb @@ -3,4 +3,15 @@ class Link < ActiveRecord::Base belongs_to :source, polymorphic: true, integer_type: true belongs_to :target, polymorphic: true, integer_type: true + + # FCM regression fixture (see spec/fcm_polymorphic_name_guard_spec.rb): a + # plain (non-integer-type) polymorphic association whose target (Country) + # overrides `polymorphic_name`. Exercises the fork's guard that leaves plain + # polymorphic associations to Rails instead of forcing the target's base_class. + belongs_to :legacy_source, polymorphic: true + + # Resolve the custom polymorphic_name ('Nation') back to Country on read. + def self.polymorphic_class_for(name) + name == 'Nation' ? Country : super + end end diff --git a/spec/support/migrations/10_create_country_table_and_legacy_source_reference.rb b/spec/support/migrations/10_create_country_table_and_legacy_source_reference.rb new file mode 100644 index 0000000..893164b --- /dev/null +++ b/spec/support/migrations/10_create_country_table_and_legacy_source_reference.rb @@ -0,0 +1,23 @@ +# FCM regression fixture - supports spec/fcm_polymorphic_name_guard_spec.rb and +# the fork delta documented in lib/polymorphic_integer_type/belongs_to_polymorphic_association_extension.rb. +# +# Adds a plain (string-typed) polymorphic `legacy_source` to `links`, plus a +# `countries` table whose model (Country) overrides `polymorphic_name`. +class CreateCountryTableAndLegacySourceReference < ActiveRecord::Migration[5.0] + + def up + create_table :countries do |t| + t.string :name + end + + add_column :links, :legacy_source_id, :integer + add_column :links, :legacy_source_type, :string + end + + def down + remove_column :links, :legacy_source_type + remove_column :links, :legacy_source_id + drop_table :countries + end + +end