paperclip-storage-ftp 1.2.1 → 1.2.2
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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -2
- data/Gemfile +2 -0
- data/README.md +13 -4
- data/gemfiles/Gemfile.paperclip-2.x +2 -0
- data/gemfiles/Gemfile.paperclip-3.x +2 -0
- data/gemfiles/Gemfile.paperclip-4.x +2 -0
- data/lib/paperclip/storage/ftp.rb +3 -0
- data/lib/paperclip/storage/ftp/server.rb +9 -0
- data/paperclip-storage-ftp.gemspec +1 -1
- data/spec/integration_spec.rb +45 -20
- data/spec/paperclip/storage/ftp/server_spec.rb +18 -4
- data/spec/paperclip/storage/ftp_spec.rb +6 -2
- data/spec/spec_helper.rb +16 -1
- data/spec/support/integration/user.rb +9 -13
- data/test-all.sh +1 -1
- metadata +32 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ca9a1238f7b7f38cac421a942ccd513b637bd10
|
4
|
+
data.tar.gz: d48282fb301803804f7ae63f25eac3cb8f3f7555
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17a256d870d927dece3b64d96f00c9db3d2a020a7a399494d566d4c99300edd7ef9dae2feab33c4b697236fcf111efeb2a12ed867e837400ebc3ad751a37d8ca
|
7
|
+
data.tar.gz: 8f7fe427c147d1268b2d533be54c58a68c31b86bca1bbd3525d57ecdff0fed9b6ea43fc56211d896c9a6645224a837b26ec7dd6b5ab8d080e14165e959ebb7cf
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,9 +3,11 @@
|
|
3
3
|
Allow [Paperclip](https://github.com/thoughtbot/paperclip) attachments
|
4
4
|
to be stored on FTP servers.
|
5
5
|
|
6
|
-
##
|
6
|
+
## Status
|
7
7
|
|
8
8
|
[](http://travis-ci.org/xing/paperclip-storage-ftp)
|
9
|
+
[](https://coveralls.io/r/xing/paperclip-storage-ftp?branch=master)
|
10
|
+
[](http://badge.fury.io/rb/paperclip-storage-ftp)
|
9
11
|
|
10
12
|
## Installation
|
11
13
|
|
@@ -66,11 +68,14 @@ class User < ActiveRecord::Base
|
|
66
68
|
],
|
67
69
|
|
68
70
|
# Optional socket connect timeout (in seconds).
|
69
|
-
# This only limits the connection phase, once connected
|
71
|
+
# This only limits the connection phase, once connected
|
72
|
+
# this option is of no more use.
|
70
73
|
:ftp_connect_timeout => 5, # optional, nil by default (OS default timeout)
|
71
74
|
|
72
|
-
#
|
73
|
-
#
|
75
|
+
# Optional flag to skip dead servers.
|
76
|
+
# If set to true and the connection to a particular server cannot be
|
77
|
+
# established, the connection error will be ignored and the files will
|
78
|
+
# not be uploaded to that server.
|
74
79
|
# If set to false and the connection to a particular server cannot be established,
|
75
80
|
# a SystemCallError will be raised (Errno::ETIMEDOUT, Errno::ENETUNREACH, etc.).
|
76
81
|
:ftp_ignore_failing_connections => true # optional, false by default
|
@@ -79,6 +84,10 @@ end
|
|
79
84
|
|
80
85
|
## Changelog
|
81
86
|
|
87
|
+
### 1.2.2
|
88
|
+
|
89
|
+
* Remove empty parent directories after image deletion [#21](https://github.com/xing/paperclip-storage-ftp/pull/21)
|
90
|
+
|
82
91
|
### 1.2.1
|
83
92
|
|
84
93
|
* Raise `Paperclip::Storage::Ftp::NoServerAvailable` error when using `:ftp_ignore_failing_connections => true` but all servers are down
|
@@ -59,6 +59,9 @@ module Paperclip
|
|
59
59
|
@queued_for_delete.each do |path|
|
60
60
|
log("deleting ftp://#{server.user}@#{server.host}:#{path}")
|
61
61
|
server.delete_file(path)
|
62
|
+
|
63
|
+
log("deleting empty parent directories ftp://#{server.user}@#{server.host}:#{path}")
|
64
|
+
server.rmdir_p(File.dirname(path))
|
62
65
|
end
|
63
66
|
end
|
64
67
|
end.each(&:join)
|
@@ -68,6 +68,15 @@ module Paperclip
|
|
68
68
|
connection.delete(remote_file_path)
|
69
69
|
end
|
70
70
|
|
71
|
+
def rmdir_p(dir_path)
|
72
|
+
while(true)
|
73
|
+
connection.rmdir(dir_path)
|
74
|
+
dir_path = File.dirname(dir_path)
|
75
|
+
end
|
76
|
+
rescue Net::FTPTempError, Net::FTPPermError
|
77
|
+
# Stop trying to remove parent directories
|
78
|
+
end
|
79
|
+
|
71
80
|
def mkdir_p(dirname)
|
72
81
|
pathname = Pathname.new(dirname)
|
73
82
|
pathname.descend do |p|
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
13
13
|
gem.name = "paperclip-storage-ftp"
|
14
14
|
gem.require_paths = ["lib"]
|
15
|
-
gem.version = "1.2.
|
15
|
+
gem.version = "1.2.2"
|
16
16
|
|
17
17
|
gem.add_dependency("paperclip")
|
18
18
|
|
data/spec/integration_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
require "timeout"
|
3
|
+
require "fileutils"
|
3
4
|
|
4
5
|
describe "paperclip-storage-ftp", :integration => true do
|
5
6
|
|
@@ -23,16 +24,18 @@ describe "paperclip-storage-ftp", :integration => true do
|
|
23
24
|
let(:uploaded_file_server2_medium) { FtpServer::USER2_PATH + "/medium/avatar.jpg" }
|
24
25
|
let(:uploaded_file_server2_thumb) { FtpServer::USER2_PATH + "/thumb/avatar.jpg" }
|
25
26
|
|
27
|
+
let(:uploaded_file_server1_other) { FtpServer::USER1_PATH + "/original/foo.txt" }
|
28
|
+
|
26
29
|
it "stores the attachment on the ftp servers" do
|
27
30
|
user.avatar = file
|
28
31
|
user.save!
|
29
32
|
|
30
|
-
File.exists?(uploaded_file_server1).should
|
31
|
-
File.exists?(uploaded_file_server1_medium).should
|
32
|
-
File.exists?(uploaded_file_server1_thumb).should
|
33
|
-
File.exists?(uploaded_file_server2).should
|
34
|
-
File.exists?(uploaded_file_server2_medium).should
|
35
|
-
File.exists?(uploaded_file_server2_thumb).should
|
33
|
+
File.exists?(uploaded_file_server1).should be true
|
34
|
+
File.exists?(uploaded_file_server1_medium).should be true
|
35
|
+
File.exists?(uploaded_file_server1_thumb).should be true
|
36
|
+
File.exists?(uploaded_file_server2).should be true
|
37
|
+
File.exists?(uploaded_file_server2_medium).should be true
|
38
|
+
File.exists?(uploaded_file_server2_thumb).should be true
|
36
39
|
|
37
40
|
file.size.should == File.size(uploaded_file_server1)
|
38
41
|
file.size.should == File.size(uploaded_file_server2)
|
@@ -44,12 +47,34 @@ describe "paperclip-storage-ftp", :integration => true do
|
|
44
47
|
|
45
48
|
user.destroy
|
46
49
|
|
47
|
-
File.exists?(uploaded_file_server1).should
|
48
|
-
File.exists?(uploaded_file_server1_medium).should
|
49
|
-
File.exists?(uploaded_file_server1_thumb).should
|
50
|
-
|
51
|
-
File.exists?(
|
52
|
-
File.exists?(
|
50
|
+
File.exists?(uploaded_file_server1).should be false
|
51
|
+
File.exists?(uploaded_file_server1_medium).should be false
|
52
|
+
File.exists?(uploaded_file_server1_thumb).should be false
|
53
|
+
|
54
|
+
File.exists?(uploaded_file_server2).should be false
|
55
|
+
File.exists?(uploaded_file_server2_medium).should be false
|
56
|
+
File.exists?(uploaded_file_server2_thumb).should be false
|
57
|
+
end
|
58
|
+
|
59
|
+
it "removes empty parent directories after image deletion" do
|
60
|
+
user.avatar = file
|
61
|
+
user.save!
|
62
|
+
|
63
|
+
user.destroy
|
64
|
+
|
65
|
+
Dir.exists?(File.dirname(uploaded_file_server1)).should be false
|
66
|
+
Dir.exists?(File.dirname(uploaded_file_server2)).should be false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "does not remove parent directories which are not empty" do
|
70
|
+
user.avatar = file
|
71
|
+
user.save!
|
72
|
+
|
73
|
+
FileUtils.touch(uploaded_file_server1_other)
|
74
|
+
|
75
|
+
user.destroy
|
76
|
+
|
77
|
+
File.exists?(uploaded_file_server1_other).should be true
|
53
78
|
end
|
54
79
|
|
55
80
|
it "survives temporarily closed ftp connections" do
|
@@ -64,8 +89,8 @@ describe "paperclip-storage-ftp", :integration => true do
|
|
64
89
|
user.avatar = file
|
65
90
|
user.save!
|
66
91
|
|
67
|
-
File.exists?(uploaded_file_server1).should
|
68
|
-
File.exists?(uploaded_file_server2).should
|
92
|
+
File.exists?(uploaded_file_server1).should be true
|
93
|
+
File.exists?(uploaded_file_server2).should be true
|
69
94
|
end
|
70
95
|
|
71
96
|
it "allows ignoring failed connections" do
|
@@ -73,12 +98,12 @@ describe "paperclip-storage-ftp", :integration => true do
|
|
73
98
|
user.avatar = file
|
74
99
|
expect{ user.save! }.to_not raise_error
|
75
100
|
|
76
|
-
File.exists?(uploaded_file_server1).should
|
77
|
-
File.exists?(uploaded_file_server1_medium).should
|
78
|
-
File.exists?(uploaded_file_server1_thumb).should
|
79
|
-
File.exists?(uploaded_file_server2).should
|
80
|
-
File.exists?(uploaded_file_server2_medium).should
|
81
|
-
File.exists?(uploaded_file_server2_thumb).should
|
101
|
+
File.exists?(uploaded_file_server1).should be true
|
102
|
+
File.exists?(uploaded_file_server1_medium).should be true
|
103
|
+
File.exists?(uploaded_file_server1_thumb).should be true
|
104
|
+
File.exists?(uploaded_file_server2).should be false
|
105
|
+
File.exists?(uploaded_file_server2_medium).should be false
|
106
|
+
File.exists?(uploaded_file_server2_thumb).should be false
|
82
107
|
end
|
83
108
|
|
84
109
|
it "raises a SystemCallError when not ignoring failed connections" do
|
@@ -30,22 +30,22 @@ describe Paperclip::Storage::Ftp::Server do
|
|
30
30
|
|
31
31
|
it "returns true if the file exists on the server" do
|
32
32
|
server.connection.should_receive(:nlst).with("/files/original").and_return(["foo.jpg"])
|
33
|
-
server.file_exists?("/files/original/foo.jpg").should
|
33
|
+
server.file_exists?("/files/original/foo.jpg").should be true
|
34
34
|
end
|
35
35
|
|
36
36
|
it "recognizes complete file paths correctly" do
|
37
37
|
server.connection.should_receive(:nlst).with("/files/original").and_return(["/files/original/foo.jpg"])
|
38
|
-
server.file_exists?("/files/original/foo.jpg").should
|
38
|
+
server.file_exists?("/files/original/foo.jpg").should be true
|
39
39
|
end
|
40
40
|
|
41
41
|
it "returns false if the file does not exist on the server" do
|
42
42
|
server.connection.should_receive(:nlst).with("/files/original").and_return([])
|
43
|
-
server.file_exists?("/files/original/foo.jpg").should
|
43
|
+
server.file_exists?("/files/original/foo.jpg").should be false
|
44
44
|
end
|
45
45
|
|
46
46
|
it "returns false if the ftp server responds with a FTPTempError" do
|
47
47
|
server.connection.should_receive(:nlst).with("/files/original").and_raise(Net::FTPTempError)
|
48
|
-
server.file_exists?("/files/original/foo.jpg").should
|
48
|
+
server.file_exists?("/files/original/foo.jpg").should be false
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -83,6 +83,20 @@ describe Paperclip::Storage::Ftp::Server do
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
+
context "#rmdir_p" do
|
87
|
+
before do
|
88
|
+
server.stub(:connection).and_return(double("connection"))
|
89
|
+
end
|
90
|
+
|
91
|
+
it "deletes the directory and all parent directories" do
|
92
|
+
server.connection.should_receive(:rmdir).with("/files/foo/bar")
|
93
|
+
server.connection.should_receive(:rmdir).with("/files/foo")
|
94
|
+
server.connection.should_receive(:rmdir).with("/files"){ raise Net::FTPPermError }
|
95
|
+
server.connection.should_not_receive(:rmdir).with("/")
|
96
|
+
server.rmdir_p("/files/foo/bar")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
86
100
|
context "#establish_connection" do
|
87
101
|
it "creates the ftp connection for the given server" do
|
88
102
|
ftp = double("ftp")
|
@@ -34,13 +34,13 @@ describe Paperclip::Storage::Ftp do
|
|
34
34
|
context "#exists?" do
|
35
35
|
it "returns false if original_filename not set" do
|
36
36
|
attachment.stub(:original_filename).and_return(nil)
|
37
|
-
attachment.exists?.should
|
37
|
+
attachment.exists?.should be false
|
38
38
|
end
|
39
39
|
|
40
40
|
it "returns true if the file exists on the primary server" do
|
41
41
|
first_server.should_receive(:file_exists?).with("/files/original/foo.jpg").and_return(true)
|
42
42
|
attachment.should_receive(:with_primary_ftp_server).and_yield(first_server)
|
43
|
-
attachment.exists?.should
|
43
|
+
attachment.exists?.should be true
|
44
44
|
end
|
45
45
|
|
46
46
|
it "accepts an optional style_name parameter to build the correct file path" do
|
@@ -112,9 +112,13 @@ describe Paperclip::Storage::Ftp do
|
|
112
112
|
])
|
113
113
|
|
114
114
|
first_server.should_receive(:delete_file).with("/files/original/foo.jpg")
|
115
|
+
first_server.should_receive(:rmdir_p).with("/files/original")
|
115
116
|
first_server.should_receive(:delete_file).with("/files/thumb/foo.jpg")
|
117
|
+
first_server.should_receive(:rmdir_p).with("/files/thumb")
|
116
118
|
second_server.should_receive(:delete_file).with("/files/original/foo.jpg")
|
119
|
+
second_server.should_receive(:rmdir_p).with("/files/original")
|
117
120
|
second_server.should_receive(:delete_file).with("/files/thumb/foo.jpg")
|
121
|
+
second_server.should_receive(:rmdir_p).with("/files/thumb")
|
118
122
|
|
119
123
|
attachment.should_receive(:with_ftp_servers).and_yield([first_server, second_server])
|
120
124
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
|
+
require "simplecov"
|
2
|
+
require "coveralls"
|
3
|
+
|
4
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter "spec"
|
7
|
+
end
|
8
|
+
|
1
9
|
RSpec.configure do |config|
|
2
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
3
10
|
config.run_all_when_everything_filtered = true
|
11
|
+
|
12
|
+
config.expect_with :rspec do |c|
|
13
|
+
c.syntax = [:expect, :should]
|
14
|
+
end
|
15
|
+
|
16
|
+
config.mock_with :rspec do |c|
|
17
|
+
c.syntax = [:expect, :should]
|
18
|
+
end
|
4
19
|
end
|
5
20
|
|
6
21
|
require "paperclip/storage/ftp"
|
@@ -40,29 +40,27 @@ class UserBase < ActiveRecord::Base
|
|
40
40
|
}
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
|
43
|
+
def self.setup_avatar_attachment(options = avatar_options)
|
44
|
+
has_attached_file :avatar, options
|
45
45
|
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
class User < UserBase
|
50
|
-
|
51
|
-
setup_validation
|
50
|
+
setup_avatar_attachment
|
52
51
|
end
|
53
52
|
|
54
53
|
class UserWithConnectTimeout < UserBase
|
55
54
|
TIMEOUT = 0.1
|
56
55
|
|
57
|
-
|
56
|
+
setup_avatar_attachment(avatar_options.merge(
|
58
57
|
:ftp_servers => [
|
59
58
|
{
|
60
59
|
:host => "127.0.0.2" # should raise Errno::ETIMEDOUT
|
61
60
|
}
|
62
61
|
],
|
63
62
|
:ftp_connect_timeout => TIMEOUT
|
64
|
-
)
|
65
|
-
setup_validation
|
63
|
+
))
|
66
64
|
end
|
67
65
|
|
68
66
|
class UserWithInvalidPort < UserBase
|
@@ -87,15 +85,13 @@ class UserWithInvalidPort < UserBase
|
|
87
85
|
end
|
88
86
|
|
89
87
|
class UserIgnoringFailingConnection < UserWithInvalidPort
|
90
|
-
|
88
|
+
setup_avatar_attachment(avatar_options.merge(
|
91
89
|
:ftp_ignore_failing_connections => true
|
92
|
-
)
|
93
|
-
setup_validation
|
90
|
+
))
|
94
91
|
end
|
95
92
|
|
96
93
|
class UserNotIgnoringFailingConnection < UserWithInvalidPort
|
97
|
-
|
94
|
+
setup_avatar_attachment(avatar_options.merge(
|
98
95
|
:ftp_ignore_failing_connections => false
|
99
|
-
)
|
100
|
-
setup_validation
|
96
|
+
))
|
101
97
|
end
|
data/test-all.sh
CHANGED
metadata
CHANGED
@@ -1,85 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paperclip-storage-ftp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sebastian Röbke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
version_requirements: !ruby/object:Gem::Requirement
|
15
|
-
requirements:
|
16
|
-
- - '>='
|
17
|
-
- !ruby/object:Gem::Version
|
18
|
-
version: '0'
|
19
|
-
prerelease: false
|
20
14
|
name: paperclip
|
21
15
|
requirement: !ruby/object:Gem::Requirement
|
22
16
|
requirements:
|
23
|
-
- -
|
17
|
+
- - ">="
|
24
18
|
- !ruby/object:Gem::Version
|
25
19
|
version: '0'
|
26
20
|
type: :runtime
|
27
|
-
|
21
|
+
prerelease: false
|
28
22
|
version_requirements: !ruby/object:Gem::Requirement
|
29
23
|
requirements:
|
30
|
-
- -
|
24
|
+
- - ">="
|
31
25
|
- !ruby/object:Gem::Version
|
32
26
|
version: '0'
|
33
|
-
|
27
|
+
- !ruby/object:Gem::Dependency
|
34
28
|
name: rspec
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
|
-
- -
|
31
|
+
- - ">="
|
38
32
|
- !ruby/object:Gem::Version
|
39
33
|
version: '0'
|
40
34
|
type: :development
|
41
|
-
|
35
|
+
prerelease: false
|
42
36
|
version_requirements: !ruby/object:Gem::Requirement
|
43
37
|
requirements:
|
44
|
-
- -
|
38
|
+
- - ">="
|
45
39
|
- !ruby/object:Gem::Version
|
46
40
|
version: '0'
|
47
|
-
|
41
|
+
- !ruby/object:Gem::Dependency
|
48
42
|
name: rake
|
49
43
|
requirement: !ruby/object:Gem::Requirement
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
|
-
|
49
|
+
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
51
|
requirements:
|
58
|
-
- -
|
52
|
+
- - ">="
|
59
53
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
61
|
-
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
62
56
|
name: daemon_controller
|
63
57
|
requirement: !ruby/object:Gem::Requirement
|
64
58
|
requirements:
|
65
|
-
- -
|
59
|
+
- - ">="
|
66
60
|
- !ruby/object:Gem::Version
|
67
61
|
version: 1.1.0
|
68
62
|
type: :development
|
69
|
-
|
63
|
+
prerelease: false
|
70
64
|
version_requirements: !ruby/object:Gem::Requirement
|
71
65
|
requirements:
|
72
|
-
- -
|
66
|
+
- - ">="
|
73
67
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
75
|
-
|
68
|
+
version: 1.1.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
76
70
|
name: activerecord
|
77
71
|
requirement: !ruby/object:Gem::Requirement
|
78
72
|
requirements:
|
79
|
-
- -
|
73
|
+
- - ">="
|
80
74
|
- !ruby/object:Gem::Version
|
81
75
|
version: '0'
|
82
76
|
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
83
|
description: Allow Paperclip attachments to be stored on FTP servers
|
84
84
|
email:
|
85
85
|
- sebastian.roebke@xing.com
|
@@ -87,8 +87,8 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
- .gitignore
|
91
|
-
- .travis.yml
|
90
|
+
- ".gitignore"
|
91
|
+
- ".travis.yml"
|
92
92
|
- Gemfile
|
93
93
|
- LICENSE
|
94
94
|
- README.md
|
@@ -147,17 +147,17 @@ require_paths:
|
|
147
147
|
- lib
|
148
148
|
required_ruby_version: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- -
|
150
|
+
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
153
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
154
|
requirements:
|
155
|
-
- -
|
155
|
+
- - ">="
|
156
156
|
- !ruby/object:Gem::Version
|
157
157
|
version: '0'
|
158
158
|
requirements: []
|
159
159
|
rubyforge_project:
|
160
|
-
rubygems_version: 2.2.
|
160
|
+
rubygems_version: 2.2.2
|
161
161
|
signing_key:
|
162
162
|
specification_version: 4
|
163
163
|
summary: Allow Paperclip attachments to be stored on FTP servers
|