Building a library system (ActiveRecord question)

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

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.

Mick S. 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?

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 :frowning:

Any help would be greatly appreciated.


Mislav