Convert Figma logo to code with AI

shrinerb logoshrine

File Attachment toolkit for Ruby applications

3,174
274
3,174
14

Top Related Projects

28,920

The next open source file uploader for web browsers :dog:

Classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks

2,452

Ruby file uploads, take 3

Easy file attachment management for ActiveRecord

mini replacement for RMagick

Quick Overview

Shrine is a flexible file attachment toolkit for Ruby applications. It provides a complete solution for handling file uploads, storage, and processing, with support for various storage services and image processing libraries. Shrine is designed to be modular and customizable, allowing developers to tailor it to their specific needs.

Pros

  • Highly flexible and customizable, with a plugin system for extending functionality
  • Supports multiple storage services (local, S3, Google Cloud Storage, etc.)
  • Provides built-in file validation and processing capabilities
  • Excellent documentation and active community support

Cons

  • Steeper learning curve compared to simpler file upload solutions
  • May be overkill for simple file upload requirements
  • Requires additional setup and configuration for advanced features
  • Performance can be impacted when handling large numbers of uploads simultaneously

Code Examples

  1. Basic file upload and retrieval:
class PhotoUploader < Shrine
  # plugins and uploading logic
end

class Photo < ApplicationRecord
  include PhotoUploader::Attachment(:image)
end

# Upload a file
photo = Photo.new(image: File.open("path/to/image.jpg", "rb"))
photo.save

# Retrieve the file URL
photo.image_url #=> "https://my-bucket.s3.amazonaws.com/path/to/image.jpg"
  1. Image processing with derivatives:
require "image_processing/mini_magick"

class ImageUploader < Shrine
  plugin :derivatives

  Attacher.derivatives do |original|
    magick = ImageProcessing::MiniMagick.source(original)

    {
      small:  magick.resize_to_limit!(300, 300),
      medium: magick.resize_to_limit!(500, 500),
      large:  magick.resize_to_limit!(800, 800),
    }
  end
end

photo.image_derivatives! # generate derivatives
photo.image_url(:small) #=> "https://my-bucket.s3.amazonaws.com/path/to/small.jpg"
  1. Direct uploads to S3:
class PhotoUploader < Shrine
  plugin :presign_endpoint, presign_options: -> (request) {
    { content_disposition: ContentDisposition.inline(request.params["filename"]) }
  }
end

# In your routes.rb
Rails.application.routes.draw do
  mount PhotoUploader.presign_endpoint(:cache) => "/s3/params"
end

Getting Started

  1. Add Shrine to your Gemfile:
gem "shrine", "~> 3.0"
  1. Create an initializer (e.g., config/initializers/shrine.rb):
require "shrine"
require "shrine/storage/file_system"

Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data
Shrine.plugin :restore_cached_data

Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"),
  store: Shrine::Storage::FileSystem.new("public", prefix: "uploads"),
}
  1. Generate an uploader and include it in your model:
class ImageUploader < Shrine
  # plugins and uploading logic
end

class Photo < ApplicationRecord
  include ImageUploader::Attachment(:image)
end

Competitor Comparisons

28,920

The next open source file uploader for web browsers :dog:

Pros of Uppy

  • Cross-platform support: Works with various JavaScript frameworks and can be used in both browser and Node.js environments
  • Rich UI components: Provides pre-built UI elements for a polished file upload experience
  • Extensive plugin ecosystem: Offers a wide range of plugins for additional functionality

Cons of Uppy

  • JavaScript-only: Limited to JavaScript environments, unlike Shrine which is Ruby-based
  • Potentially heavier: May have a larger footprint due to its comprehensive feature set
  • Learning curve: More complex API compared to Shrine's simpler approach

Code Comparison

Uppy (JavaScript):

const uppy = new Uppy()
  .use(Dashboard, { trigger: '#select-files' })
  .use(Tus, { endpoint: '/uploads' })
  .on('complete', (result) => {
    console.log('Upload complete! We've uploaded these files:', result.successful)
  })

Shrine (Ruby):

class ImageUploader < Shrine
  plugin :derivation_endpoint, prefix: "derivations/image"
  
  derivation :thumbnail do |file, width, height|
    file.resize_to_limit!(width.to_i, height.to_i)
  end
end

This comparison highlights the different approaches and languages used by Uppy and Shrine, showcasing Uppy's JavaScript-based configuration and Shrine's Ruby-based setup for file uploads and image processing.

Classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks

Pros of CarrierWave

  • Simpler setup and configuration for basic use cases
  • Built-in image processing capabilities using RMagick or MiniMagick
  • Extensive documentation and large community support

Cons of CarrierWave

  • Less flexible and modular architecture compared to Shrine
  • Performance can be slower, especially for larger file uploads
  • Limited support for direct uploads and background processing

Code Comparison

CarrierWave:

class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  version :thumb do
    process resize_to_fit: [50, 50]
  end
end

Shrine:

class ImageUploader < Shrine
  plugin :derivatives

  Attacher.derivatives do |original|
    magick = ImageProcessing::MiniMagick.source(original)
    { thumb: magick.resize_to_limit!(50, 50) }
  end
end

Both CarrierWave and Shrine are popular file upload solutions for Ruby applications. CarrierWave offers a simpler setup and built-in image processing, making it easier for beginners. However, Shrine provides a more flexible and modular architecture, better performance, and advanced features like direct uploads and background processing. The code comparison shows how both libraries handle image processing, with Shrine offering a more streamlined approach using plugins and derivatives.

2,452

Ruby file uploads, take 3

Pros of Refile

  • Simpler and more lightweight, making it easier to set up and use for basic file upload needs
  • Built-in image processing capabilities without additional dependencies
  • Seamless integration with ActiveRecord for easy attachment handling

Cons of Refile

  • Less flexible and customizable compared to Shrine
  • Limited support for advanced features like background processing and direct uploads
  • No longer actively maintained, which may lead to compatibility issues with newer Ruby versions

Code Comparison

Refile:

class User < ApplicationRecord
  attachment :profile_image
end

<%= form.attachment_field :profile_image %>

Shrine:

class User < ApplicationRecord
  include ImageUploader::Attachment(:profile_image)
end

<%= form.file_field :profile_image, accept: "image/*" %>

Both Shrine and Refile are file attachment libraries for Ruby applications, but they differ in their approach and features. Shrine offers more flexibility and advanced capabilities, making it suitable for complex file handling requirements. It supports various storage backends, plugins, and direct uploads.

Refile, on the other hand, provides a simpler solution with built-in image processing, making it easier to get started with basic file uploads. However, its development has slowed down, which may be a concern for long-term project maintenance.

When choosing between the two, consider your project's specific needs, desired level of customization, and long-term maintenance requirements.

Easy file attachment management for ActiveRecord

Pros of Paperclip

  • Simpler setup and configuration for basic use cases
  • Tighter integration with ActiveRecord models
  • Well-established and widely used in Rails community

Cons of Paperclip

  • Limited flexibility for complex file processing workflows
  • Lack of support for direct uploads and background processing
  • No longer actively maintained (deprecated in favor of Active Storage)

Code Comparison

Paperclip:

class User < ActiveRecord::Base
  has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }
  validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\z/
end

Shrine:

class User < ActiveRecord::Base
  include ImageUploader::Attachment(:avatar)
end

class ImageUploader < Shrine
  plugin :derivatives
  plugin :validation_helpers

  Attacher.derivatives do |original|
    magick = ImageProcessing::MiniMagick.source(original)
    { medium: magick.resize_to_limit!(300, 300),
      thumb: magick.resize_to_limit!(100, 100) }
  end

  Attacher.validate do
    validate_mime_type %w[image/jpeg image/png image/webp]
  end
end

Shrine offers more flexibility and advanced features, while Paperclip provides a simpler setup for basic use cases. Shrine's code is more verbose but allows for greater customization and separation of concerns.

mini replacement for RMagick

Pros of MiniMagick

  • Lightweight and focused specifically on image processing
  • Simple API for common image manipulation tasks
  • Extensive support for various image formats

Cons of MiniMagick

  • Limited to image processing, not a full-featured file upload solution
  • Requires ImageMagick to be installed on the system
  • Less flexibility for handling non-image file types

Code Comparison

MiniMagick:

image = MiniMagick::Image.open("input.jpg")
image.resize "300x300"
image.format "png"
image.write "output.png"

Shrine:

uploaded_file = Shrine.upload(File.open("input.jpg"), :store)
processed = uploaded_file.derivation(:resize).call("300x300")
processed.download.path # => path to resized image

Summary

MiniMagick is a lightweight gem focused on image processing, offering a simple API for common tasks. It requires ImageMagick to be installed and is limited to image manipulation. Shrine, on the other hand, is a more comprehensive file attachment toolkit that handles various file types and provides a flexible plugin system. While MiniMagick excels in straightforward image processing, Shrine offers a more robust solution for file uploads and storage in Ruby applications.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Shrine

Shrine logo: a red paperclip

Shrine is a toolkit for handling file attachments in Ruby applications. Some highlights:

If you're curious how it compares to other file attachment libraries, see the Advantages of Shrine. Otherwise, follow along with the Getting Started guide.

Links

ResourceURL
Website & Documentationshrinerb.com
Demo codeRoda / Rails
Wikigithub.com/shrinerb/shrine/wiki
Discussion forumgithub.com/shrinerb/shrine/discussions
Alternate Discussion forumdiscourse.shrinerb.com

Setup

Run:

bundle add shrine

Then add config/initializers/shrine.rb which sets up the storage and loads ORM integration:

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

Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary
  store: Shrine::Storage::FileSystem.new("public", prefix: "uploads"),       # permanent
}

Shrine.plugin :activerecord           # loads Active Record integration
Shrine.plugin :cached_attachment_data # enables retaining cached file across form redisplays
Shrine.plugin :restore_cached_data    # extracts metadata for assigned cached files

Next, add the <name>_data column to the table you want to attach files to. For an "image" attachment on a photos table this would be an image_data column:

$ rails generate migration add_image_data_to_photos image_data:text # or :jsonb

If using jsonb consider adding a gin index for fast key-value pair searchability within image_data.

Now create an uploader class (which you can put in app/uploaders) and register the attachment on your model:

class ImageUploader < Shrine
  # plugins and uploading logic
end
class Photo < ActiveRecord::Base
  include ImageUploader::Attachment(:image) # adds an `image` virtual attribute
end

In our views let's now add form fields for our attachment attribute that will allow users to upload files:

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

When the form is submitted, in your controller you can assign the file from request params to the attachment attribute on the model:

class PhotosController < ApplicationController
  def create
    Photo.create(photo_params) # attaches the uploaded file
    # ...
  end

  private

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

Once a file is uploaded and attached to the record, you can retrieve the file URL and display it on the page:

<%= image_tag @photo.image_url %>

See the Getting Started guide for further documentation.

Inspiration

Shrine was heavily inspired by Refile and Roda. From Refile it borrows the idea of "backends" (here named "storages"), attachment interface, and direct uploads. From Roda it borrows the implementation of an extensible plugin system.

Similar libraries

  • Paperclip
  • CarrierWave
  • Dragonfly
  • Refile
  • Active Storage

Contributing

Please refer to the contributing page.

Code of Conduct

Everyone interacting in the Shrine project’s codebases, issue trackers, and mailing lists is expected to follow the Shrine code of conduct.

License

The gem is available as open source under the terms of the MIT License.