I'm rebuilding a library/academic system (including public web) using excellent Rails. I'm trying to make the most out of ActiveRecord, but rethinking the database schema spawned some potential issues that may cause problems down the road, so I want thoughts on this from more experienced community. The thing is, all entities in the system have a fixed set of metadata. At first we were copying these columns across entities too keep things simple: (these models made simple for illustration purposes) article = Article.new article.name = 'foo' article.source = 'bar' article.publisher = .... article.ISBN = 12345 newsitem = News.new newsitem.title = 'lorem' newsitem.source = 'bar' mag = Magazine.new mag.name = 'ipsum' mag.publisher = ... mag.ISBN = .... After a while, things looked not-so-great. We wanted to move the common metadata out to a separate table and create associations to it from every model. That would include the magic columns created/updated_on and similar. After that, we need to make it possible for entities to have metadata attributes out from the fixed set if needed, in other words custom metadata (but that is probably a more complex issue that we aren't going to cope with right now). My goal is to make this technical detail (metadata set moved to the separate table) transparent to the existing models. For those who don't understand me (maybe I've put it wrong): I still want to access these attributes directly, eg. @event = Colloquium.find(:first) @event.foo # NOT "event.metadata.foo" ! Also, I want to retain magic functionality of ActiveRecord, like timestamping ('created/updated_on' columns), single table inheritance ('type' column), and so, EVEN if these columns are moved to the metadata table (as with everything else). I've thought about using views or stored procedures (for more complex things) for making entities look like they are a single table, but want to know what others think first. So, if you have a suggestion how to deal with this metadata issue, feel free to drop an opinion. Thanks, -- Mislav
on 2006-05-15 13:31
on 2006-05-15 13:44
I would look at using single table inheritance for your various entity types. Common metadata can then reside in this table since there is no point in storing it elsewhere. Custom metadata can be stored in separate tables. You can always create accessor methods in the STI model for the custom metadata. This is what I am doing for a commercial application.
on 2006-05-15 15:51
Mick Sharpe wrote: > I would look at using single table inheritance for your various entity > types. Common metadata can then reside in this table since there is no > point in storing it elsewhere. Custom metadata can be stored in separate > tables. You can always create accessor methods in the STI model for the > custom metadata. This is what I am doing for a commercial application. Interesting approach, but doesn't quite fit. You see, all entities have different base attributes, same metadata attributes and optional custom metadata attributes. Your solution is good for a case where there is only the latter (metadata), but what about base attributes? They are not similar among entities. If I move those base attributes to separate tables, then I finish with the same thing - having a single entity across multiple tables - that I wanted to avoid. Good tip for creating accessor methods for custom metadata! It has inspired me. Maybe you can talk about your schema and models more? Relying on STI is fine for you?
on 2006-05-15 21:21
I've hit a barrier in ActiveRecord. This may seem a simple issue, but I can't find a workaround for hours now. The thing is, I have many models that share something in common - some assocations and validation rules. (made simple for illustration purposes) module Event < ActiveRecord::Base belongs_to :metadata, :foreign_key => "metadata" validates_presence_of :metadata # extra things here ... end module Book < ActiveRecord::Base belongs_to :metadata, :foreign_key => "metadata" validates_presence_of :metadata # extra things here ... end These are not just 2 models. There are more in my application, and they all share the same association and basic validation - but they are NOT a same (or even a similar) entity. I don't want to use STI (single table inheritance) because of this reason. So, how to stay DRY? How not to repeat this across models? An Observer might solve the validation issue. A mixin might (!) solve the association setup issue, but not without serious hacking. If I subclass a skeleton model, that triggers STI. I've ran out of ideas.... And all this trouble about a common problem: staying DRY with models that share a set of properties :( Any help would be greatly appreciated. -- Mislav