views:

721

answers:

4

How can I tell Activerecord to not load blob columns unless explicitly asked for? There are some pretty large blobs in my legacy DB that must be excluded for 'normal' Objects.

+3  A: 

I believe you can ask AR to load specific columns in your invocation to find:

MyModel.find(id, :select => 'every, attribute, except, the, blobs')

However, this would need to be updated as you add columns, so it's not ideal. I don't think there is any way to specifically exclude one column in rails (nor in a single SQL select).

I guess you could write it like this:

MyModel.find(id, :select => MyModel.column_names - ['column_to_exclude'])

Test these out before you take my word for it though. :)

fd
+2  A: 

fd's answer is mostly right, but ActiveRecord doesn't currently accept an array as a :select argument, so you'll need to join the desired columns into a comma-delimited string, like so:

desired_columns = (MyModel.column_names - ['column_to_exclude']).join(', ')
MyModel.find(id, :select => desired_columns)
Zeke
+1  A: 

A clean approach requiring NO CHANGES to the way you code else where in your app, i.e. no messing with :select options

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.

http://github.com/choonkeat/binary_column_table

Usage is simple

Member.create(:name => "Michael", :photo => IO.read("avatar.png"))
#=> 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

m = Member.last #=> only columns in "members" table is fetched (no blobs)
m.name          #=> "Michael"
m.photo         #=> binary content of the "avatar.png" file
A: 

I just ran into this using rail 3.

Fortunately it wasn't that difficult to solve. I set a default_scope that removed the particular columns I didn't want from the result. For example, in the model I had there was an xml text field that could be quite long that wasn't used in most views.

default_scope select((column_names - ['data']).map { |column_name| "`#{table_name}`.`#{column_name}`"})

You'll see from the solution that I had to map the columns to fully qualified versions so I could continue to use the model through relationships without ambiguities in attributes. Later where you do want to have the field just tack on another .select(:data) to have it included.

Chris Hoffman