Straight forward file uploads for Ruby Apps
Uploading is... fun, fun, fun, 'til daddy takes the t_bird
away.
Add this line to your application's Gemfile:
gem 't_bird', require: false
And then execute:
$ bundle
I became frustrated by the very coupled design of the leading ruby
upload libraries and wanted something that was more modular (to
allow for flexibility), wasn't glued to a Model
(or any other class),
and fulfilled my most common use case out of the box:
First, configure t_bird
with a few settings:
require 't_bird'
TBird::Configuration.configure |config|
config.aws_key 'amazon access key id'
config.aws_secret 'amazon secret access key'
config.aws_bucket 'name of s3 bucket that already exists'
config.thumbnail_size 100
end
Place this code so that it runs when your app boots.
config.ru
is probably a good spot.config/initializers/t_bird.rb
.Then, assuming you have a multipart form like this:
form enctype="multipart/form-data" method="POST"
input type="file" name="brand[image]"
input type="submit"
Example is using slim for clarity and terseness, but that doesn't mean you have to.
In the action the form posts to, grab the uploaded file and upload it with t_bird
:
# prepended to your filename and enables you
# to create a path to your file on S3
options = { identifier: "images/brands" }
# instantiate your uploader, pass it your file
uploader = TBird::Uploader.new(params[:brand][:image], options)
# return value is the same as uploader.uploads
uploader.upload!
# returns a hash of the URL(s) to your uploads on S3
# store this in the way that makes the most sense for your app
brand.images = uploader.uploads
versions
defined: :thumbnail
and :original
.:thumbnail
will create crop a square image from the upload.
thumbnail_size
in your configuration (see above).:original
will be the raw, unadulterated file that the user submitted.There are three options you can pass into your TBird::Uploader
instance:
:identifer
''
SHA1
digest of the original_filename
t_bird
:token
t_bird
:metadata
tags: brands, images
, or anything else you might think oft_bird
doesn't provide any read access to this metadata, once it's stored on S3. It's up to you to use S3's API to do anything with it.In order to define custom versions, and other advanced customization, create a subclass of TBird::Uploader
:
class FileUploader < TBird::Uploader
version :original do
->(file) { file.original }
end
end
:original
:original
will be created.
versions
defined, your uploader
won't upload anything.Here's a more complex example that defines several custom versions
:
class ComplexUploader < TBird::Uploader
# resizes image to a *width* of 200px, maintains aspect ratio
version :small do
->(img) { img.resize '200' }
end
# resizes image to a *height* of 300px, maintains aspect ratio
version :large do
->(img) { img.resize 'x300' }
end
# resizes image to a *height* of 300px, maintains aspect ratio
version :resized do
->(img) { img.resize '500x300' }
end
# custom thumbnail size, allowing your to ignore
# the value of TBird::Configuration.thumbnail_size
# on an uploader by uploader basis
version :thumbnail do
->(img) { img.thumbnail 200 }
end
# want MOAR power?
# use process, which gets you inside a
# MiniMagick::Image#combine_options block
version :complex do
lambda do |img|
img.process do |magick|
magick.sample "50%"
magick.rotate "-90>"
magick.quality '88'
end
end
end
end
For more information on MiniMagick::Image#combine_options
, refer to the mini_magick docs.
TBird::Processor#process
can be a very sharp stick, so carefully test your processing code with a variety of files in a non-production environment, and as usual, be wary of using values from outside of your class as input for your processing routines.
namer
method in your subclass to switch out the object that's responsible for generating the name used on S3.
new_name
, and take the version
, which will be a symbol, as input.processor
method in your subclass to switch out the processing library.
version
macro will be passed an instance of your processor
,
so be sure that your processor
will respond to any methods the code inside your blocks call on it. upload!
method to remix the whole flow!
t_bird
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)