class Shrine::Storage::Linter
Checks if the storage conforms to Shrine’s specification.
Shrine::Storage::Linter.new(storage).call
If the check fails, by default it raises a ‘Shrine::LintError`, but you can also specify `action: :warn`:
Shrine::Storage::Linter.new(storage, action: :warn).call
You can also specify an IO factory which the storage will use:
Shrine::Storage::Linter.new(storage).call(->{File.open("test/fixtures/image.jpg")})
Attributes
storage[R]
Public Class Methods
call(*args)
click to toggle source
# File lib/shrine/storage/linter.rb, line 27 def self.call(*args) new(*args).call end
new(storage, action: :error, nonexisting: "nonexisting")
click to toggle source
# File lib/shrine/storage/linter.rb, line 31 def initialize(storage, action: :error, nonexisting: "nonexisting") @storage = storage @action = action @nonexisting = nonexisting end
Public Instance Methods
call(io_factory = default_io_factory)
click to toggle source
# File lib/shrine/storage/linter.rb, line 37 def call(io_factory = default_io_factory) storage.upload(io_factory.call, id = "foo", shrine_metadata: { "foo" => "bar" }) lint_open(id) lint_exists(id) lint_url(id) lint_delete(id) if storage.respond_to?(:delete_prefixed) storage.upload(io_factory.call, id1 = "a/a/a") storage.upload(io_factory.call, id2 = "a/a/b") storage.upload(io_factory.call, id3 = "a/aaa/a") lint_delete_prefixed(prefix: "a/a/", expect_deleted: [id1, id2], expect_remaining: [id3]) storage.delete(id3) end if storage.respond_to?(:clear!) storage.upload(io_factory.call, id = "quux".dup) lint_clear(id) end if storage.respond_to?(:presign) lint_presign(id) end true end
lint_clear(id)
click to toggle source
# File lib/shrine/storage/linter.rb, line 104 def lint_clear(id) storage.clear! error :clear!, "file still #exists? after clearing" if storage.exists?(id) end
lint_delete(id)
click to toggle source
# File lib/shrine/storage/linter.rb, line 94 def lint_delete(id) storage.delete(id) error :delete, "file still #exists? after deleting" if storage.exists?(id) begin storage.delete(id) rescue => exception error :delete, "shouldn't fail if the file doesn't exist, but raised #{exception.class}" end end
lint_delete_prefixed(prefix:, expect_deleted:, expect_remaining:)
click to toggle source
# File lib/shrine/storage/linter.rb, line 116 def lint_delete_prefixed(prefix:, expect_deleted:, expect_remaining:) storage.delete_prefixed(prefix) expect_deleted.each do |key| next unless storage.exists?(key) error :delete_prefixed, "#{key} still #exists? after #clear_prefix('a/a/')" end expect_remaining.each do |key| next if storage.exists?(key) error :delete_prefixed, "#{key} doesn't #exists? but should after #clear_prefix('a/a/')" end end
lint_exists(id)
click to toggle source
# File lib/shrine/storage/linter.rb, line 84 def lint_exists(id) error :exists?, "returns false for a file that was uploaded" if !storage.exists?(id) end
lint_open(id)
click to toggle source
# File lib/shrine/storage/linter.rb, line 69 def lint_open(id) opened = storage.open(id) error :open, "doesn't return a valid IO object" if !io?(opened) error :open, "returns an empty IO object" if opened.read.empty? opened.close begin storage.open(@nonexisting) error :open, "should raise an exception on nonexisting file" rescue Shrine::FileNotFound rescue => exception error :open, "should raise Shrine::FileNotFound on nonexisting file" end end
lint_presign(id)
click to toggle source
# File lib/shrine/storage/linter.rb, line 109 def lint_presign(id) data = storage.presign(id) error :presign, "result should be a Hash" unless data.respond_to?(:to_h) error :presign, "result should include :method key" unless data.to_h.key?(:method) error :presign, "result should include :url key" unless data.to_h.key?(:url) end
lint_url(id)
click to toggle source
# File lib/shrine/storage/linter.rb, line 88 def lint_url(id) # just assert #url exists, it isn't required to return anything url = storage.url(id) error :url, "should return either nil or a string" if !(url.nil? || url.is_a?(String)) end
Private Instance Methods
default_io_factory()
click to toggle source
# File lib/shrine/storage/linter.rb, line 159 def default_io_factory -> { FakeIO.new("file") } end
error(method_name, message)
click to toggle source
# File lib/shrine/storage/linter.rb, line 147 def error(method_name, message) if @action == :error raise LintError, full_message(method_name, message) else warn full_message(method_name, message) end end
full_message(method_name, message)
click to toggle source
# File lib/shrine/storage/linter.rb, line 155 def full_message(method_name, message) "#{@storage.class}##{method_name} - #{message}" end
io?(object)
click to toggle source
# File lib/shrine/storage/linter.rb, line 140 def io?(object) uploader.send(:_enforce_io, object) true rescue Shrine::InvalidFile false end
uploader()
click to toggle source
# File lib/shrine/storage/linter.rb, line 134 def uploader shrine = Class.new(Shrine) shrine.storages[:storage] = storage shrine.new(:storage) end