I have a Base
class which contains STI and named procedures
, looking like this:
class Base < ActiveRecord
self.abstract_class = true
self.table_name = "procedures"
self.inheritance_column = nil
end
We also have multiple superclasses named for isntance ProcedureA
and ProcedureB
, looking like this:
class ProcedureA < Base
end
class ProcedureB < Base
end
A procedure can contain another procedure so i'd like to add this to the base class. But when retrieving the other procedure i'd like to know the actual class name. So this works:
class Base < ActiveRecord
self.abstract_class = true
self.table_name = "procedures"
self.inheritance_column = nil
has_one :parent, class_name: "Base"
end
But when retrieving it form the database it returns is as the Base
class but not the specific class that was assigned.
For instance:
procedure_a = ProcedureA.create!()
procedure_b = ProcedureB.create!()
procedure_a.parent = procedure_b
procedure_a.save!
procedure_a.parent => Is ProcedureB
ProcedureA.first.parent => Is Base class
So at this point i don't know how to get the actual class instead of the base class. I tried playing with polymorphic: true
but doesn't work.
There is a lot of confusion going on here.
To create a self referential assocation you need to use belongs_to
not has_one
.
class User
belongs_to :manager,
class_name: 'User',
optional: true
has_many :subordinates,
class_name: 'User',
foreign_key: :manager_id
end
After all the foreign key is stored on this models table.
But then there is also the fact that your Base is actively sabotaging Single Table Inheritance. It should just read:
class Base < ActiveRecord
self.table_name = "procedures" # all children will be stored in this table
end
self.abstract_class = true
tells ActiveRecord to ignore this class when resolving the table name of its children. That's the opposite of what you want.
self.inheritance_column = nil
disables the type inferance that you need for single table inheritance to work.
The way STI in Rails works you don't actually have to do anything. Any class that inherits from ActiveRecord::Base and is not abstract is a STI parent class by default. All you need to do is add a type
column and subclasses and bob's your uncle.
Adding the self-referential assocation with STI is pretty much the same as above example but with a twist:
class Base < ActiveRecord
belongs_to :parent,
class_name: 'Base',
optional: true
end
class_name: 'Base',
seems kind of odd but its really just telling Rails which table to look for the assocatiated records on. When loading the record the type inferance will override what class is instanciated anyways (or at least it would if you didn't sabotage it).
Note that this is not a case where you want a polymorphic assocation. Thats used when you have a single assocation that points to multiple different tables.