mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Support storing demodulized class name for polymorphic type
This is an alternative of #29722. Before Rails 6.1, storing demodulized class name is supported only for STI type by `store_full_sti_class` class attribute. Now `store_full_class_name` class attribute can handle both STI and polymorphic types. Closes #29722. See also #29601, #32048, #32148.
This commit is contained in:
parent
97066dac7a
commit
62cfbdf36e
3 changed files with 100 additions and 17 deletions
|
@ -1,3 +1,12 @@
|
|||
* Support storing demodulized class name for polymorphic type.
|
||||
|
||||
Before Rails 6.1, storing demodulized class name is supported only for STI type
|
||||
by `store_full_sti_class` class attribute.
|
||||
|
||||
Now `store_full_class_name` class attribute can handle both STI and polymorphic types.
|
||||
|
||||
*Ryuta Kamizono*
|
||||
|
||||
* Deprecate `rails db:structure:{load, dump}` tasks and extend
|
||||
`rails db:schema:{load, dump}` tasks to work with either `:ruby` or `:sql` format,
|
||||
depending on `config.active_record.schema_format` configuration value.
|
||||
|
|
|
@ -38,6 +38,8 @@ module ActiveRecord
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
class_attribute :store_full_class_name, instance_writer: false, default: true
|
||||
|
||||
# Determines whether to store the full constant name including namespace when using STI.
|
||||
# This is true, by default.
|
||||
class_attribute :store_full_sti_class, instance_writer: false, default: true
|
||||
|
@ -164,14 +166,14 @@ module ActiveRecord
|
|||
|
||||
# Returns the value to be stored in the inheritance column for STI.
|
||||
def sti_name
|
||||
store_full_sti_class ? name : name.demodulize
|
||||
store_full_sti_class && store_full_class_name ? name : name.demodulize
|
||||
end
|
||||
|
||||
# Returns the class for the provided +type_name+.
|
||||
#
|
||||
# It is used to find the class correspondent to the value stored in the inheritance column.
|
||||
def sti_class_for(type_name)
|
||||
if store_full_sti_class
|
||||
if store_full_sti_class && store_full_class_name
|
||||
ActiveSupport::Dependencies.constantize(type_name)
|
||||
else
|
||||
compute_type(type_name)
|
||||
|
@ -186,14 +188,18 @@ module ActiveRecord
|
|||
|
||||
# Returns the value to be stored in the polymorphic type column for Polymorphic Associations.
|
||||
def polymorphic_name
|
||||
base_class.name
|
||||
store_full_class_name ? base_class.name : base_class.name.demodulize
|
||||
end
|
||||
|
||||
# Returns the class for the provided +name+.
|
||||
#
|
||||
# It is used to find the class correspondent to the value stored in the polymorphic type column.
|
||||
def polymorphic_class_for(name)
|
||||
name.constantize
|
||||
if store_full_class_name
|
||||
ActiveSupport::Dependencies.constantize(name)
|
||||
else
|
||||
compute_type(name)
|
||||
end
|
||||
end
|
||||
|
||||
def inherited(subclass)
|
||||
|
|
|
@ -8,14 +8,10 @@ module Namespaced
|
|||
class Post < ActiveRecord::Base
|
||||
self.table_name = "posts"
|
||||
has_one :tagging, as: :taggable, class_name: "Tagging"
|
||||
|
||||
def self.polymorphic_name
|
||||
sti_name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PolymorphicFullStiClassNamesSharedTest
|
||||
module FullStiClassNamesSharedTest
|
||||
def setup
|
||||
@old_store_full_sti_class = ActiveRecord::Base.store_full_sti_class
|
||||
ActiveRecord::Base.store_full_sti_class = store_full_sti_class
|
||||
|
@ -31,7 +27,7 @@ module PolymorphicFullStiClassNamesSharedTest
|
|||
def test_class_names
|
||||
ActiveRecord::Base.store_full_sti_class = !store_full_sti_class
|
||||
post = Namespaced::Post.find_by_title("Great stuff")
|
||||
assert_nil post.tagging
|
||||
assert_equal @tagging, post.tagging
|
||||
|
||||
ActiveRecord::Base.store_full_sti_class = store_full_sti_class
|
||||
post = Namespaced::Post.find_by_title("Great stuff")
|
||||
|
@ -41,7 +37,7 @@ module PolymorphicFullStiClassNamesSharedTest
|
|||
def test_class_names_with_includes
|
||||
ActiveRecord::Base.store_full_sti_class = !store_full_sti_class
|
||||
post = Namespaced::Post.includes(:tagging).find_by_title("Great stuff")
|
||||
assert_nil post.tagging
|
||||
assert_equal @tagging, post.tagging
|
||||
|
||||
ActiveRecord::Base.store_full_sti_class = store_full_sti_class
|
||||
post = Namespaced::Post.includes(:tagging).find_by_title("Great stuff")
|
||||
|
@ -51,7 +47,7 @@ module PolymorphicFullStiClassNamesSharedTest
|
|||
def test_class_names_with_eager_load
|
||||
ActiveRecord::Base.store_full_sti_class = !store_full_sti_class
|
||||
post = Namespaced::Post.eager_load(:tagging).find_by_title("Great stuff")
|
||||
assert_nil post.tagging
|
||||
assert_equal @tagging, post.tagging
|
||||
|
||||
ActiveRecord::Base.store_full_sti_class = store_full_sti_class
|
||||
post = Namespaced::Post.eager_load(:tagging).find_by_title("Great stuff")
|
||||
|
@ -62,15 +58,15 @@ module PolymorphicFullStiClassNamesSharedTest
|
|||
post = Namespaced::Post.find_by_title("Great stuff")
|
||||
|
||||
ActiveRecord::Base.store_full_sti_class = !store_full_sti_class
|
||||
assert_nil Tagging.find_by(taggable: post)
|
||||
assert_equal @tagging, Tagging.find_by(taggable: post)
|
||||
|
||||
ActiveRecord::Base.store_full_sti_class = store_full_sti_class
|
||||
assert_equal @tagging, Tagging.find_by(taggable: post)
|
||||
end
|
||||
end
|
||||
|
||||
class PolymorphicFullStiClassNamesTest < ActiveRecord::TestCase
|
||||
include PolymorphicFullStiClassNamesSharedTest
|
||||
class FullStiClassNamesTest < ActiveRecord::TestCase
|
||||
include FullStiClassNamesSharedTest
|
||||
|
||||
private
|
||||
def store_full_sti_class
|
||||
|
@ -78,11 +74,83 @@ class PolymorphicFullStiClassNamesTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
class PolymorphicNonFullStiClassNamesTest < ActiveRecord::TestCase
|
||||
include PolymorphicFullStiClassNamesSharedTest
|
||||
class NonFullStiClassNamesTest < ActiveRecord::TestCase
|
||||
include FullStiClassNamesSharedTest
|
||||
|
||||
private
|
||||
def store_full_sti_class
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
module PolymorphicFullClassNamesSharedTest
|
||||
def setup
|
||||
@old_store_full_class_name = ActiveRecord::Base.store_full_class_name
|
||||
ActiveRecord::Base.store_full_class_name = store_full_class_name
|
||||
|
||||
post = Namespaced::Post.create(title: "Great stuff", body: "This is not", author_id: 1)
|
||||
@tagging = post.create_tagging!
|
||||
end
|
||||
|
||||
def teardown
|
||||
ActiveRecord::Base.store_full_class_name = @old_store_full_class_name
|
||||
end
|
||||
|
||||
def test_class_names
|
||||
ActiveRecord::Base.store_full_class_name = !store_full_class_name
|
||||
post = Namespaced::Post.find_by_title("Great stuff")
|
||||
assert_nil post.tagging
|
||||
|
||||
ActiveRecord::Base.store_full_class_name = store_full_class_name
|
||||
post = Namespaced::Post.find_by_title("Great stuff")
|
||||
assert_equal @tagging, post.tagging
|
||||
end
|
||||
|
||||
def test_class_names_with_includes
|
||||
ActiveRecord::Base.store_full_class_name = !store_full_class_name
|
||||
post = Namespaced::Post.includes(:tagging).find_by_title("Great stuff")
|
||||
assert_nil post.tagging
|
||||
|
||||
ActiveRecord::Base.store_full_class_name = store_full_class_name
|
||||
post = Namespaced::Post.includes(:tagging).find_by_title("Great stuff")
|
||||
assert_equal @tagging, post.tagging
|
||||
end
|
||||
|
||||
def test_class_names_with_eager_load
|
||||
ActiveRecord::Base.store_full_class_name = !store_full_class_name
|
||||
post = Namespaced::Post.eager_load(:tagging).find_by_title("Great stuff")
|
||||
assert_nil post.tagging
|
||||
|
||||
ActiveRecord::Base.store_full_class_name = store_full_class_name
|
||||
post = Namespaced::Post.eager_load(:tagging).find_by_title("Great stuff")
|
||||
assert_equal @tagging, post.tagging
|
||||
end
|
||||
|
||||
def test_class_names_with_find_by
|
||||
post = Namespaced::Post.find_by_title("Great stuff")
|
||||
|
||||
ActiveRecord::Base.store_full_class_name = !store_full_class_name
|
||||
assert_nil Tagging.find_by(taggable: post)
|
||||
|
||||
ActiveRecord::Base.store_full_class_name = store_full_class_name
|
||||
assert_equal @tagging, Tagging.find_by(taggable: post)
|
||||
end
|
||||
end
|
||||
|
||||
class PolymorphicFullClassNamesTest < ActiveRecord::TestCase
|
||||
include PolymorphicFullClassNamesSharedTest
|
||||
|
||||
private
|
||||
def store_full_class_name
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
class PolymorphicNonFullClassNamesTest < ActiveRecord::TestCase
|
||||
include PolymorphicFullClassNamesSharedTest
|
||||
|
||||
private
|
||||
def store_full_class_name
|
||||
false
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue