StoreBaseSTIClass
ActiveRecord has always stored the base class in polymorphic_type
columns when using STI. This can have non-trivial
performance implications in certain cases. This gem adds the store_base_sti_class
configuration option which controls
whether ActiveRecord will store the base class or the actual class. Defaults to true for backwards compatibility.
Description
Given the following class definitions:
class Address
belongs_to :addressable, polymorphic: true
end
class Person
has_many :addresses, as: addressable
end
class Vendor < Person
end
and given the following code:
vendor = Vendor.create(...)
address = vendor.addresses.create(...)
p vendor
p address
will output:
#<Vendor id: 1, type: "Vendor" ...>
#<Address id: 1, addressable_id: 1, addressable_type: 'Person' ...>
Notice that addressable_type
column is Person even though the actual class is Vendor.
Normally, this isn't a problem, however, it can have negative performance characteristics in certain circumstances. The most obvious one is that a join with persons or an extra query is required to find out the actual type of addressable.
This gem adds the ActiveRecord::Base.store_base_sti_class
configuration option. It defaults to true for backwards
compatibility. Setting it to false will alter ActiveRecord's behavior to store the actual class in polymorphic_type
columns when STI is used.
In the example above, if the ActiveRecord::Base.store_base_sti_class
is false
, the output will be,
#<Vendor id: 1, type: "Vendor" ...>
#<Address id: 1, addressable_id: 1, addressable_type: 'Vendor' ...>
Usage
Add the following line to your Gemfile
gem 'store_base_sti_class'
then bundle install. Once you have the gem installed, add the following to one of the initializers (or make a new one) in config/initializers,
ActiveRecord::Base.store_base_sti_class = false
When changing this behavior, you will have write a migration to update all of your existing _type
columns accordingly.
You may also need to change your application if it explicitly relies on the _type
columns.
Notes
This gem incorporates work from:
It currently works with ActiveRecord 4.2.x
through 7.0.x
. If you need support for ActiveRecord 3.x
, use a
pre-1.0
version of the gem, or ActiveRecord < 4.2
use a pre-2.0
version of the gem, or ActiveRecord < 6
use
version < 3
of the gem.
Conflicts
This gem produces known conflicts with these other gems:
When using friendly_id >= 5.2.5
with the
History module enabled, duplicate slugs will be
generated for STI subclasses with the same sluggable identifier (ex: name). This will either cause saves to fail if you
have the proper indexes in place, or will cause slug lookups to be non-deterministic, either of which is undesirable.