Changing type of ActiveRecord Class in Rails with Single Table Inheritance
You can just set the type field to 'User' and save the record. The in-memory object will still show as a BaseUser but the next time you reload the in-memory object will be a User
>> b=BaseUser.new
>> b.class # = BaseUser
# Set the Type. In-Memory object is still a BaseUser
>> b.type='User'
>> b.class # = BaseUser
>> b.save
# Retrieve the records through both models (Each has the same class)
>> User.find(1).class # = User
>> BaseUser.find(1).class # User
Rename single table inheritance rails model class name without changing existing data
This is how you could do it:
- Create
ULD < Component
component/file that is a copy ofUld < Component
. I.e. have 2 components, don't removeUld
- In places where you previously fetched
Uld
make it so that now you fetch records where type isUld
orULD
- In places where you created new
Uld
records make it so that it instead creates newULD
records - Deploy these changes without any migrations, this way your servers will be backwards compatible with
Uld
but would also work withULD
- Deploy your migration now
- Finally, remove all the mentions/files related to the old
Uld
and deploy again
Rails 4 update Type when migrating to Single Table Inheritance
If you had more rows in the database User.each would become quite slow as it makes an SQL call for each user.
Generally you could use User.update_all(field: value)
to do this in one SQL call but there is another reason to avoid this: if the User
model is later removed the migration will no longer run.
One way to update all rows at once without referencing the model is to use raw SQL in the migration:
def up
execute "UPDATE users SET type = 'Admin' WHERE type IS NULL"
end
Rails / ActiveRecord - Single Table Inheritance - overriding type field
In modern Rails, you'd use inheritance_column=
(as panckreous noted):
class M < ApplicationRecord
self.inheritance_column = 'whatever'
#...
end
In older versions of Rails (i.e. what was around when this answer was originally written), you'd use [set_inheritance_column
] to change the name:
Sets the name of the inheritance column to use to the given value, or (if the value is
nil
orfalse
) to the value returned by the given block.
The column still has to be a string (or text
) as AR will want to put the class name in there:
Single table inheritance
Active Record allows inheritance by storing the name of the class in a column that is named “type” by default.
Single Table Inheritance - Additional Class Name
After detailed research and diving deep into the Rails STI source code, I found that my scenario will need to override the Rails' default STI. Following is what I needed to achieve the goal:
class Candidate::Site
# To enable renaming of Site to Candidate::Site
# per ENG-9551, we need to:
# 1. disable the 'type' column from using Rails' built-in STI
self.inheritance_column = :_nonexistant_column_to_bypass_sti
# 2. manually set the type column to Candidate::Site when we save,
# so that new and edited records are saved as Candidate::Site
before_save { self.type = 'Candidate::Site' }
# 3. always report the type as a Candidate::Site
def type
'Candidate::Site'
end
# 4. and set a default scope which only reads type columns that are
# 'Candidate::Site' or 'Site' so that STI
# still appears to be the same as always
default_scope { where(type: 'Candidate::Site').or(where(type: 'Site')) }
...
...
...
end
So, now any new record created with Candidate::Site.create
will store type Candidate::Site
while queries will use default scope and consider both the type, Candidate::Site
as well as Site
.
Related Topics
Text_Field_With_Auto_Complete Inside Form_For
Invalid Configuration or No Rubies Listed
Download and Write .Tar.Gz Files Without Corruption
Ruby Attr_Reader Allows One to Modify String Variable If Using <<
Elegant Command-Parsing in an Oop-Based Text Game
Ruby Block and Returning Something from Block
How Does Rake Db::Migrate Actually Work
How to Refer a Local Gem in Ruby
How to Read Post Data in Rack Request
Failing to Bundle Install Tiny_Tds on MAC Os X 10.8 with Homebrew Freetds
How to Create Pretty JSON in Chef (Ruby)
Combine Thumbnails to One Large Image with Rmagick
Turn a Ruby Hash into HTML List
Issues with Has_Many :Through, Cache, Touch and Counter_Cache
Ruby - Platform Independent Way to Determine Ips of All Network Interfaces
How to Restart Rails from Within Rails
Ruby on Rails Looks for CSS in Assets Instead of Public/Stylesheets