未验证 提交 2a29dde5 编写于 作者: R Ryuta Kamizono 提交者: GitHub

Merge pull request #39685 from kamipo/store_full_class_name

Support storing demodulized class name for polymorphic type
* 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 Inheritance
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 @@ def abstract_class?
# 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 @@ def sti_class_for(type_name)
# 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 @@ def teardown
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 @@ def test_class_names
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 @@ def test_class_names_with_includes
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 @@ def test_class_names_with_find_by
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 @@ def store_full_sti_class
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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册