saviour 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -18
  3. data/README.md +6 -9
  4. data/lib/saviour.rb +8 -0
  5. data/lib/saviour/base_uploader.rb +17 -4
  6. data/lib/saviour/config.rb +1 -1
  7. data/lib/saviour/db_helpers.rb +69 -0
  8. data/lib/saviour/file.rb +76 -26
  9. data/lib/saviour/integrator.rb +8 -3
  10. data/lib/saviour/life_cycle.rb +60 -12
  11. data/lib/saviour/local_storage.rb +35 -12
  12. data/lib/saviour/model.rb +12 -3
  13. data/lib/saviour/s3_storage.rb +46 -17
  14. data/lib/saviour/source_filename_extractor.rb +6 -1
  15. data/lib/saviour/uploader/processors_runner.rb +29 -2
  16. data/lib/saviour/url_source.rb +7 -3
  17. data/lib/saviour/validator.rb +34 -4
  18. data/lib/saviour/version.rb +1 -1
  19. data/saviour.gemspec +4 -3
  20. data/spec/feature/{allow_overriding_attached_as_method.rb → allow_overriding_attached_as_method_spec.rb} +0 -0
  21. data/spec/feature/crud_workflows_spec.rb +26 -10
  22. data/spec/feature/dirty_spec.rb +29 -21
  23. data/spec/feature/memory_usage_spec.rb +84 -0
  24. data/spec/feature/{processors_api.rb → processors_api_spec.rb} +22 -5
  25. data/spec/feature/{rewind_source_before_read.rb → rewind_source_before_read_spec.rb} +0 -0
  26. data/spec/feature/transactional_behavior_spec.rb +147 -0
  27. data/spec/feature/{uploader_declaration.rb → uploader_declaration_spec.rb} +0 -0
  28. data/spec/feature/validations_spec.rb +19 -0
  29. data/spec/feature/with_copy_spec.rb +43 -0
  30. data/spec/models/base_uploader_spec.rb +12 -33
  31. data/spec/models/config_spec.rb +2 -2
  32. data/spec/models/file_spec.rb +19 -47
  33. data/spec/models/local_storage_spec.rb +13 -34
  34. data/spec/models/s3_storage_spec.rb +12 -37
  35. data/spec/models/url_source_spec.rb +4 -4
  36. data/spec/spec_helper.rb +4 -0
  37. metadata +29 -14
  38. data/gemfiles/4.0.gemfile +0 -9
  39. data/gemfiles/4.1.gemfile +0 -9
  40. data/gemfiles/4.2.gemfile +0 -9
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Saviour::Config do
4
4
  describe "#storage" do
5
5
  it do
6
- expect { Saviour::Config.storage.anything }.to raise_error(RuntimeError)
6
+ expect { Saviour::Config.storage.anything }.to raise_error(Saviour::ConfigurationError)
7
7
  end
8
8
 
9
9
  it do
@@ -31,7 +31,7 @@ describe Saviour::Config do
31
31
  Thread.main.thread_variable_set("Saviour::Config", nil)
32
32
 
33
33
  Thread.new {
34
- expect { Saviour::Config.storage.anything }.to raise_error(RuntimeError)
34
+ expect { Saviour::Config.storage.anything }.to raise_error(Saviour::ConfigurationError)
35
35
  }.join
36
36
  end
37
37
 
@@ -29,7 +29,7 @@ describe Saviour::File do
29
29
  store_dir { "/store/dir" }
30
30
  } }
31
31
 
32
- let(:example_file) { double(read: "some file contents", path: "/my/path", rewind: nil) }
32
+ let(:example_file) { double(read: "some file contents", filename: "file.txt", rewind: nil) }
33
33
 
34
34
  let(:dummy_class) {
35
35
  klass = Class.new
@@ -51,33 +51,36 @@ describe Saviour::File do
51
51
 
52
52
  it "shows error if assigned object do not respond to :read" do
53
53
  file = Saviour::File.new(uploader_klass, dummy_class.new, :file)
54
- expect { file.assign(6) }.to raise_error(RuntimeError)
54
+ expect { file.assign(6) }.to raise_error(Saviour::SourceError)
55
55
  end
56
56
  end
57
57
 
58
58
  describe "#write" do
59
59
  it "fails without source" do
60
60
  file = Saviour::File.new(uploader_klass, dummy_class.new, :file)
61
- expect { file.write }.to raise_error(RuntimeError)
61
+ expect { file.write }.to raise_error(Saviour::MissingSource)
62
62
  end
63
63
 
64
64
  describe "filename used" do
65
65
  it "is extracted from original_filename if possible" do
66
66
  file = Saviour::File.new(uploader_klass, dummy_class.new, :file)
67
- file.assign(double(read: "contents", original_filename: 'original.jpg', path: "/my/path/my_file.zip", rewind: nil))
67
+ file.assign(double(read: "contents", original_filename: 'original.jpg', rewind: nil))
68
68
  uploader = double
69
69
  allow(file).to receive(:uploader).and_return(uploader)
70
- expect(uploader).to receive(:write).with("contents", "original.jpg")
70
+ expect(uploader).to receive(:_process_as_contents).with("contents", "original.jpg")
71
71
  file.write
72
72
  end
73
73
 
74
74
  it "is extracted from path if possible" do
75
75
  file = Saviour::File.new(uploader_klass, dummy_class.new, :file)
76
- file.assign(double(read: "contents", path: "/my/path/my_file.zip", rewind: nil))
77
- uploader = double
78
- allow(file).to receive(:uploader).and_return(uploader)
79
- expect(uploader).to receive(:write).with("contents", "my_file.zip")
80
- file.write
76
+ with_test_file("example.xml") do |xml_file|
77
+ dummy_file = double(read: "contents", path: xml_file.path, rewind: nil)
78
+ file.assign(dummy_file)
79
+ uploader = double
80
+ allow(file).to receive(:uploader).and_return(uploader)
81
+ expect(uploader).to receive(:_process_as_file).with(an_instance_of(Tempfile), File.basename(xml_file.path))
82
+ file.write
83
+ end
81
84
  end
82
85
 
83
86
  it "is random if cannot be guessed" do
@@ -86,18 +89,18 @@ describe Saviour::File do
86
89
  allow(SecureRandom).to receive(:hex).and_return("stubbed-random")
87
90
  uploader = double
88
91
  allow(file).to receive(:uploader).and_return(uploader)
89
- expect(uploader).to receive(:write).with("contents", "stubbed-random")
92
+ expect(uploader).to receive(:_process_as_contents).with("contents", "stubbed-random")
90
93
  file.write
91
94
  end
92
95
  end
93
96
 
94
- it "returns the path" do
97
+ it "returns the final contents and path" do
95
98
  object = dummy_class.new
96
99
  file = Saviour::File.new(uploader_klass, object, :file)
97
- file.assign(double(read: "contents", path: "/my/path/my_file.zip", rewind: nil))
100
+ file.assign(double(read: "contents", filename: "my_file.zip", rewind: nil))
98
101
  uploader = double
99
102
  allow(file).to receive(:uploader).and_return(uploader)
100
- expect(uploader).to receive(:write).with("contents", "my_file.zip").and_return("/store/dir/my_file.zip")
103
+ expect(uploader).to receive(:_process_as_contents).with("contents", "my_file.zip").and_return(['contents', "/store/dir/my_file.zip"])
101
104
  expect(file.write).to eq "/store/dir/my_file.zip"
102
105
  end
103
106
  end
@@ -114,12 +117,12 @@ describe Saviour::File do
114
117
 
115
118
  it "is cleared after persisting" do
116
119
  file = Saviour::File.new(uploader_klass, dummy_class.new, :file)
117
- file.assign(double(read: "contents", path: "/my/path/my_file.zip", rewind: nil))
120
+ file.assign(double(read: "contents", filename: "my_file.zip", rewind: nil))
118
121
  expect(file).to be_changed
119
122
 
120
123
  uploader = double
121
124
  allow(file).to receive(:uploader).and_return(uploader)
122
- expect(uploader).to receive(:write).and_return("/some/path")
125
+ expect(uploader).to receive(:_process_as_contents).and_return("/some/path")
123
126
  file.write
124
127
 
125
128
  expect(file).not_to be_changed
@@ -139,37 +142,6 @@ describe Saviour::File do
139
142
  end
140
143
  end
141
144
 
142
- describe "#with_copy" do
143
- it "provides a copy of the stored file" do
144
- file = Saviour::File.new(uploader_klass, dummy_class.new, :file)
145
- file.set_path! "/path/file.jpg"
146
- allow(file).to receive(:read).and_return("some contents")
147
-
148
- file.with_copy do |tmpfile|
149
- expect(tmpfile.read).to eq "some contents"
150
- end
151
- end
152
-
153
- it "deletes the copied file even on exception" do
154
- file = Saviour::File.new(uploader_klass, dummy_class.new, :file)
155
- file.set_path! "/path/file.jpg"
156
- allow(file).to receive(:read).and_return("some contents")
157
-
158
- mocked_tmpfile = double(binmode: "", rewind: "", flush: "", write: "")
159
- allow(Tempfile).to receive(:open).and_yield(mocked_tmpfile)
160
-
161
- expect(mocked_tmpfile).to receive(:close)
162
- expect(mocked_tmpfile).to receive(:delete)
163
-
164
- test_exception = Class.new(StandardError)
165
-
166
- begin
167
- file.with_copy { |_| raise(test_exception, "some exception within the block") }
168
- rescue test_exception
169
- end
170
- end
171
- end
172
-
173
145
  describe "#blank?" do
174
146
  it "it's true when not yet assigned nor persisted" do
175
147
  file = Saviour::File.new(uploader_klass, dummy_class.new, :file)
@@ -21,40 +21,19 @@ describe Saviour::LocalStorage do
21
21
  end
22
22
  end
23
23
 
24
- describe "overwritting an existing file" do
25
- context "with overwrite protection" do
26
- it "raises an error" do
27
- path = File.join(@tmpdir, destination_path)
28
-
29
- FileUtils.mkdir_p(File.dirname(path))
30
- File.write(path, "some dummy content")
31
- expect(File.file?(path)).to be_truthy
32
-
33
- with_test_file("camaloon.jpg") do |file, _|
34
- contents = file.read
35
- expect { subject.write(contents, destination_path) }.to raise_error(RuntimeError)
36
- end
37
- end
38
- end
39
-
40
- context "without overwrite protection" do
41
- subject { Saviour::LocalStorage.new(local_prefix: @tmpdir, overwrite_protection: false) }
42
-
43
- it do
44
- path = File.join(@tmpdir, destination_path)
24
+ it "overwrites the existing file" do
25
+ path = File.join(@tmpdir, destination_path)
45
26
 
46
- FileUtils.mkdir_p(File.dirname(path))
47
- File.write(path, "some dummy content")
48
- expect(File.file?(path)).to be_truthy
27
+ FileUtils.mkdir_p(File.dirname(path))
28
+ File.write(path, "some dummy content")
29
+ expect(File.file?(path)).to be_truthy
49
30
 
50
- with_test_file("camaloon.jpg") do |file, _|
51
- contents = file.read
52
- subject.write(contents, destination_path)
31
+ with_test_file("camaloon.jpg") do |file, _|
32
+ contents = file.read
33
+ subject.write(contents, destination_path)
53
34
 
54
- expect(File.file?(path)).to be_truthy
55
- expect(File.read(path)).to eq contents
56
- end
57
- end
35
+ expect(File.file?(path)).to be_truthy
36
+ expect(File.read(path)).to eq contents
58
37
  end
59
38
  end
60
39
  end
@@ -67,7 +46,7 @@ describe Saviour::LocalStorage do
67
46
  end
68
47
 
69
48
  it "fails if the file do not exists" do
70
- expect { subject.read("nope.rar") }.to raise_error(RuntimeError)
49
+ expect { subject.read("nope.rar") }.to raise_error(Saviour::FileNotPresent)
71
50
  end
72
51
  end
73
52
 
@@ -82,7 +61,7 @@ describe Saviour::LocalStorage do
82
61
  end
83
62
 
84
63
  it "fails if the file do not exists" do
85
- expect { subject.delete("nope.rar") }.to raise_error(RuntimeError)
64
+ expect { subject.delete("nope.rar") }.to raise_error(Saviour::FileNotPresent)
86
65
  end
87
66
 
88
67
  it "does not leave an empty dir behind" do
@@ -124,7 +103,7 @@ describe Saviour::LocalStorage do
124
103
  with_test_file("camaloon.jpg") do |file, _|
125
104
  expect {
126
105
  subject.public_url(File.basename(file.path))
127
- }.to raise_error(RuntimeError)
106
+ }.to raise_error(Saviour::LocalStorage::MissingPublicUrlPrefix)
128
107
  end
129
108
  end
130
109
  end
@@ -32,43 +32,18 @@ describe Saviour::S3Storage do
32
32
  expect { subject.write("contents", key) }.to raise_error.with_message(/The key in S3 must be at max 1024 bytes, this key is too big/)
33
33
  end
34
34
 
35
- describe "overwritting" do
36
- context "without overwrite protection" do
37
- subject {
38
- Saviour::S3Storage.new(
39
- bucket: "fake-bucket",
40
- aws_access_key_id: "stub",
41
- aws_secret_access_key: "stub",
42
- public_url_prefix: "https://fake-bucket.s3.amazonaws.com",
43
- overwrite_protection: false
44
- )
45
- }
46
-
47
- it "overwrites the existing file" do
48
- mocked_s3.write("some dummy contents", destination_path)
49
- expect(mocked_s3.exists?(destination_path)).to be_truthy
50
-
51
- with_test_file("camaloon.jpg") do |file, _|
52
- contents = file.read
53
- subject.write(contents, destination_path)
54
- expect(mocked_s3.read(destination_path)).to eq contents
55
- end
56
- end
57
- end
58
-
59
- context "with overwrite protection" do
60
- it "raises an exception" do
61
- mocked_s3.write("some dummy contents", destination_path)
62
- expect(mocked_s3.exists?(destination_path)).to be_truthy
35
+ it "overwrites the existing file" do
36
+ mocked_s3.write("some dummy contents", destination_path)
37
+ expect(mocked_s3.exists?(destination_path)).to be_truthy
63
38
 
64
- with_test_file("camaloon.jpg") do |file, _|
65
- contents = file.read
66
- expect { subject.write(contents, destination_path) }.to raise_error(RuntimeError)
67
- end
68
- end
39
+ with_test_file("camaloon.jpg") do |file, _|
40
+ contents = file.read
41
+ subject.write(contents, destination_path)
42
+ expect(mocked_s3.read(destination_path)).to eq contents
69
43
  end
70
44
  end
71
45
 
46
+
72
47
  it "ignores leading slash" do
73
48
  subject.write("trash contents", "/folder/file.out")
74
49
  expect(subject.exists?("folder/file.out")).to be_truthy
@@ -77,7 +52,7 @@ describe Saviour::S3Storage do
77
52
  end
78
53
 
79
54
  describe "fog create options" do
80
- subject { Saviour::S3Storage.new(bucket: "fake-bucket", aws_access_key_id: "stub", aws_secret_access_key: "stub", public_url_prefix: "https://fake-bucket.s3.amazonaws.com", create_options: {'Cache-Control' => 'max-age=31536000'}) }
55
+ subject { Saviour::S3Storage.new(bucket: "fake-bucket", aws_access_key_id: "stub", aws_secret_access_key: "stub", public_url_prefix: "https://fake-bucket.s3.amazonaws.com", create_options: { 'Cache-Control' => 'max-age=31536000' }) }
81
56
 
82
57
  it "uses passed options to create new files in S3" do
83
58
  with_test_file("camaloon.jpg") do |file, _|
@@ -103,7 +78,7 @@ describe Saviour::S3Storage do
103
78
  end
104
79
 
105
80
  it "fails if the file do not exists" do
106
- expect { subject.read("nope.rar") }.to raise_error(RuntimeError)
81
+ expect { subject.read("nope.rar") }.to raise_error(Saviour::FileNotPresent)
107
82
  end
108
83
  end
109
84
 
@@ -122,7 +97,7 @@ describe Saviour::S3Storage do
122
97
  end
123
98
 
124
99
  it "fails if the file do not exists" do
125
- expect { subject.delete("nope.rar") }.to raise_error(RuntimeError)
100
+ expect { subject.delete("nope.rar") }.to raise_error(Saviour::FileNotPresent)
126
101
  end
127
102
  end
128
103
 
@@ -152,7 +127,7 @@ describe Saviour::S3Storage do
152
127
  with_test_file("camaloon.jpg") do |file, _|
153
128
  contents = file.read
154
129
  mocked_s3.write(contents, destination_path)
155
- expect { subject.public_url(destination_path) }.to raise_error(RuntimeError)
130
+ expect { subject.public_url(destination_path) }.to raise_error(Saviour::S3Storage::MissingPublicUrlPrefix)
156
131
  end
157
132
  end
158
133
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Saviour::UrlSource do
4
4
  describe "initialization" do
5
5
  it "fails if no valid uri" do
6
- expect { Saviour::UrlSource.new("%^7QQ#%%@#@@") }.to raise_error(ArgumentError).with_message(/is not a valid URI/)
6
+ expect { Saviour::UrlSource.new("%^7QQ#%%@#@@") }.to raise_error(Saviour::UrlSource::InvalidUrl).with_message(/is not a valid URI/)
7
7
  end
8
8
 
9
9
  it "does not fail if provided a valid uri" do
@@ -23,7 +23,7 @@ describe Saviour::UrlSource do
23
23
  allow(Net::HTTP).to receive(:get_response).and_return(Net::HTTPNotFound)
24
24
 
25
25
  a = Saviour::UrlSource.new("http://aboubaosdubioaubosdubaou.com/path/file.jpg")
26
- expect { a.read }.to raise_error(RuntimeError).with_message(/failed after 3 attempts/)
26
+ expect { a.read }.to raise_error(Saviour::UrlSource::ConnectionFailed).with_message(/failed after 3 attempts/)
27
27
  end
28
28
 
29
29
  it "retries the request 3 times on error" do
@@ -54,7 +54,7 @@ describe Saviour::UrlSource do
54
54
  expect(response).to receive(:[]).with("location").exactly(10).times.and_return("http://example.org")
55
55
  expect(Net::HTTP).to receive(:get_response).exactly(10).times.and_return(response)
56
56
 
57
- expect { Saviour::UrlSource.new("http://faked.blabla").read }.to raise_error(RuntimeError).with_message(/Max number of allowed redirects reached \(10\) when resolving/)
57
+ expect { Saviour::UrlSource.new("http://faked.blabla").read }.to raise_error(Saviour::UrlSource::TooManyRedirects).with_message(/Max number of allowed redirects reached \(10\) when resolving/)
58
58
  end
59
59
 
60
60
  it "fails if the redirected location is not a valid URI" do
@@ -63,7 +63,7 @@ describe Saviour::UrlSource do
63
63
 
64
64
  expect(Net::HTTP).to receive(:get_response).and_return(response)
65
65
 
66
- expect { Saviour::UrlSource.new("http://faked.blabla").read }.to raise_error(ArgumentError).with_message(/is not a valid URI/)
66
+ expect { Saviour::UrlSource.new("http://faked.blabla").read }.to raise_error(Saviour::UrlSource::InvalidUrl).with_message(/is not a valid URI/)
67
67
  end
68
68
  end
69
69
  end
data/spec/spec_helper.rb CHANGED
@@ -5,6 +5,7 @@ require 'bundler/setup'
5
5
  require 'rspec'
6
6
  require 'active_record'
7
7
  require 'sqlite3'
8
+ require 'get_process_mem'
8
9
 
9
10
  require File.expand_path("../../lib/saviour", __FILE__)
10
11
 
@@ -43,6 +44,9 @@ RSpec.configure do |config|
43
44
  }
44
45
  end
45
46
 
47
+ config.before do
48
+ Test.delete_all
49
+ end
46
50
  config.after { Fog::Mock.reset }
47
51
  end
48
52
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saviour
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roger Campos
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-06 00:00:00.000000000 Z
11
+ date: 2018-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.0'
19
+ version: '5.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '4.0'
26
+ version: '5.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '4.0'
33
+ version: '5.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '4.0'
40
+ version: '5.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: get_process_mem
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  description: File storage handler following active record model lifecycle
140
154
  email:
141
155
  - roger@rogercampos.com
@@ -150,14 +164,12 @@ files:
150
164
  - LICENSE.txt
151
165
  - README.md
152
166
  - Rakefile
153
- - gemfiles/4.0.gemfile
154
- - gemfiles/4.1.gemfile
155
- - gemfiles/4.2.gemfile
156
167
  - gemfiles/5.0.gemfile
157
168
  - gemfiles/5.1.gemfile
158
169
  - lib/saviour.rb
159
170
  - lib/saviour/base_uploader.rb
160
171
  - lib/saviour/config.rb
172
+ - lib/saviour/db_helpers.rb
161
173
  - lib/saviour/file.rb
162
174
  - lib/saviour/integrator.rb
163
175
  - lib/saviour/life_cycle.rb
@@ -173,17 +185,20 @@ files:
173
185
  - lib/saviour/validator.rb
174
186
  - lib/saviour/version.rb
175
187
  - saviour.gemspec
176
- - spec/feature/allow_overriding_attached_as_method.rb
188
+ - spec/feature/allow_overriding_attached_as_method_spec.rb
177
189
  - spec/feature/crud_workflows_spec.rb
178
190
  - spec/feature/dirty_spec.rb
179
191
  - spec/feature/follow_file_spec.rb
180
192
  - spec/feature/halt_processor_spec.rb
193
+ - spec/feature/memory_usage_spec.rb
181
194
  - spec/feature/persisted_path_spec.rb
182
- - spec/feature/processors_api.rb
195
+ - spec/feature/processors_api_spec.rb
183
196
  - spec/feature/reload_model_spec.rb
184
- - spec/feature/rewind_source_before_read.rb
185
- - spec/feature/uploader_declaration.rb
197
+ - spec/feature/rewind_source_before_read_spec.rb
198
+ - spec/feature/transactional_behavior_spec.rb
199
+ - spec/feature/uploader_declaration_spec.rb
186
200
  - spec/feature/validations_spec.rb
201
+ - spec/feature/with_copy_spec.rb
187
202
  - spec/models/base_uploader_spec.rb
188
203
  - spec/models/config_spec.rb
189
204
  - spec/models/file_spec.rb
@@ -209,7 +224,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
209
224
  requirements:
210
225
  - - ">="
211
226
  - !ruby/object:Gem::Version
212
- version: 2.1.0
227
+ version: 2.2.0
213
228
  required_rubygems_version: !ruby/object:Gem::Requirement
214
229
  requirements:
215
230
  - - ">="