diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 30ee65a67781..4cbfcd753d56 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -29,6 +29,9 @@ require "models/member" require "models/membership" require "models/club" +require "models/program" +require "models/program_offering" +require "models/enrollment" require "models/organization" require "models/user" require "models/family" @@ -1548,6 +1551,21 @@ def test_has_many_through_update_ids_with_conditions assert_equal [], author.nonspecial_categories_with_condition_ids end + def test_has_many_through_from_same_parent_to_same_child_creates_join_models + club = Club.new(name: "Awesome Rails Club") + member = club.simple_members.build(name: "Jane Doe") + + program = Program.new(name: "Learn Ruby on Rails") + program.members << member + + club.programs << program + + club.save! + + assert_equal(1, program.enrollments.size) + assert_equal(1, club.simple_memberships.size) + end + def test_single_has_many_through_association_with_unpersisted_parent_instance post_with_single_has_many_through = Class.new(Post) do def self.name; "PostWithSingleHasManyThrough"; end diff --git a/activerecord/test/models/club.rb b/activerecord/test/models/club.rb index 5d12be07965d..dc2a1b03f7cb 100644 --- a/activerecord/test/models/club.rb +++ b/activerecord/test/models/club.rb @@ -15,6 +15,12 @@ class Club < ActiveRecord::Base scope :general, -> { left_joins(:category).where(categories: { name: "General" }).unscope(:limit) } + has_many :program_offerings + has_many :programs, through: :program_offerings + + has_many :simple_memberships, class_name: "Membership" + has_many :simple_members, through: :simple_memberships, foreign_key: "member_id" + accepts_nested_attributes_for :membership private diff --git a/activerecord/test/models/enrollment.rb b/activerecord/test/models/enrollment.rb new file mode 100644 index 000000000000..38458ea2b840 --- /dev/null +++ b/activerecord/test/models/enrollment.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class Enrollment < ActiveRecord::Base + belongs_to :program + belongs_to :member, class_name: "SimpleMember" +end diff --git a/activerecord/test/models/member.rb b/activerecord/test/models/member.rb index f69aac061ea3..37837c08f8fb 100644 --- a/activerecord/test/models/member.rb +++ b/activerecord/test/models/member.rb @@ -44,6 +44,13 @@ class Member < ActiveRecord::Base scope :with_member_type_id, -> (id) { where(member_type_id: id) } end +class SimpleMember < ActiveRecord::Base + self.table_name = "members" + + has_many :memberships + has_many :clubs, through: :memberships +end + class SelfMember < ActiveRecord::Base self.table_name = "members" has_and_belongs_to_many :friends, class_name: "SelfMember", join_table: "member_friends" diff --git a/activerecord/test/models/membership.rb b/activerecord/test/models/membership.rb index 97bfd7391b67..b02a269efac0 100644 --- a/activerecord/test/models/membership.rb +++ b/activerecord/test/models/membership.rb @@ -4,6 +4,9 @@ class Membership < ActiveRecord::Base enum :type, %i(Membership CurrentMembership SuperMembership SelectedMembership TenantMembership) belongs_to :member belongs_to :club + has_one :sponsor, through: :club + + belongs_to :simple_member, foreign_key: "member_id" end class CurrentMembership < Membership diff --git a/activerecord/test/models/program.rb b/activerecord/test/models/program.rb new file mode 100644 index 000000000000..efb5425956fe --- /dev/null +++ b/activerecord/test/models/program.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class Program < ActiveRecord::Base + has_many :enrollments + has_many :members, through: :enrollments, class_name: "SimpleMember" +end diff --git a/activerecord/test/models/program_offering.rb b/activerecord/test/models/program_offering.rb new file mode 100644 index 000000000000..12606d304a55 --- /dev/null +++ b/activerecord/test/models/program_offering.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class ProgramOffering < ActiveRecord::Base + belongs_to :club + belongs_to :program +end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 4b778b37e158..966620cf42f4 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -588,6 +588,11 @@ t.references :car, index: false end + create_table :enrollments, force: true do |t| + t.integer :program_id + t.integer :member_id + end + create_table :entrants, force: true do |t| t.string :name, null: false t.integer :course_id, null: false @@ -1018,6 +1023,16 @@ t.decimal :discounted_price end + create_table :program_offerings, force: true do |t| + t.integer :club_id + t.integer :program_id + t.datetime :start_date + end + + create_table :programs, force: true do |t| + t.string :name + end + add_check_constraint :products, "price > discounted_price", name: "products_price_check" create_table :product_types, force: true do |t|