Shrine

Shrine

  • Guides
  • Plugins
  • External
  • Discourse
  • GitHub
  • Wiki

›Extending

Introduction

  • Advantages of Shrine
  • Getting Started

Base

  • The Design of Shrine
  • Retrieving Uploads
  • Using Attacher

Storage

  • File System
  • AWS S3
  • Memory

Features

  • Direct Uploads to S3
  • Extracting Metadata
  • File Processing
  • File Validation

Extras

  • Multiple Files
  • Securing Uploads
  • Testing with Shrine

Migrating

  • Managing Derivatives
  • Migrating File Locations
  • Migrating File Storage

Extending

  • Writing a Plugin
  • Writing a Persistence Plugin
  • Writing a Storage

Upgrading

  • Upgrading to Shrine 3.x
  • Upgrading from CarrierWave
  • Upgrading from Paperclip
  • Upgrading from Refile
Edit

Writing a Plugin

Shrine has a lot of plugins built-in, but you can use Shrine's plugin system to create your own.

Definition

Simply put, a plugin is a module:

module MyPlugin
  # ... 
end
 
Shrine.plugin MyPlugin

If you would like to load plugins with a symbol (like you already do with plugins that ship with Shrine), you need to put the plugin in shrine/plugins/my_plugin.rb in your load path and register it:

# shrine/plugins/my_plugin.rb 
class Shrine
  module Plugins
    module MyPlugin
      # ... 
    end
 
    register_plugin(:my_plugin, MyPlugin)
  end
end
Shrine.plugin :my_plugin

Methods

The way to make plugins actually extend Shrine's core classes is by defining special modules inside the plugin. Here's a list of all "special" modules:

InstanceMethods        # gets included into `Shrine` 
ClassMethods           # gets extended into `Shrine` 
AttachmentMethods      # gets included into `Shrine::Attachment` 
AttachmentClassMethods # gets extended into `Shrine::Attachment` 
AttacherMethods        # gets included into `Shrine::Attacher` 
AttacherClassMethods   # gets extended into `Shrine::Attacher` 
FileMethods            # gets included into `Shrine::UploadedFile` 
FileClassMethods       # gets extended into `Shrine::UploadedFile` 

For example, this is how you would make your plugin add some logging to uploading:

module MyPlugin
  module InstanceMethods
    def upload(io, **options)
      time = Time.now
      result = super
      duration = Time.now - time
      puts "Upload duration: #{duration}s"
    end
  end
end

Notice that we can call super to get the original behaviour.

Configuration

You'll likely want to make your plugin configurable. You can do that by overriding the .configure class method and storing received options into Shrine.opts:

module MyPlugin
  def self.configure(uploader, **opts)
    uploader.opts[:my_plugin] ||= {}
    uploader.opts[:my_plugin].merge!(opts)
  end
 
  module InstanceMethods
    def upload(io, **options)
      opts[:my_plugin] #=> { ... } 
      # ... 
    end
  end
end

Users can now pass these configuration options when loading your plugin:

Shrine.plugin :my_plugin, foo: "bar"

Dependencies

If your plugin depends on other plugins, you can load them inside of .load_dependencies:

module MyPlugin
  def self.load_dependencies(uploader, **opts)
    uploader.plugin :derivatives # depends on the derivatives plugin 
  end
end

The dependencies will get loaded before your plugin, allowing you to override methods of your dependencies in your method modules.

The same configuration options passed to .configure are passed to .load_dependencies as well.

← Migrating File StorageWriting a Persistence Plugin →
  • Definition
  • Methods
  • Configuration
  • Dependencies
Shrine
Docs
GuidesPluginsExternalContributing
Community
DiscourseStack Overflow
More
BlogGitHubStar
Follow @shrine_rb
Copyright © 2022 Janko Marohnić