diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index f6cd5efb4537ddcf3a7b897f0b97c95df9dddf3f..755fb32c3ffa6c0451bd51eb14bc92dd7d241dd8 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +* Fix how to calculate associated class name when using `habtm` namespaced. + + Fixes #14709. + + *Kassio Borges* + * `change_column_default` allows `[]` as argument to `change_column_default`. Fixes #11586. diff --git a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb index e47227737485b4f73792d4a7db0b44f1739230fa..ad781e50c9a5916c178642dd0bc641b576437dc8 100644 --- a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb @@ -23,7 +23,11 @@ def self.build(lhs_class, name, options) KnownTable.new options[:join_table].to_s else class_name = options.fetch(:class_name) { - name.to_s.camelize.singularize + model_name = name.to_s.camelize.singularize + if parent_name = lhs_class.parent_name.presence + model_name = model_name.prepend("#{parent_name}::") + end + model_name } KnownClass.new lhs_class, class_name end diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index cfdfff6af9d2a741c65e7e8ab15bd77ffecb9a3f..878f1877dbddfd37b362c40672541cb13caaa744 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -22,6 +22,9 @@ require 'models/country' require 'models/treaty' require 'models/vertex' +require 'models/publisher' +require 'models/publisher/article' +require 'models/publisher/magazine' require 'active_support/core_ext/string/conversions' class ProjectWithAfterCreateHook < ActiveRecord::Base @@ -848,4 +851,13 @@ def test_association_with_validate_false_does_not_run_associated_validation_call def test_custom_join_table assert_equal 'edges', Vertex.reflect_on_association(:sources).join_table end + + def test_namespaced_habtm + magazine = Publisher::Magazine.create + article = Publisher::Article.create + magazine.articles << article + magazine.save + + assert_includes magazine.articles, article + end end diff --git a/activerecord/test/models/publisher.rb b/activerecord/test/models/publisher.rb new file mode 100644 index 0000000000000000000000000000000000000000..0d4a7f92351a03de7cc8e9ff1fa44d1424627bc9 --- /dev/null +++ b/activerecord/test/models/publisher.rb @@ -0,0 +1,2 @@ +module Publisher +end diff --git a/activerecord/test/models/publisher/article.rb b/activerecord/test/models/publisher/article.rb new file mode 100644 index 0000000000000000000000000000000000000000..03a277bbddfd71b8fa716ff596e323d2f2f08ef2 --- /dev/null +++ b/activerecord/test/models/publisher/article.rb @@ -0,0 +1,3 @@ +class Publisher::Article < ActiveRecord::Base + has_and_belongs_to_many :magazines +end diff --git a/activerecord/test/models/publisher/magazine.rb b/activerecord/test/models/publisher/magazine.rb new file mode 100644 index 0000000000000000000000000000000000000000..82e1a14008ec447f6ef9786262b409a0f7f130d0 --- /dev/null +++ b/activerecord/test/models/publisher/magazine.rb @@ -0,0 +1,3 @@ +class Publisher::Magazine < ActiveRecord::Base + has_and_belongs_to_many :articles +end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index da3074e90f2f34c3acfa3eae8070466ee24e21dd..a78074d53042df2af3289293b16eda0be69171b9 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -62,6 +62,14 @@ def create_table(*args, &block) t.string :name end + create_table :articles, force: true do |t| + end + + create_table :articles_magazines, force: true do |t| + t.references :article + t.references :magazine + end + create_table :audit_logs, force: true do |t| t.column :message, :string, null: false t.column :developer_id, :integer, null: false @@ -385,6 +393,9 @@ def create_table(*args, &block) t.column :custom_lock_version, :integer end + create_table :magazines, force: true do |t| + end + create_table :mateys, id: false, force: true do |t| t.column :pirate_id, :integer t.column :target_id, :integer