multiple_table_inheritance
multiple_table_inheritance copied to clipboard
How to reference a child attribute from an inherited method in the parent?
Is it possible to do something like:
class Employee < ActiveRecord::Base
acts_as_superclass
belongs_to :team
def give_date
self.training_completed_at
end
end
class Programmer < ActiveRecord::Base
inherits_from :employee, :methods => true
end
@programmer = Programmer.first
@programmer.give_date
This is a silly example but is something like this possible?
Yeah, that's the intention of the :methods
option on the inherits_from
call. I will say though that I created this gem for Rails 3.x, and the internals have changed quite a bit since then that I can't promise this gem will still work under 4.x. (In fact, I'm pretty certain that it won't.)
With that said, I'm definitely open to updates on the gem to make it work, but it's not something I have time for or actually need right now to be able to focus any kind of time on it. If you wish to pursue, I'm happy to accept pull requests to get it fixed up! :)
I'm running rails 3.2.20 so it's ok at the moment but I would like to upgrade my app to rails 4 at some point.
Actually what I'm trying to do is: @employee = Employee.first # assume first employee is a Programmer @employee.give_date
I'm getting undefined method training_completed_at for #<Employee
Where is training_completed_at
defined?
I'm using your example so:
create_table :programmers, :inherits => :employee do |t|
t.datetime :training_completed_at
end
Okay, I can explain what is going on. The give_date
method is properly being delegated to the Employee
object, but then the Employee
object tries to call training_completed_at
on itself. This doesn't work because you defined it on Programmer
, not Employee
. The delegation is intended for methods that exist on the parent record. Since training_completed_at
exists on the programmer itself and not other inheriting classes, why not just call that method directly?
So I have 7 child classes and 5 of them have :name attributes. I've a method first_name that returns the first word from the name attribute. I want to go through each of the parent's objects (filtered to just the 5 that have names) and print their first_name.
This sounds like something that can't (currently) be done in the approach you're taking, in that there's no existing method to access the child from the parent. Either this method could be added (shouldn't be too hard), or else you'll need to try a slightly different approach. Adding this method would probably look as easy as something like:
module MultipleTableInheritance::Parent::Base::InstanceMethods
def child
send(subtype_column.to_sym).constantize.find_by_id(id)
end
end
You could then call child.whatever
from the superclass.
If you're trying to access first_name
, and that only exists on 5 of the 7 models, I'd consider defining them on the remaining 2 models, e.g.:
class Employee < ActiveRecord::Base
acts_as_superclass
end
class Programmer < ActiveRecord::Base
inherits_from :employee
validates :name, presence: true
def first_name
name.strip.split(/\s+/).first
end
end
class Manager < ActiveRecord::Base
inherits_from :employee
validates :first_name, presence: true
end