ruby

Why Should Shrine Be Your Go-To Tool for File Uploads in Rails?

Revolutionizing File Uploads in Rails with Shrine's Magic

Why Should Shrine Be Your Go-To Tool for File Uploads in Rails?

Easy File Uploads with Shrine in Rails

When it comes to handling file uploads in Ruby on Rails, there are quite a few options on the table. However, one gem that stands out for its sheer flexibility and modularity is Shrine. Shrine is a robust toolkit designed to deal with file attachments in Ruby apps, and it fits into Rails like a glove. Here’s a goto-guide to get you on your way to setting up Shrine for file uploads in your Rails project.

First off, get Shrine up and running in your Rails app. If you don’t already have a Rails app, create a new one.

rails new photo_app -T

The -T flag will skip the default unit test setup.

Now, add the necessary gems to your Gemfile:

gem 'shrine', '~> 3.3'
gem 'image_processing', '~> 1.12', '>= 1.12.1'

The image_processing gem comes in handy for those times when you need to create different image sizes or perform image type and size validations. Run bundle install to set them up.

Now, Shrine needs some initial configuration. Head over to the config/initializers directory in your app and create a file named shrine.rb. Throw in the following:

require "shrine"
require "shrine/storage/file_system"
require "shrine/storage/memory"

if Rails.env.test?
  Shrine.storages = {
    cache: Shrine::Storage::Memory.new,
    store: Shrine::Storage::Memory.new,
  }
else
  Shrine.storages = {
    cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"),
    store: Shrine::Storage::FileSystem.new("public", prefix: "uploads"),
  }
end

Shrine.plugin :activerecord 
Shrine.plugin :cached_attachment_data 
Shrine.plugin :restore_cached_data 
Shrine.plugin :validation_helpers
Shrine.plugin :validation

This sets up the different storage options for both cached and permanent files. You can always switch to cloud storage like Amazon S3 for production, but file system storage works fine for now.

Next, let’s make your model and create a migration to include a column for storing file data. Generating a model for Photo would look something like this:

rails generate model Photo title:string image_data:text
rails db:migrate

This will create a photos table with an image_data column where Shrine will stash all the info about the uploaded file.

Right, so now we create an uploader class to actually handle the file uploads. In the app/uploaders directory, make an ImageUploader class:

class ImageUploader < Shrine
  # plugins and uploading logic
end

Include this in your model:

class Photo < ActiveRecord::Base
  include ImageUploader::Attachment(:image) # adds an `image` virtual attribute
end

To get your users uploading files, you’ll need form fields in your views. Here’s an example of what that might look like:

<%= form_for @photo do |f| %>
  <%= f.hidden_field :image, value: @photo.cached_image_data, id: nil %>
  <%= f.file_field :image %>
  <%= f.submit %>
<% end %>

Handling the uploads in your controller is straightforward, too. Here’s how you can manage that in the PhotosController:

class PhotosController < ApplicationController
  def create
    @photo = Photo.new(photo_params)
    if @photo.save
      redirect_to @photo, notice: 'Photo was successfully created.'
    else
      render :new
    end
  end

  private

  def photo_params
    params.require(:photo).permit(:title, :image)
  end
end

One of the coolest features of Shrine is handling direct uploads and background processing.

Direct uploads let files go directly from the client to your storage asynchronously, making for a slick user experience. Using the upload_endpoint plugin sets this up nicely:

Shrine.plugin :upload_endpoint

# config/routes.rb
Rails.application.routes.draw do
  mount Shrine.upload_endpoint(:cache) => "/upload" # POST /upload
end

You can then configure a JavaScript library like Uppy to make use of this endpoint.

For background processing, particularly useful for generating thumbnails or handling big files, you can leverage libraries like Sidekiq or Resque. Here’s how you might use Sidekiq for background processing:

class Photo < ActiveRecord::Base
  include ImageUploader::Attachment(:image)

  after_save :process_image_in_background

  private

  def process_image_in_background
    ImageProcessingJob.perform_later(self)
  end
end

class ImageProcessingJob < Sidekiq::Worker
  sidekiq_options retry: false

  def perform(photo)
    photo.image_derivatives!  # Process the image here
  end
end

While on the topic of storage, Shrine also supports cloud storage services like Amazon S3, Google Cloud Storage, and Cloudinary.

For Amazon S3, you need to add some gems and configure the storage options like so:

require "shrine/storage/s3"

s3_options = {
  access_key_id: ENV['S3_KEY'],
  secret_access_key: ENV['S3_SECRET'],
  region: ENV['S3_REGION'],
  bucket: ENV['S3_BUCKET'],
}

Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"),
  store: Shrine::Storage::S3.new(prefix: "store", **s3_options),
}

This sets up your permanent storage to use Amazon S3.

In a nutshell, Shrine is a great gem for dealing with file uploads in Rails apps. Its modular nature, cloud storage support, and nifty features like direct uploads and background processing make it a go-to for managing file attachments. By following these steps, you’ll have Shrine up and running in your Rails app in no time. Whether you’re working with images, videos, or any other files, Shrine gives you the tools you need to handle them smoothly.

Keywords: Shrine, file uploads, Ruby on Rails, file attachments, image processing, cloud storage, Amazon S3, background processing, direct uploads, Uppy



Similar Posts
Blog Image
5 Advanced WebSocket Techniques for Real-Time Rails Applications

Discover 5 advanced WebSocket techniques for Ruby on Rails. Optimize real-time communication, improve performance, and create dynamic web apps. Learn to leverage Action Cable effectively.

Blog Image
Building Bulletproof Observability Pipelines in Ruby on Rails Applications

Master Rails observability with middleware, structured logging, and distributed tracing. Learn custom metrics, error tracking, and sampling strategies to build production-ready monitoring pipelines. Boost performance today.

Blog Image
Is Ahoy the Secret to Effortless User Tracking in Rails?

Charting Your Rails Journey: Ahoy's Seamless User Behavior Tracking for Pro Developers

Blog Image
Is Your Ruby Code Missing Out on the Hidden Power of Fibers?

Unlock Ruby's Full Async Potential Using Fibers for Unmatched Efficiency

Blog Image
TracePoint: The Secret Weapon for Ruby Debugging and Performance Boosting

TracePoint in Ruby is a powerful debugging tool that allows developers to hook into code execution. It can track method calls, line executions, and exceptions in real-time. TracePoint is useful for debugging, performance analysis, and runtime behavior modification. It enables developers to gain deep insights into their code's inner workings, making it an essential tool for advanced Ruby programming.

Blog Image
Rust's Const Generics: Boost Performance and Flexibility in Your Code Now

Const generics in Rust allow parameterizing types with constant values, enabling powerful abstractions. They offer flexibility in creating arrays with compile-time known lengths, type-safe functions for any array size, and compile-time computations. This feature eliminates runtime checks, reduces code duplication, and enhances type safety, making it valuable for creating efficient and expressive APIs.