Ashley,
It would seem to me that you could accomplish a much of what you’re
talking about with something that looks like this:
class Worker < ActiveRecord::Base
has_one :manager
has_one :first_aider
def manager?
!manager.nil?
end
def first_aider?
!first_aider.nil?
end
end
class Manager < ActiveRecord::Base
belongs_to :worker
end
class FirstAider < ActiveRecord::Base
belongs_to :worker
end
john = Worker.find_by_name(“john”)
John the manager will shout now if he is one.
john.manager.shout if john.manager?
John the first aider will heal if he is one.
john.first_aider.heal if john.first_aider?
In fact, using a method similar to what I did in my plugin, you can
create a proxy accessor if you really want to call john.shout and not
john.manager.shout.
One of the design goals of my plugin is functionality through a simple
means. If you notice, it’s really nothing more than an attribute proxy
method generator that iterates over the parent’s attributes. You could
theoretically even add something like this:
class Worker < ActiveRecord::Base
has_one :manager
alias_associated_attr(‘manager’, ‘shout’)
def manager?
!manager.nil?
end
end
steve = Worker.find_by_name(“steve”)
steve.shout if steve.manager?
I’m not sure if I quite answered your question here, but I guess my
point is that I don’t think you really need inheritance at all for the
scenario you pointed out above. It even can yield a bit cleaner code
sometimes when you can encapsulate the role-specific methods/attributes,
in this case for manager, in their own class.
Regards,
Ray
Ashley M. wrote:
On Tuesday 04 July 2006 04:40, Josh S. wrote:
How interesting! Â I’m impressed you were able to get this to work in as
little code as you did. Pretty good for a science project. However, I
think your approach has some serious limitations and you may be right
about it being fundamentally flawed.
I haven’t seen the code yet but Class TI is a feature I’d really like in
Rails. There’s a chance I’ll get to do some work on it at work so I was
hoping to see someone else have a go for inspiration.
One issue I’ve wondered about is when you have non-mutually exclusive
subclasses. Eg
Worker
(def work; ...; end)
/ \
Manager First Aider
(def shout; …; end) (def heal; …; end)
Should entries be allowed in both the managers and first_aiders
tables? If
so I guess you have to use mixins to allow extra code funcionality from
both
subcategories.
By the way, I think in a typical ClassTI design, the PKs of the segments
are synced across tables, so you don’t need to keep a FK for the parent
record in the child record.
I assume by this you mean that you don’t have auto-incremented surrogate
keys
in the subclass tables, and the primary key is manually set to the same
value
as the corresponding superclass entry? I think that’s what I’ve seen
before.
My big gripe with ClassTI is that you have to do a select or join for
each level of inheritance to get a single object from the database. That
doesn’t make it a non-starter, but it’s a pretty big performance hurdle
to get over.
If you don’t like the complexity of the joins, don’t forget you can
define
views to represent the “whole” subclass.
I think the performance hit of joins is often over-estimated. Fetching
everything in the combined join will take longer than a single table,
but
most queries only involve a subset of data. (Also some database servers
can
cache the result of joins.) Generally it’s probably better to design
for
simplicity first, and only change your design for performance if really
necessary.
I imagine the worst thing you could do with a Class TI design is to
iterate
over the entities, fetching each one in turn. That would make the app
query
every subclass table to find what class it belongs to.
Have you looked into the Concrete Table Inheritance pattern? I think
that would be more useful for Rails type apps, though it could be a
polymorphic nightmare doing a find(:all) on the parent class!
I haven’t given it THAT much thought, but I’m not too fond of Concrete
TI.
Mainly because:
- it complicates table design
(changes must be made to multiple tables)
- it makes it harder to turn one entity type into another
(in Class TI, just insert or delete a sub-entity record)
- it completely rules out multi-class entities
(unless you want really nasty redundancy in the data)
Let me know your thoughts everyone hopefully I’ll be able to join in the
Class
TI effort some time.
Ashley