Polymorphic STI setup
I have an app that is making extensive use of an Entity model.
In past version of this app (working on a rewrite, current version is in PHP) this was modeled with a single table inheritance with basically two identical models.
One model was Entity, which is associated with projects and has multiple types (client, requestor, provider, etc).
Another model was Addressbook, which is mostly identical to entity, save for a different table and model name and a few addressbook only fields (such as disabled).
We currently have a column on entity for addressbook_id to map project entities back to the addressbook, or failing that we try to do a mapping based on email address. Data between the addressbook and entities is NOT kept in sync, that is, one must be able to update the entity in a project without any impact on the data in the addressbook (though we provide an option to update the addressbook as well).
Regardless, there are 4 or 5 types of entities. They have mostly the same fields (first name, last name, email, address, phone, etc). Each entity type may have 1 - 3 fields that are unique to it but that's about it. In addition to this in the current app entities may be people or companies (same STI table, which also has a company_name field).
For what the app needs to do, easily being able to find all entities for a project (regardless of type or whether they are people or companies) is a win. Also being able to easily join entities in a query, and searching them per project, win.
Because of this, I'm inclined to stick to the STI model and 开发者_运维百科keep it simple, and since each type shares 90% of the same fields it's not a lot of waste. However, I'm curious if there's any good suggestion to deal with the whole issue of having essentially the same models for both Addressbook and Entity, but keeping the data in separate tables. I've contemplated how a polymorphic association might help but I think that would make the table structure more complicated and might hurt performance of queries (fairly large data set, where these entities may be included in list views).
But really I don't want to end up with this...
class Entity
class Customer < Entity
class Addressbook
class AddressbookCustomer < Addressbook
etc...
Not terribly DRY, and there is common functionality between the entity types and subtypes (for example, both Entity and Addressbook would have a name method that returns a full name, and both Customer and AddressbookCustomer might have a last_order method).
The data currently is just stored in two tables, addressbook and entities, which have a type column. However, this is a clean break so legacy table structures don't have to be kept, however from the perspective of keeping it simple I do like that structure.
Any suggestions?
I've never done this but if you want to share code among all of your "entities" why not create one base class that everything else inherits from:
class OneClassToRuleThemAll < ActiveRecord::Base
def name
...
class Entity < OneClassToRuleThemAll
set_table_name "entities"
class AddressBook < OneClassToRuleThemAll
set_table_name "address_books"
That gives you one base class for shared methods but separate tables for each branch in your inheritance tree.
If you don't like that solution, because you still want to share methods that don't belong in the OneClassToRuleThemAll
but are shared between cousin classes further down the tree, then why not write a little module to hold those functions, like last order
, and then just import that module into each of the cousin classes that need those functions?
P.S. I don't even know if the first example would work, but I think it should.
精彩评论