Class: Shrine::Storage::Linter

Inherits:
Object
  • Object
show all
Defined in:
lib/shrine/storage/linter.rb

Overview

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")})

Defined Under Namespace

Classes: FakeIO

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(storage, action: :error, nonexisting: "nonexisting") ⇒ Linter

Returns a new instance of Linter.



31
32
33
34
35
# File 'lib/shrine/storage/linter.rb', line 31

def initialize(storage, action: :error, nonexisting: "nonexisting")
  @storage     = storage
  @action      = action
  @nonexisting = nonexisting
end

Class Method Details

.call(*args) ⇒ Object



27
28
29
# File 'lib/shrine/storage/linter.rb', line 27

def self.call(*args)
  new(*args).call
end

Instance Method Details

#call(io_factory = default_io_factory) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 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) ⇒ Object



104
105
106
107
# 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) ⇒ Object



94
95
96
97
98
99
100
101
102
# 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:) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
# 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) ⇒ Object



84
85
86
# 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) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 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) ⇒ Object



109
110
111
112
113
114
# 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) ⇒ Object



88
89
90
91
92
# 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