views:

110

answers:

3

I'm working on my first Rails application (my first Ruby app, for that matter) and I have a best practice question about inheritance. I have to be able to upload physical media and I want to store the physical properties separately in the database so that certain attributes can be queried outside of the application as easily as within in. To manage this, I have an images table and a binaries table. The former stores metadata specific to images, of course, while the latter stores physical file metadata that will apply to a range of file types. Once I have my approach solidified, I'll add a swfs table, a videos table and perhaps others.

At the moment, I have a BinaryObserver class captures the before_create callback of an image and uploads the physical file - the binary. This is working fine, but I'm wondering about other approaches. Specifically, I'm wondering if I couldn't (and shouldn't) establish a basic inheritance model where Binary extends ActiveRecord::Base and Image extends Binary.

As it stands right now, Image belongs_to Binary and Binary has_one Image. Since there's an obvious is-a relationship, though, should I use inheritance? Does rails even support such a thing when interacting with a database? This might be the best way to reduce the amount of work required to support a new file type.

Would appreciate any thoughts or suggestions on this. I'm experimenting with the language and the framework, so I'm trying to learn best practices before I get in too deep.

Thanks.

A: 

From the DB point of view.. You don't need the binaries table... if you save the binary data in the database, it's just a property- like date.. you wouldn't make dates table :)

To say that Image extends Binary because Image "is-a" Binary is not accurate, Image "is-made-of" binary, like Person made of Flesh (you wouldn't say Person extend Flesh)

Anyway, there is a plugin for attachments: attachment_fu, use it :)

amikazmi
We may have to agree to disagree :-). First, I want to share the physical file metadata. Images, SWFs, videoes, etc. all have common properties of file size, extension, etc. I don't want to store those in each individual table (and image metadata is different from SWF data, etc.).Second, I would argue that an image is a specific type of file. Hence, the is-a relationship. Maybe the difference is in how you look at it. In my case, I need to track several types specifically, but lump other types (text, Word Doc and others) into a more generic class.
Rob Wilkerson
Paperclip is also nice for handling attachments.
Andy Gaskell
+1  A: 

Fortunately, there is a very nice single-table inheritance built into rails.

Unfortunately, what you are looking for is multi-table and support is pretty bleak.

Check out some examples on how people have implemented such:

http://zackham.com/2008/8/21/multiple-table-inheritance

http://github.com/sava/class%5Ftable%5Finheritance/tree/master

http://github.com/rwl4/inherits%5Ffrom/tree/master

Or you could just switch to single-table inheritance (though that defeats your previous comment):

class Binary < ActiveRecord::Base
end

class Image < Binary
end

and add this to your Binary model:

type VARCHAR(20) NOT NULL

Examples:

@binaries = Binary.find(:all)

@images = Image.find(:all)
iano
Ah, polymorphic associations. This is pretty nice, actually, and should be all that I need. Nothing I can envision would extend Image; everything would just extend Binary. If I understand the brief additional reading I've done, I'd also have to reverse the polarity of my current relationship. At the moment, my foreign key is on the images table.The more I think about it, this sounds like a perfectly sound way of meeting my needs, but I'm not sure it's significantly better than what I have in place now. I'll have to play with it and determine how much easier it is to add new subtypes.
Rob Wilkerson
My bad, iano. I misunderstood single table inheritance in Rails and you're right. It doesn't meet my needs. I don't want to jam everything up into one table and denormalize my data that way. I guess I'll stick with my observer, but not for the reason I originally thought.
Rob Wilkerson
A: 

If you are writing production code and not just testing out stuff, then I highly recommend attachment_fu or similar way to handle this situation.

matti