Skip to content

Instantly share code, notes, and snippets.

@jamiehodge
Created August 26, 2013 09:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamiehodge/6339574 to your computer and use it in GitHub Desktop.
Save jamiehodge/6339574 to your computer and use it in GitHub Desktop.
Sequel file plugin
require 'pathname'
module Storage
class Local
attr_reader :path
def initialize(path)
@path = Pathname(path).expand_path
end
def [](id)
Collection.new(id, self)
end
end
class Collection
def initialize(id, store)
@id = id.to_s
@store = store
end
def path
@store.path + @id
end
def [](id)
File.new file_path(id)
end
def []=(id, io, mode = 'w')
File.open(file_path(id), mode) do |f|
f << io.read(4096) until io.eof?
end
end
def delete(id)
File.unlink file_path(id) if File.exist? file_path(id)
end
private
def file_path(id)
FilePath.new(id, self).path
end
end
class FilePath
def initialize(id, collection)
@id = id.to_s
@collection = collection
end
def path
@collection.path + @id
end
end
end
module Sequel
module Plugins
module File
def self.configure(model, **options)
model.instance_variable_set(:@storage, options.fetch(:storage))
model.plugin :dirty
end
module ClassMethods
def storage
@storage[table_name]
end
end
module InstanceMethods
def file
@file ||= self.class.storage[id] unless new?
end
def file=(v)
will_change_column(:file)
@file = v
end
def after_create
super
self.class.storage[id] = file
end
def after_update
super
self.class.storage[id] = file if column_changed?(:file)
end
def after_destroy
super
self.class.storage.delete(id)
end
end
end
end
end
require 'sequel'
DB = Sequel.sqlite
DB.create_table :assets do
primary_key :id
end
class Asset < Sequel::Model
plugin :file, storage: Storage::Local.new('~/Desktop/store')
end
require 'stringio'
a = Asset.create(file: StringIO.new('abc'))
a.update(file: StringIO.new('def'))
a.file.rewind
p a.file.read
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment