Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

8 Commits

Repository files navigation

For whatever reason you need or choose to store blobs in databases. Yet, you do not wish to mix blob columns in the same table as your regular attributes. BinaryColumnTable helps you store ALL blobs in a separate table, managed transparently by an ActiveRecord model. Optionally, it helps you record the content-type of the blob.

This plugin does nothing else.

In your existing model, e.g. Member, declare your binary columns (note: these columns does not exist in your “members” table)

classMember<ActiveRecord::Basehas_binary_columns:photo, :resume, :secret_zipend

For that to work, generate a model called BinaryColumn to contain these blobs.

rails generate model BinaryColumn original_table_type:string original_table_id:integer name:string content_type:string original_filename:string content:binary

You may wish to edit the generated migration file to add a custom index to the bottom of the “self.up” method,

classCreateBinaryColumns<ActiveRecord::Migrationdefself.upcreate_table:binary_columnsdo|t|t.string:original_table_typet.integer:original_table_idt.string:namet.string:content_typet.string:original_filenamet.binary:contentt.timestampsendadd_index:binary_columns, [:original_table_id, :original_table_type, :name], :name=>:by_owner_field_name# add this lineenddefself.downdrop_table:binary_columnsendend

Then apply the schema change,

rakedb:migrate

Finally, modify the generated app/models/binary_column.rb to have a polymorphic “belongs_to”

classBinaryColumn<ActiveRecord::Basebelongs_to:original_table, :polymorphic=>truedeffile_extensionself.original_filename.to_s.split('.').lastendend

The usage is simple and straight-forward as-if the columns are in the original table.

m = Member.newm.name = "Michael"m.photo = IO.read("avatar.png") #=> binary stringm.resume = File.open("resume.doc") #=> IO object (e.g. when uploading via http form)m.save!#=> creates a record in "members" table, saving "Michael" into the "name" column#=> creates a record in "binary_columns" table, saving "avatar.png" binary into "content" column#=> creates a record in "binary_columns" table, saving "resume.doc" binary into "content" columnm = Member.lastm.name#=> "Michael"m.photo_attributes#=> light-weight loading of BinaryColumn object (excludes BLOB)m.photo_attributes.file_extension#=> "png"m.photo#=> binary content of the "avatar.png" filem.resume#=> binary content of the "resume.doc"

Note: If you MUST have your binary column table called something other than “binary_columns”, just edit ActiveRecord::Extensions::BinaryColumnTable::CLASS_NAME

Note: Population of the “content_type” attribute requires “file” command on OS, i.e. most Unix otherwise, remove “content_type” column from table definition to skip content_type extraction

Note: Accessing the content_type attribute is not sugar coated, add a “_binary_column.content_type” suffix. i.e. from our earlier example

m = Member.lastm.photo#=> binary content of the "avatar.png" filem.photo_binary_column.content_type#=> "image/png; charset=binary"

You may wish to generate index for that table as well

./script/generate migration AddIndexesToBinaryColumns

Edit the generated db/migrate/*_add_indexes_to_binary_columns.rb to look like this

classAddIndexesToBinaryColumns<ActiveRecord::Migrationdefself.upadd_index:binary_columns, [:original_table_id, :original_table_type, :name], :name=>'by_original_table_name'enddefself.downremove_index:binary_columns, :name=>'by_original_table_name'endend

Then run migration to commit the schema change

rakedb:migrate

Copyright © 2009 Chew Choon Keat, released under the MIT license

About

For whatever reason you need or choose to store blobs in databases, at *least* have the decency to put them all in a separate table

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors