carrierwave-postgresql
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
Copyright (c) 2012 Diogo Biazus. See LICENSE.txt for further details.