active_storage_validations 0.9.5 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: efa69aeeea1b171286c6ca464e38146dedef79d22853c35ec6ea0ce0ca089812
4
- data.tar.gz: e186561942afb6b295839565323d0bbed704de9e413b79ecc1fb194ada643ca5
3
+ metadata.gz: c9b366848f85ac520038a9efe0bee0514338f4d28b8f292ef87ad06d1ee0da28
4
+ data.tar.gz: 651195be6d5d23bf20c4600656e799005e3e1fc118ac21cc5fe023b24f43ae73
5
5
  SHA512:
6
- metadata.gz: c31ec657e1121427f19d7617d5efbeab639c6ebd87c0333c36510064e7b4d8125ffd8e4f5afa86121e626dd608d2ad1b859a3515c8bc7683e0793291a30c7fd2
7
- data.tar.gz: 3141abc08b6b33d90f9874a74e93f6aaddb0ebbd52bdd36ee292a1e0ff7d37cf65a8ced082d316f48cc8e0132320c4f83304d9823971906526096264129c0145
6
+ metadata.gz: f6231454bce1c4b09bf4dba3a83238f09b3fa0593c0c04146342ac6dd035048f890edcb594d24747f9d5e55d5ef86a35eba7fa93b109f101906b0f5b4f373c06
7
+ data.tar.gz: 6a5a9a0abd3f7abbddd92d8f1e5601859bbcc06e17f049046e5c9e2744760aa4fd7fa77462c22fb8d076cc4aef801e9b814a6b8663edb08e9c32a497ec041908
data/README.md CHANGED
@@ -26,16 +26,17 @@ For example you have a model like this and you want to add validation.
26
26
  class User < ApplicationRecord
27
27
  has_one_attached :avatar
28
28
  has_many_attached :photos
29
+ has_one_attached :image
29
30
 
30
31
  validates :name, presence: true
31
32
 
32
33
  validates :avatar, attached: true, content_type: 'image/png',
33
34
  dimension: { width: 200, height: 200 }
34
- validates :photos, attached: true, content_type: ['image/png', 'image/jpg', 'image/jpeg'],
35
+ validates :photos, attached: true, content_type: ['image/png', 'image/jpeg'],
35
36
  dimension: { width: { min: 800, max: 2400 },
36
37
  height: { min: 600, max: 1800 }, message: 'is not given between dimension' }
37
38
  validates :image, attached: true,
38
- content_type: ['image/png', 'image/jpg'],
39
+ content_type: ['image/png', 'image/jpeg'],
39
40
  aspect_ratio: :landscape
40
41
  end
41
42
  ```
@@ -44,13 +45,15 @@ or
44
45
 
45
46
  ```ruby
46
47
  class Project < ApplicationRecord
48
+ has_one_attached :logo
47
49
  has_one_attached :preview
48
50
  has_one_attached :attachment
49
51
  has_many_attached :documents
50
52
 
51
53
  validates :title, presence: true
52
54
 
53
- validates :preview, attached: true, size: { less_than: 100.megabytes , message: 'is not given between size' }
55
+ validates :logo, attached: true, size: { less_than: 100.megabytes , message: 'is too large' }
56
+ validates :preview, attached: true, size: { between: 1.kilobyte..100.megabytes , message: 'is not given between size' }
54
57
  validates :attachment, attached: true, content_type: { in: 'application/pdf', message: 'is not a PDF' }
55
58
  validates :documents, limit: { min: 1, max: 3 }
56
59
  end
@@ -58,14 +61,15 @@ end
58
61
 
59
62
  ### More examples
60
63
 
61
- - Content type validation using symbols. In order to infer the correct mime type from the symbol, the types must be registered with `MimeMagic::EXTENSIONS`.
64
+ - Content type validation using symbols. In order to infer the correct mime type from the symbol, the types must be registered with `Marcel::EXTENSIONS` (`MimeMagic::EXTENSIONS` for Rails <= 6.1.3).
62
65
 
63
66
  ```ruby
64
67
  class User < ApplicationRecord
65
68
  has_one_attached :avatar
66
69
  has_many_attached :photos
67
70
 
68
- validates :avatar, attached: true, content_type: :png # MimeMagic.by_extension(:png).to_s => 'image/png'
71
+ validates :avatar, attached: true, content_type: :png # Marcel::Magic.by_extension(:png).to_s => 'image/png'
72
+ # Rails <= 6.1.3; MimeMagic.by_extension(:png).to_s => 'image/png'
69
73
  # or
70
74
  validates :photos, attached: true, content_type: [:png, :jpg, :jpeg]
71
75
  # or
@@ -176,6 +180,8 @@ gem 'active_storage_validations'
176
180
 
177
181
  # Optional, to use :dimension validator or :aspect_ratio validator
178
182
  gem 'mini_magick', '>= 4.9.5'
183
+ # Or
184
+ gem 'ruby-vips', '>= 2.1.0'
179
185
  ```
180
186
 
181
187
  And then execute:
@@ -292,6 +298,22 @@ To run tests in root folder of gem:
292
298
  * `BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle exec rake test` to run for Rails 5.2
293
299
  * `BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle exec rake test` to run for Rails 6.0
294
300
  * `BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle exec rake test` to run for Rails 6.1
301
+ * `BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle exec rake test` to run for Rails main branch
302
+
303
+ Snippet to run in console:
304
+
305
+ ```
306
+ BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle
307
+ BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle
308
+ BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle
309
+ BUNDLE_GEMFILE=gemfiles/rails_7_0.gemfile bundle
310
+ BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle
311
+ BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle exec rake test
312
+ BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle exec rake test
313
+ BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle exec rake test
314
+ BUNDLE_GEMFILE=gemfiles/rails_7_0.gemfile bundle exec rake test
315
+ BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle exec rake test
316
+ ```
295
317
 
296
318
  ## Known issues
297
319
 
@@ -344,7 +366,18 @@ You are welcome to contribute.
344
366
  - https://github.com/jayshepherd
345
367
  - https://github.com/ohbarye
346
368
  - https://github.com/randsina
347
- - https://github.com/...
369
+ - https://github.com/vietqhoang
370
+ - https://github.com/kemenaran
371
+ - https://github.com/jrmhaig
372
+ - https://github.com/tagliala
373
+ - https://github.com/evedovelli
374
+ - https://github.com/JuanVqz
375
+ - https://github.com/luiseugenio
376
+ - https://github.com/equivalent
377
+ - https://github.com/NARKOZ
378
+ - https://github.com/stephensolis
379
+ - https://github.com/kwent
380
+ = https://github.com/Animesh-Ghosh
348
381
 
349
382
  ## License
350
383
 
@@ -2,21 +2,21 @@ pt-BR:
2
2
  errors:
3
3
  messages:
4
4
  content_type_invalid: "tem um tipo de arquivo inválido"
5
- file_size_out_of_range: "tamanho %{file_size} está fora da faixa de tamanho válida"
6
- limit_out_of_range: "número total está fora do limite"
5
+ file_size_out_of_range: "tem tamanho %{file_size} e está fora da faixa de tamanho válida"
6
+ limit_out_of_range: "o número total está fora do limite"
7
7
  image_metadata_missing: "não é uma imagem válida"
8
- dimension_min_inclusion: "deve ser maior ou igual a %{width} x %{height} pixel"
9
- dimension_max_inclusion: "deve ser menor ou igual a %{width} x %{height} pixel"
10
- dimension_width_inclusion: "largura não está entre %{min} e %{max} pixel"
11
- dimension_height_inclusion: "altura não está entre %{min} e %{max} pixel"
12
- dimension_width_greater_than_or_equal_to: "largura deve ser maior ou igual a %{length} pixel"
13
- dimension_height_greater_than_or_equal_to: "altura deve ser maior ou igual a %{length} pixel"
14
- dimension_width_less_than_or_equal_to: "largura deve ser menor ou igual a %{length} pixel"
15
- dimension_height_less_than_or_equal_to: "altura deve ser menor ou igual a %{length} pixel"
16
- dimension_width_equal_to: "largura deve ser igual a %{length} pixel"
17
- dimension_height_equal_to: "altura deve ser igual a %{length} pixel"
8
+ dimension_min_inclusion: "deve ser maior ou igual a %{width} x %{height} pixels"
9
+ dimension_max_inclusion: "deve ser menor ou igual a %{width} x %{height} pixels"
10
+ dimension_width_inclusion: "deve ter largura entre %{min} e %{max} pixels"
11
+ dimension_height_inclusion: "deve ter altura entre %{min} e %{max} pixels"
12
+ dimension_width_greater_than_or_equal_to: "deve ter largura maior ou igual a %{length} pixels"
13
+ dimension_height_greater_than_or_equal_to: "deve ter altura maior ou igual a %{length} pixels"
14
+ dimension_width_less_than_or_equal_to: "deve ter largura menor ou igual a %{length} pixels"
15
+ dimension_height_less_than_or_equal_to: "deve ter altura menor ou igual a %{length} pixels"
16
+ dimension_width_equal_to: "deve ter largura igual a %{length} pixels"
17
+ dimension_height_equal_to: "deve ter altura igual a %{length} pixels"
18
18
  aspect_ratio_not_square: "não é uma imagem quadrada"
19
- aspect_ratio_not_portrait: "não contém uma imagem no formato retrato"
20
- aspect_ratio_not_landscape: "não contém uma imagem no formato paisagem"
19
+ aspect_ratio_not_portrait: "não está no formato retrato"
20
+ aspect_ratio_not_landscape: "não está no formato paisagem"
21
21
  aspect_ratio_is_not: "não contém uma proporção de %{aspect_ratio}"
22
22
  aspect_ratio_unknown: "não tem uma proporção definida"
@@ -8,7 +8,6 @@ module ActiveStorageValidations
8
8
  PRECISION = 3
9
9
 
10
10
  def initialize(options)
11
- require 'mini_magick' unless defined?(MiniMagick)
12
11
  super(options)
13
12
  end
14
13
 
@@ -18,7 +17,7 @@ module ActiveStorageValidations
18
17
  raise ArgumentError, 'You must pass "aspect_ratio: :OPTION" option to the validator'
19
18
  end
20
19
 
21
- if Rails::VERSION::MAJOR >= 6
20
+ if Rails.gem_version >= Gem::Version.new('6.0.0')
22
21
  def validate_each(record, attribute, _value)
23
22
  return true unless record.send(attribute).attached?
24
23
 
@@ -37,14 +36,14 @@ module ActiveStorageValidations
37
36
  # Rails 5
38
37
  def validate_each(record, attribute, _value)
39
38
  return true unless record.send(attribute).attached?
40
-
39
+
41
40
  files = Array.wrap(record.send(attribute))
42
-
41
+
43
42
  files.each do |file|
44
43
  # Analyze file first if not analyzed to get all required metadata.
45
44
  file.analyze; file.reload unless file.analyzed?
46
45
  metadata = file.metadata
47
-
46
+
48
47
  next if is_valid?(record, attribute, metadata)
49
48
  break
50
49
  end
@@ -7,8 +7,6 @@ module ActiveStorageValidations
7
7
  AVAILABLE_CHECKS = %i[width height min max].freeze
8
8
 
9
9
  def initialize(options)
10
- require 'mini_magick' unless defined?(MiniMagick)
11
-
12
10
  [:width, :height].each do |length|
13
11
  if options[length] and options[length].is_a?(Hash)
14
12
  if range = options[length][:in]
@@ -34,7 +32,7 @@ module ActiveStorageValidations
34
32
  end
35
33
 
36
34
 
37
- if Rails::VERSION::MAJOR >= 6
35
+ if Rails.gem_version >= Gem::Version.new('6.0.0')
38
36
  def validate_each(record, attribute, _value)
39
37
  return true unless record.send(attribute).attached?
40
38
 
@@ -91,29 +89,32 @@ module ActiveStorageValidations
91
89
 
92
90
  # Validation based on checks :width and :height.
93
91
  else
92
+ width_or_height_invalid = false
94
93
  [:width, :height].each do |length|
95
94
  next unless options[length]
96
95
  if options[length].is_a?(Hash)
97
96
  if options[length][:in] && (file_metadata[length] < options[length][:min] || file_metadata[length] > options[length][:max])
98
97
  add_error(record, attribute, options[:message].presence || :"dimension_#{length}_inclusion", min: options[length][:min], max: options[length][:max])
99
- return false
98
+ width_or_height_invalid = true
100
99
  else
101
100
  if options[length][:min] && file_metadata[length] < options[length][:min]
102
101
  add_error(record, attribute, options[:message].presence || :"dimension_#{length}_greater_than_or_equal_to", length: options[length][:min])
103
- return false
102
+ width_or_height_invalid = true
104
103
  end
105
104
  if options[length][:max] && file_metadata[length] > options[length][:max]
106
105
  add_error(record, attribute, options[:message].presence || :"dimension_#{length}_less_than_or_equal_to", length: options[length][:max])
107
- return false
106
+ width_or_height_invalid = true
108
107
  end
109
108
  end
110
109
  else
111
110
  if file_metadata[length] != options[length]
112
111
  add_error(record, attribute, options[:message].presence || :"dimension_#{length}_equal_to", length: options[length])
113
- return false
112
+ width_or_height_invalid = true
114
113
  end
115
114
  end
116
115
  end
116
+
117
+ return false if width_or_height_invalid
117
118
  end
118
119
 
119
120
  true # valid file
@@ -35,7 +35,7 @@ module ActiveStorageValidations
35
35
  def failure_message
36
36
  <<~MESSAGE
37
37
  Expected #{@attribute_name}
38
-
38
+
39
39
  Accept content types: #{allowed_types.join(", ")}
40
40
  #{accepted_types_and_failures}
41
41
 
@@ -57,7 +57,7 @@ module ActiveStorageValidations
57
57
  end
58
58
 
59
59
  def rejected_types
60
- @rejected_types || (Marcel::TYPES.keys - allowed_types)
60
+ @rejected_types || (content_type_keys - allowed_types)
61
61
  end
62
62
 
63
63
  def allowed_types_allowed?
@@ -96,6 +96,16 @@ module ActiveStorageValidations
96
96
  suffix = type.to_s.split('/').last
97
97
  { io: Tempfile.new('.'), filename: "test.#{suffix}", content_type: type }
98
98
  end
99
+
100
+ private
101
+
102
+ def content_type_keys
103
+ if Rails.gem_version < Gem::Version.new('6.1.0')
104
+ Mime::LOOKUP.keys
105
+ else
106
+ Marcel::TYPES.keys
107
+ end
108
+ end
99
109
  end
100
110
  end
101
111
  end
@@ -22,7 +22,7 @@ module ActiveStorageValidations
22
22
  end
23
23
 
24
24
  def self.mock_metadata(attachment, width, height)
25
- if Rails::VERSION::MAJOR >= 6
25
+ if Rails.gem_version >= Gem::Version.new('6.0.0')
26
26
  # Mock the Metadata class for rails 6
27
27
  mock = OpenStruct.new(metadata: { width: width, height: height })
28
28
  stub_method(ActiveStorageValidations::Metadata, :new, mock) do
@@ -3,9 +3,30 @@ module ActiveStorageValidations
3
3
  attr_reader :file
4
4
 
5
5
  def initialize(file)
6
+ require_image_processor
6
7
  @file = file
7
8
  end
8
9
 
10
+ def image_processor
11
+ Rails.application.config.active_storage.variant_processor
12
+ end
13
+
14
+ def exception_class
15
+ if image_processor == :vips && defined?(Vips)
16
+ Vips::Error
17
+ elsif defined?(MiniMagick)
18
+ MiniMagick::Error
19
+ end
20
+ end
21
+
22
+ def require_image_processor
23
+ if image_processor == :vips
24
+ require 'vips' unless defined?(Vips)
25
+ else
26
+ require 'mini_magick' unless defined?(MiniMagick)
27
+ end
28
+ end
29
+
9
30
  def metadata
10
31
  read_image do |image|
11
32
  if rotated_image?(image)
@@ -21,17 +42,16 @@ module ActiveStorageValidations
21
42
  def read_image
22
43
  is_string = file.is_a?(String)
23
44
  if is_string || file.is_a?(ActiveStorage::Blob)
24
- if is_string
25
- # If Rails 5.2 or 6.0, use `find_signed`
26
- if Rails::VERSION::MAJOR < 6 || (Rails::VERSION::MAJOR == 6 && Rails::VERSION::MINOR == 0)
27
- blob = ActiveStorage::Blob.find_signed(file)
28
- # If Rails 6.1 or higher, use `find_signed!`
29
- elsif Rails::VERSION::MAJOR > 6 || (Rails::VERSION::MAJOR == 6 && Rails::VERSION::MINOR >= 1)
30
- blob = ActiveStorage::Blob.find_signed!(file)
45
+ blob =
46
+ if is_string
47
+ if Rails.gem_version < Gem::Version.new('6.1.0')
48
+ ActiveStorage::Blob.find_signed(file)
49
+ else
50
+ ActiveStorage::Blob.find_signed!(file)
51
+ end
52
+ else
53
+ file
31
54
  end
32
- else
33
- blob = file
34
- end
35
55
 
36
56
  tempfile = Tempfile.new(["ActiveStorage-#{blob.id}-", blob.filename.extension_with_delimiter])
37
57
  tempfile.binmode
@@ -43,29 +63,50 @@ module ActiveStorageValidations
43
63
  tempfile.flush
44
64
  tempfile.rewind
45
65
 
46
- image = MiniMagick::Image.new(tempfile.path)
66
+ image = if image_processor == :vips && defined?(Vips) && Vips::get_suffixes.include?(File.extname(tempfile.path).downcase)
67
+ Vips::Image.new_from_file(tempfile.path)
68
+ elsif defined?(MiniMagick)
69
+ MiniMagick::Image.new(tempfile.path)
70
+ end
47
71
  else
48
- image = MiniMagick::Image.new(read_file_path)
72
+ image = if image_processor == :vips && defined?(Vips) && Vips::get_suffixes.include?(File.extname(read_file_path).downcase)
73
+ Vips::Image.new_from_file(read_file_path)
74
+ elsif defined?(MiniMagick)
75
+ MiniMagick::Image.new(read_file_path)
76
+ end
49
77
  end
50
78
 
51
- if image.valid?
79
+ if image && valid_image?(image)
52
80
  yield image
53
81
  else
54
- logger.info "Skipping image analysis because ImageMagick doesn't support the file"
82
+ logger.info "Skipping image analysis because ImageMagick or Vips doesn't support the file"
55
83
  {}
56
84
  end
57
- rescue LoadError
58
- logger.info "Skipping image analysis because the mini_magick gem isn't installed"
85
+ rescue LoadError, NameError
86
+ logger.info "Skipping image analysis because the mini_magick or ruby-vips gem isn't installed"
59
87
  {}
60
- rescue MiniMagick::Error => error
61
- logger.error "Skipping image analysis due to an ImageMagick error: #{error.message}"
88
+ rescue exception_class => error
89
+ logger.error "Skipping image analysis due to an #{exception_class.name.split('::').map(&:downcase).join(' ').capitalize} error: #{error.message}"
62
90
  {}
63
91
  ensure
64
92
  image = nil
65
93
  end
66
94
 
95
+ def valid_image?(image)
96
+ image_processor == :vips && image.is_a?(Vips::Image) ? image.avg : image.valid?
97
+ rescue exception_class
98
+ false
99
+ end
100
+
67
101
  def rotated_image?(image)
68
- %w[ RightTop LeftBottom ].include?(image["%[orientation]"])
102
+ if image_processor == :vips && image.is_a?(Vips::Image)
103
+ image.get('exif-ifd0-Orientation').include?('Right-top') ||
104
+ image.get('exif-ifd0-Orientation').include?('Left-bottom')
105
+ else
106
+ %w[ RightTop LeftBottom ].include?(image["%[orientation]"])
107
+ end
108
+ rescue exception_class # field "exif-ifd0-Orientation" not found
109
+ false
69
110
  end
70
111
 
71
112
  def read_file_path
@@ -25,6 +25,9 @@ module ActiveStorageValidations
25
25
  next if content_size_valid?(file.blob.byte_size)
26
26
 
27
27
  errors_options[:file_size] = number_to_human_size(file.blob.byte_size)
28
+ errors_options[:min_size] = number_to_human_size(min_size)
29
+ errors_options[:max_size] = number_to_human_size(max_size)
30
+
28
31
  record.errors.add(attribute, :file_size_out_of_range, **errors_options)
29
32
  break
30
33
  end
@@ -43,5 +46,13 @@ module ActiveStorageValidations
43
46
  file_size >= options[:greater_than_or_equal_to]
44
47
  end
45
48
  end
49
+
50
+ def min_size
51
+ options[:between]&.min || options[:greater_than] || options[:greater_than_or_equal_to]
52
+ end
53
+
54
+ def max_size
55
+ options[:between]&.max || options[:less_than] || options[:less_than_or_equal_to]
56
+ end
46
57
  end
47
58
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorageValidations
4
- VERSION = '0.9.5'
4
+ VERSION = '0.9.8'
5
5
  end
metadata CHANGED
@@ -1,17 +1,59 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_storage_validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Kasyanchuk
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-26 00:00:00.000000000 Z
11
+ date: 2022-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rails
14
+ name: activejob
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activemodel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 5.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 5.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: activestorage
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 5.2.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 5.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
15
57
  requirement: !ruby/object:Gem::Requirement
16
58
  requirements:
17
59
  - - ">="
@@ -52,6 +94,20 @@ dependencies:
52
94
  - - ">="
53
95
  - !ruby/object:Gem::Version
54
96
  version: 4.9.5
97
+ - !ruby/object:Gem::Dependency
98
+ name: ruby-vips
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 2.1.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 2.1.0
55
111
  - !ruby/object:Gem::Dependency
56
112
  name: pry
57
113
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +150,20 @@ dependencies:
94
150
  - - ">="
95
151
  - !ruby/object:Gem::Version
96
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: marcel
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
97
167
  description: Validations for Active Storage (presence)
98
168
  email:
99
169
  - igorkasyanchuk@gmail.com
@@ -138,7 +208,7 @@ homepage: https://github.com/igorkasyanchuk/active_storage_validations
138
208
  licenses:
139
209
  - MIT
140
210
  metadata: {}
141
- post_install_message:
211
+ post_install_message:
142
212
  rdoc_options: []
143
213
  require_paths:
144
214
  - lib
@@ -153,8 +223,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
223
  - !ruby/object:Gem::Version
154
224
  version: '0'
155
225
  requirements: []
156
- rubygems_version: 3.0.3
157
- signing_key:
226
+ rubygems_version: 3.2.3
227
+ signing_key:
158
228
  specification_version: 4
159
229
  summary: Validations for Active Storage
160
230
  test_files: []