diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5fcb0b..4523ebb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,19 +14,21 @@ 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 + - Gemfile.rails-7.2-stable + ruby-version: ['3.1', '3.0'] + exclude: + - gemfile: Gemfile.rails-7.2-stable + ruby-version: "3.0" env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }} steps: - - uses: actions/checkout@v2 - - name: Set up Ruby + - uses: actions/checkout@v3 + - name: Set up Ruby ${{ matrix.ruby-version }} uses: ruby/setup-ruby@v1 with: - ruby-version: "2.6" + ruby-version: ${{ matrix.ruby-version }} - 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..5c8d227 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/setup-ruby@v1 + - uses: actions/checkout@v3 + - name: Set up Ruby 3.1 + uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7.x + ruby-version: 3.1 - name: Publish to RubyGems env: diff --git a/.gitignore b/.gitignore index fb6abe9..d0342bd 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,8 @@ test/version_tmp tmp .byebug_history 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 new file mode 100644 index 0000000..7e66bf5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,28 @@ +# Changelog + +## 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 + +## 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`. + +## 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 new file mode 100644 index 0000000..83cc5c2 --- /dev/null +++ b/gemfiles/Gemfile.rails-7.0-stable @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +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.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..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 @@ -64,8 +68,10 @@ def remove_type_and_establish_mapping(name, options, scope) 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 @@ -86,8 +92,10 @@ 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, &extension) + 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 def has_one(name, scope = nil, **options) @@ -96,8 +104,27 @@ def has_one(name, scope = nil, **options) scope = nil end - remove_type_and_establish_mapping(name, options, scope) - super(name, options.delete(:scope), **options) + 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(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 + 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 + 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..cd9cb87 --- /dev/null +++ b/lib/polymorphic_integer_type/polymorphic_foreign_association_extension.rb @@ -0,0 +1,11 @@ +module PolymorphicIntegerType + module PolymorphicForeignAssociationExtension + + def set_owner_attributes(record) + super + if reflection.try(:foreign_integer_type) && reflection.try(:integer_type) + record._write_attribute(reflection.foreign_integer_type, reflection.integer_type) + end + end + end +end diff --git a/lib/polymorphic_integer_type/version.rb b/lib/polymorphic_integer_type/version.rb index 2407f66..febae78 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.3.0" end diff --git a/polymorphic_integer_type.gemspec b/polymorphic_integer_type.gemspec index 7692e32..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" + 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 563fa49..6e426cf 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 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 HasOneReflection" 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 @@ -153,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 @@ -340,9 +362,22 @@ 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") 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..fdcbd3d 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' @@ -21,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| 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 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