paperclip-storage-ftp 1.0.0.rc3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +52 -33
- data/lib/paperclip/storage/ftp/server.rb +17 -4
- data/paperclip-storage-ftp.gemspec +1 -1
- data/spec/paperclip/storage/ftp/server_spec.rb +72 -15
- metadata +5 -8
data/README.md
CHANGED
@@ -9,9 +9,11 @@ to be stored on FTP servers.
|
|
9
9
|
|
10
10
|
## Installation
|
11
11
|
|
12
|
-
Add this line to your application's Gemfile
|
12
|
+
Add this line to your application's `Gemfile`:
|
13
13
|
|
14
|
-
|
14
|
+
```ruby
|
15
|
+
gem "paperclip-storage-ftp"
|
16
|
+
```
|
15
17
|
|
16
18
|
And then execute:
|
17
19
|
|
@@ -25,40 +27,45 @@ Or install it yourself as:
|
|
25
27
|
|
26
28
|
Somewhere in your code:
|
27
29
|
|
28
|
-
|
30
|
+
```ruby
|
31
|
+
require "paperclip/storage/ftp"
|
32
|
+
```
|
29
33
|
|
30
34
|
In your model:
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
36
|
+
```ruby
|
37
|
+
class User < ActiveRecord::Base
|
38
|
+
has_attached_file :avatar,
|
39
|
+
|
40
|
+
# Choose the FTP storage backend
|
41
|
+
:storage => :ftp,
|
42
|
+
|
43
|
+
# Set where to store the file on the FTP server(s).
|
44
|
+
# This supports Paperclip::Interpolations.
|
45
|
+
:path => "/path_on_ftp_server/:attachment/:id/:style/:filename",
|
46
|
+
|
47
|
+
# The full URL of where the attachment is publicly accessible.
|
48
|
+
# This supports Paperclip::Interpolations.
|
49
|
+
:url => "/url_prefix/:attachment/:id/:style/:filename",
|
50
|
+
|
51
|
+
# The list of FTP servers to use
|
52
|
+
:ftp_servers => [
|
53
|
+
{
|
54
|
+
:host => "ftp1.example.com",
|
55
|
+
:user => "foo",
|
56
|
+
:password => "bar",
|
57
|
+
:port => 21, # optional
|
58
|
+
},
|
59
|
+
# Add more servers if needed
|
60
|
+
{
|
61
|
+
:host => "ftp2.example.com",
|
62
|
+
:user => "foo",
|
63
|
+
:password => "bar",
|
64
|
+
:port => 2121
|
65
|
+
}
|
66
|
+
]
|
67
|
+
end
|
68
|
+
```
|
62
69
|
|
63
70
|
## Contributing
|
64
71
|
|
@@ -67,3 +74,15 @@ In your model:
|
|
67
74
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
68
75
|
4. Push to the branch (`git push origin my-new-feature`)
|
69
76
|
5. Create new Pull Request
|
77
|
+
|
78
|
+
## Authors
|
79
|
+
|
80
|
+
* [Sebastian Röbke](https://github.com/boosty)
|
81
|
+
* and other friendly [contributors](https://github.com/xing/paperclip-storage-ftp/graphs/contributors)
|
82
|
+
|
83
|
+
You can find out more about our work on our [dev blog](http://devblog.xing.com).
|
84
|
+
|
85
|
+
Copyright (c) 2012 [XING AG](http://www.xing.com)
|
86
|
+
|
87
|
+
Released under the MIT license. For full details see [LICENSE](https://github.com/xing/paperclip-storage-ftp/blob/master/LICENSE)
|
88
|
+
included in this distribution.
|
@@ -6,8 +6,14 @@ module Paperclip
|
|
6
6
|
module Ftp
|
7
7
|
class Server
|
8
8
|
|
9
|
+
@@connections = {}
|
10
|
+
|
11
|
+
def self.clear_connections
|
12
|
+
@@connections.clear
|
13
|
+
end
|
14
|
+
|
9
15
|
attr_accessor :host, :user, :password
|
10
|
-
attr_writer :
|
16
|
+
attr_writer :port
|
11
17
|
|
12
18
|
def initialize(options = {})
|
13
19
|
options.each do |k,v|
|
@@ -35,12 +41,19 @@ module Paperclip
|
|
35
41
|
end
|
36
42
|
|
37
43
|
def connection
|
38
|
-
|
39
|
-
|
44
|
+
connection = @@connections["#{host}:#{port}"] ||= build_connection
|
45
|
+
if connection.closed?
|
40
46
|
connection.connect(host, port)
|
41
47
|
connection.login(user, password)
|
42
|
-
connection
|
43
48
|
end
|
49
|
+
connection
|
50
|
+
end
|
51
|
+
|
52
|
+
def build_connection
|
53
|
+
connection = Net::FTP.new
|
54
|
+
connection.connect(host, port)
|
55
|
+
connection.login(user, password)
|
56
|
+
connection
|
44
57
|
end
|
45
58
|
|
46
59
|
def port
|
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
12
12
|
gem.name = "paperclip-storage-ftp"
|
13
13
|
gem.require_paths = ["lib"]
|
14
|
-
gem.version = "1.0.0
|
14
|
+
gem.version = "1.0.0"
|
15
15
|
|
16
16
|
gem.add_dependency("paperclip")
|
17
17
|
|
@@ -1,6 +1,10 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Paperclip::Storage::Ftp::Server do
|
4
|
+
before(:each) do
|
5
|
+
Paperclip::Storage::Ftp::Server.clear_connections
|
6
|
+
end
|
7
|
+
|
4
8
|
let(:server) { Paperclip::Storage::Ftp::Server.new }
|
5
9
|
|
6
10
|
context "initialize" do
|
@@ -25,36 +29,43 @@ describe Paperclip::Storage::Ftp::Server do
|
|
25
29
|
end
|
26
30
|
|
27
31
|
context "#file_exists?" do
|
32
|
+
before do
|
33
|
+
server.stub(:connection).and_return(double("connection"))
|
34
|
+
end
|
35
|
+
|
28
36
|
it "returns true if the file exists on the server" do
|
29
|
-
server.connection = double("connection")
|
30
37
|
server.connection.should_receive(:nlst).with("/files/original").and_return(["foo.jpg"])
|
31
38
|
server.file_exists?("/files/original/foo.jpg").should be_true
|
32
39
|
end
|
33
40
|
|
34
41
|
it "recognizes complete file paths correctly" do
|
35
|
-
server.connection = double("connection")
|
36
42
|
server.connection.should_receive(:nlst).with("/files/original").and_return(["/files/original/foo.jpg"])
|
37
43
|
server.file_exists?("/files/original/foo.jpg").should be_true
|
38
44
|
end
|
39
45
|
|
40
46
|
it "returns false if the file does not exist on the server" do
|
41
|
-
server.connection = double("connection")
|
42
47
|
server.connection.should_receive(:nlst).with("/files/original").and_return([])
|
43
48
|
server.file_exists?("/files/original/foo.jpg").should be_false
|
44
49
|
end
|
45
50
|
end
|
46
51
|
|
47
52
|
context "#get_file" do
|
53
|
+
before do
|
54
|
+
server.stub(:connection).and_return(double("connection"))
|
55
|
+
end
|
56
|
+
|
48
57
|
it "returns the file object" do
|
49
|
-
server.connection = double("connection")
|
50
58
|
server.connection.should_receive(:getbinaryfile).with("/files/original.jpg", "/tmp/original.jpg")
|
51
59
|
server.get_file("/files/original.jpg", "/tmp/original.jpg")
|
52
60
|
end
|
53
61
|
end
|
54
62
|
|
55
63
|
context "#put_file" do
|
64
|
+
before do
|
65
|
+
server.stub(:connection).and_return(double("connection"))
|
66
|
+
end
|
67
|
+
|
56
68
|
it "stores the file on the server" do
|
57
|
-
server.connection = double("connection")
|
58
69
|
server.should_receive(:mkdir_p).with("/files")
|
59
70
|
server.connection.should_receive(:putbinaryfile).with("/tmp/original.jpg", "/files/original.jpg")
|
60
71
|
server.put_file("/tmp/original.jpg", "/files/original.jpg")
|
@@ -62,31 +73,78 @@ describe Paperclip::Storage::Ftp::Server do
|
|
62
73
|
end
|
63
74
|
|
64
75
|
context "#delete_file" do
|
76
|
+
before do
|
77
|
+
server.stub(:connection).and_return(double("connection"))
|
78
|
+
end
|
79
|
+
|
65
80
|
it "deletes the file on the server" do
|
66
|
-
server.connection = double("connection")
|
67
81
|
server.connection.should_receive(:delete).with("/files/original.jpg")
|
68
82
|
server.delete_file("/files/original.jpg")
|
69
83
|
end
|
70
84
|
end
|
71
85
|
|
72
|
-
context "#
|
73
|
-
it "returns
|
86
|
+
context "#build_connection" do
|
87
|
+
it "returns the ftp connection for the given server" do
|
74
88
|
server.host = "ftp.example.com"
|
75
89
|
server.user = "user"
|
76
90
|
server.password = "password"
|
77
91
|
|
78
|
-
|
79
|
-
Net::FTP.should_receive(:new).
|
80
|
-
|
81
|
-
|
92
|
+
ftp = double("ftp")
|
93
|
+
Net::FTP.should_receive(:new).and_return(ftp)
|
94
|
+
ftp.should_receive(:connect).with(server.host, server.port)
|
95
|
+
ftp.should_receive(:login).with(server.user, server.password)
|
96
|
+
server.build_connection.should == ftp
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "#connection" do
|
101
|
+
it "returns the memoized ftp connection for the given server" do
|
102
|
+
connection = double("connection", :closed? => false)
|
103
|
+
server.should_receive(:build_connection).once.and_return(connection)
|
104
|
+
server.connection.should == connection
|
105
|
+
|
106
|
+
# same host, same port => memoize
|
107
|
+
same_server = Paperclip::Storage::Ftp::Server.new(
|
108
|
+
:host => server.host,
|
109
|
+
:port => server.port
|
110
|
+
)
|
111
|
+
same_server.should_receive(:build_connection).never
|
112
|
+
same_server.connection.should == connection
|
82
113
|
|
83
|
-
|
114
|
+
# different host => do not memoize
|
115
|
+
other_host_connection = double("other_host_connection", :closed? => false)
|
116
|
+
other_host_server = Paperclip::Storage::Ftp::Server.new(
|
117
|
+
:host => "other.#{server.host}",
|
118
|
+
:port => server.port
|
119
|
+
)
|
120
|
+
other_host_server.should_receive(:build_connection).once.and_return(other_host_connection)
|
121
|
+
other_host_server.connection.should == other_host_connection
|
122
|
+
|
123
|
+
# different port => do not memoize
|
124
|
+
other_port_connection = double("other_port_connection", :closed? => false)
|
125
|
+
other_port_server = Paperclip::Storage::Ftp::Server.new(
|
126
|
+
:host => server.host,
|
127
|
+
:port => server.port + 1
|
128
|
+
)
|
129
|
+
other_port_server.should_receive(:build_connection).once.and_return(other_port_connection)
|
130
|
+
other_port_server.connection.should == other_port_connection
|
131
|
+
end
|
132
|
+
|
133
|
+
it "reconnects if the connection is closed" do
|
134
|
+
connection = double("connection", :closed? => true)
|
135
|
+
server.stub(:build_connection) { connection }
|
136
|
+
connection.should_receive(:connect).with(server.host, server.port)
|
137
|
+
connection.should_receive(:login).with(server.user, server.password)
|
138
|
+
server.connection.should == connection
|
84
139
|
end
|
85
140
|
end
|
86
141
|
|
87
142
|
context "mkdir_p" do
|
143
|
+
before do
|
144
|
+
server.stub(:connection).and_return(double("connection"))
|
145
|
+
end
|
146
|
+
|
88
147
|
it "creates the directory and all its parent directories" do
|
89
|
-
server.connection = double("connection")
|
90
148
|
server.connection.should_receive(:mkdir).with("/").ordered
|
91
149
|
server.connection.should_receive(:mkdir).with("/files").ordered
|
92
150
|
server.connection.should_receive(:mkdir).with("/files/foo").ordered
|
@@ -95,7 +153,6 @@ describe Paperclip::Storage::Ftp::Server do
|
|
95
153
|
end
|
96
154
|
|
97
155
|
it "does not stop on Net::FTPPermError" do
|
98
|
-
server.connection = double("connection")
|
99
156
|
server.connection.should_receive(:mkdir).with("/").and_raise(Net::FTPPermError)
|
100
157
|
server.connection.should_receive(:mkdir).with("/files")
|
101
158
|
server.mkdir_p("/files")
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paperclip-storage-ftp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Sebastian Röbke
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: paperclip
|
@@ -126,15 +126,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
126
126
|
- - ! '>='
|
127
127
|
- !ruby/object:Gem::Version
|
128
128
|
version: '0'
|
129
|
-
segments:
|
130
|
-
- 0
|
131
|
-
hash: -504637831743076511
|
132
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
130
|
none: false
|
134
131
|
requirements:
|
135
|
-
- - ! '
|
132
|
+
- - ! '>='
|
136
133
|
- !ruby/object:Gem::Version
|
137
|
-
version:
|
134
|
+
version: '0'
|
138
135
|
requirements: []
|
139
136
|
rubyforge_project:
|
140
137
|
rubygems_version: 1.8.24
|