carrierwave-postgresql Build StatusCode Climate

This gem adds to CarrierWave a storage facility which will use the PostgreSQL's oid datatype to reference a large object residing in the databse. It supports up to 2GB files, though it's better suited for smaller ones. Makes life easier for fast prototyping and put all your data in the same place, allows one backup for all your data and file storage in heroku servers.

For more information on PostgreSQL Large Objects you can take a look at the official docs

Note about 0.2.0

This version drops support for ruby 1.9. If you use this version you should stick to 0.1.5. The new adition to 0.2.0 is support to JRuby thanks to @TheKidCoder. Due to the JRuby support the gem pg is no longer a dependency in our gemspec. This means that you need either pg or activerecord-jdbcpostgresql-adapter as a dependency of your project.

Installation

Install the latest release:

gem install carrierwave-postgresql

Require it in your code:

require 'carrierwave/postgresql'

Or, in Rails you can add it to your Gemfile:

gem 'carrierwave-postgresql'

Getting Started

First, this extension assumes 2 important things:

  • You are using CarrierWave with ActiveRecord
  • Your database is PostgreSQL

If you fill the above requirements then you can proceed to the wonderful land of database stored files!

Start off by generating an uploader:

rails generate uploader Avatar

this should give you a file in:

app/uploaders/avatar_uploader.rb

You can configure Carrierwave to use PostgreSQL Large Objects instead of the filesystem. Just change your uploader storage to :postgresql_lo as in:

class AvatarUploader < CarrierWave::Uploader::Base
  storage :postgresql_lo
end

Add an oid column to the (existing) model you want to mount the uploader on:

add_column :users, :avatar, :oid

IMPORTANT: The table contains only an oid, which is a number referencing the large object. The file content is stored in a separate table. This is nice because it does not genrate any problem with SELECT * statements and it gives us a nice file-like interface to the large object.

NOTE: If the model does not exist, and you are going to write a new model to store the oid's, the equivalent create_table migration is

  def change
    create_table :users do |t|
      t.column :avatar, :oid, :null => false

Open your model file and mount the uploader:

class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader
end

Now you can cache files by assigning them to the attribute, they will automatically be stored sinside the database using the Large Object facility when the record is saved.

u = User.new
u.avatar = params[:file]
u.avatar = File.open('somewhere')
u.save!
u.avatar.url # => '/url/to/file.png'
u.avatar.current_path # => 'path/to/file.png'
u.avatar.identifier # => 'file.png'

For more info on CarrierWave take a look at the main Carrierwave repository.

How to stream the files from the web server

Since carrierwave-postgresql doesn't make the files available via HTTP. You can do this using the Rails engine postgresql_lo_streamer.

Alternatively (in case you are not using Rails) you can stream them yourself.

The url that will be available from the field where you mounted the uploader will be the model name followed by the attribute name and with the oid as the resource id.

For instance, in the user's avatar example the url for an image with 1 as it's oid would be /user_avatar/1

You can retrieve the file contents using the following code:

u = User.new
u.avatar = params[:file]
u.avatar = File.open('somewhere')
u.save!
u.avatar.file.read

Contributing to carrierwave-postgresql

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
  • Fork the project.
  • Start a feature/bugfix branch.
  • Commit and push until you are happy with your contribution.
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Acknowledgments

This code is largely based on carrierwave-mongoid I wanted to thank jnicklas for all the open source code and for the great (and extensible) architecture of CarrierWave.

Copyright (c) 2012 Diogo Biazus. See LICENSE.txt for further details.