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 MyPluginIf 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
endShrine.plugin :my_pluginMethods
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
endNotice 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
endUsers 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
endThe 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.