paperclip-storage-ftp 1.0.4 → 1.1.0.rc1
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.
- data/.gitignore +3 -0
- data/.travis.yml +0 -12
- data/Gemfile +1 -1
- data/README.md +2 -2
- data/gemfiles/Gemfile.paperclip-2.x +2 -0
- data/gemfiles/Gemfile.paperclip-3.x +1 -1
- data/lib/paperclip/storage/ftp.rb +46 -17
- data/lib/paperclip/storage/ftp/server.rb +16 -27
- data/paperclip-storage-ftp.gemspec +1 -1
- data/spec/integration_spec.rb +32 -12
- data/spec/paperclip/storage/ftp/server_spec.rb +15 -23
- data/spec/paperclip/storage/ftp_spec.rb +58 -23
- data/spec/spec_helper.rb +3 -0
- data/spec/support/integration/ftp_server.rb +4 -2
- data/spec/support/integration/user.rb +9 -2
- data/vendor/apache-ftpserver/res/conf/users.properties +20 -19
- metadata +11 -14
data/.gitignore
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
.config
|
5
5
|
.yardoc
|
6
6
|
Gemfile.lock
|
7
|
+
gemfiles/Gemfile.*.lock
|
7
8
|
InstalledFiles
|
8
9
|
_yardoc
|
9
10
|
coverage
|
@@ -21,5 +22,7 @@ tmp
|
|
21
22
|
.ruby-gemset
|
22
23
|
vendor/apache-ftpserver/res/ftpd.pid*
|
23
24
|
vendor/apache-ftpserver/res/home/*
|
25
|
+
vendor/apache-ftpserver/res/user1/*
|
26
|
+
vendor/apache-ftpserver/res/user2/*
|
24
27
|
vendor/apache-ftpserver/res/log/*
|
25
28
|
.jrubyrc
|
data/.travis.yml
CHANGED
@@ -1,21 +1,9 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 1.8.7
|
4
|
-
- 1.9.2
|
5
3
|
- 1.9.3
|
6
4
|
- 2.0.0
|
7
|
-
- jruby-18mode
|
8
5
|
- jruby-19mode
|
9
|
-
- rbx-18mode
|
10
6
|
- rbx-19mode
|
11
7
|
gemfile:
|
12
8
|
- gemfiles/Gemfile.paperclip-2.x
|
13
9
|
- gemfiles/Gemfile.paperclip-3.x
|
14
|
-
matrix:
|
15
|
-
exclude:
|
16
|
-
- rvm: 1.8.7
|
17
|
-
gemfile: gemfiles/Gemfile.paperclip-3.x
|
18
|
-
- rvm: jruby-18mode
|
19
|
-
gemfile: gemfiles/Gemfile.paperclip-3.x
|
20
|
-
- rvm: rbx-18mode
|
21
|
-
gemfile: gemfiles/Gemfile.paperclip-3.x
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -61,7 +61,7 @@ class User < ActiveRecord::Base
|
|
61
61
|
:user => "foo",
|
62
62
|
:password => "bar",
|
63
63
|
:port => 2121, # optional, 21 by default
|
64
|
-
:passive =>
|
64
|
+
:passive => false # optional, true by default
|
65
65
|
}
|
66
66
|
]
|
67
67
|
end
|
@@ -82,7 +82,7 @@ end
|
|
82
82
|
|
83
83
|
You can find out more about our work on our [dev blog](http://devblog.xing.com).
|
84
84
|
|
85
|
-
Copyright (c)
|
85
|
+
Copyright (c) 2013 [XING AG](http://www.xing.com)
|
86
86
|
|
87
87
|
Released under the MIT license. For full details see [LICENSE](https://github.com/xing/paperclip-storage-ftp/blob/master/LICENSE)
|
88
88
|
included in this distribution.
|
@@ -8,7 +8,10 @@ module Paperclip
|
|
8
8
|
module Storage
|
9
9
|
module Ftp
|
10
10
|
def exists?(style_name = default_style)
|
11
|
-
|
11
|
+
return false unless original_filename
|
12
|
+
with_primary_ftp_server do |server|
|
13
|
+
server.file_exists?(path(style_name))
|
14
|
+
end
|
12
15
|
end
|
13
16
|
|
14
17
|
def to_file(style_name = default_style)
|
@@ -20,20 +23,25 @@ module Paperclip
|
|
20
23
|
extname = File.extname(filename)
|
21
24
|
basename = File.basename(filename, extname)
|
22
25
|
file = Tempfile.new([basename, extname])
|
23
|
-
|
26
|
+
with_primary_ftp_server do |server|
|
27
|
+
server.get_file(filename, file.path)
|
28
|
+
end
|
24
29
|
file.rewind
|
25
30
|
file
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
29
34
|
def flush_writes
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
with_ftp_servers do |servers|
|
36
|
+
servers.map do |server|
|
37
|
+
Thread.new do
|
38
|
+
@queued_for_write.each do |style_name, file|
|
39
|
+
remote_path = path(style_name)
|
40
|
+
log("saving ftp://#{server.user}@#{server.host}:#{remote_path}")
|
41
|
+
server.put_file(file.path, remote_path)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end.each(&:join)
|
37
45
|
end
|
38
46
|
|
39
47
|
after_flush_writes # allows attachment to clean up temp files
|
@@ -42,26 +50,47 @@ module Paperclip
|
|
42
50
|
end
|
43
51
|
|
44
52
|
def flush_deletes
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
53
|
+
with_ftp_servers do |servers|
|
54
|
+
servers.map do |server|
|
55
|
+
Thread.new do
|
56
|
+
@queued_for_delete.each do |path|
|
57
|
+
log("deleting ftp://#{server.user}@#{server.host}:#{path}")
|
58
|
+
server.delete_file(path)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end.each(&:join)
|
50
62
|
end
|
63
|
+
|
51
64
|
@queued_for_delete = []
|
52
65
|
end
|
53
66
|
|
54
67
|
def copy_to_local_file(style, destination_path)
|
55
|
-
|
68
|
+
with_primary_ftp_server do |server|
|
69
|
+
server.get_file(path(style), destination_path)
|
70
|
+
end
|
56
71
|
end
|
57
72
|
|
58
|
-
def
|
59
|
-
|
73
|
+
def with_primary_ftp_server(&blk)
|
74
|
+
primary_ftp_server.establish_connection
|
75
|
+
yield primary_ftp_server
|
76
|
+
ensure
|
77
|
+
primary_ftp_server.close_connection
|
60
78
|
end
|
61
79
|
|
62
80
|
def primary_ftp_server
|
63
81
|
ftp_servers.first
|
64
82
|
end
|
83
|
+
|
84
|
+
def with_ftp_servers(&blk)
|
85
|
+
ftp_servers.each(&:establish_connection)
|
86
|
+
yield ftp_servers
|
87
|
+
ensure
|
88
|
+
ftp_servers.each(&:close_connection)
|
89
|
+
end
|
90
|
+
|
91
|
+
def ftp_servers
|
92
|
+
@ftp_servers ||= @options[:ftp_servers].map{|config| Server.new(config) }
|
93
|
+
end
|
65
94
|
end
|
66
95
|
end
|
67
96
|
end
|
@@ -6,19 +6,27 @@ module Paperclip
|
|
6
6
|
module Ftp
|
7
7
|
class Server
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
def self.clear_connections
|
12
|
-
@@connections.clear
|
13
|
-
end
|
14
|
-
|
15
|
-
attr_accessor :host, :user, :password, :passive
|
16
|
-
attr_writer :port
|
9
|
+
attr_accessor :host, :user, :password, :port, :passive
|
10
|
+
attr_reader :connection
|
17
11
|
|
18
12
|
def initialize(options = {})
|
19
13
|
options.each do |k,v|
|
20
14
|
send("#{k}=", v)
|
21
15
|
end
|
16
|
+
|
17
|
+
@port = Net::FTP::FTP_PORT if @port.nil?
|
18
|
+
@passive = true if @passive.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def establish_connection
|
22
|
+
@connection = Net::FTP.new
|
23
|
+
@connection.passive = passive
|
24
|
+
@connection.connect(host, port)
|
25
|
+
@connection.login(user, password)
|
26
|
+
end
|
27
|
+
|
28
|
+
def close_connection
|
29
|
+
connection.close if connection && !connection.closed?
|
22
30
|
end
|
23
31
|
|
24
32
|
def file_exists?(path)
|
@@ -42,25 +50,6 @@ module Paperclip
|
|
42
50
|
connection.delete(remote_file_path)
|
43
51
|
end
|
44
52
|
|
45
|
-
def connection
|
46
|
-
connection = @@connections["#{host}:#{port}"] ||= build_connection
|
47
|
-
connection.close
|
48
|
-
connection.connect(host, port)
|
49
|
-
connection.login(user, password)
|
50
|
-
connection
|
51
|
-
end
|
52
|
-
|
53
|
-
def build_connection
|
54
|
-
connection = Net::FTP.new
|
55
|
-
connection.passive = passive
|
56
|
-
connection.connect(host, port)
|
57
|
-
connection
|
58
|
-
end
|
59
|
-
|
60
|
-
def port
|
61
|
-
@port || Net::FTP::FTP_PORT
|
62
|
-
end
|
63
|
-
|
64
53
|
def mkdir_p(dirname)
|
65
54
|
pathname = Pathname.new(dirname)
|
66
55
|
pathname.descend do |p|
|
@@ -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.
|
14
|
+
gem.version = "1.1.0.rc1"
|
15
15
|
|
16
16
|
gem.add_dependency("paperclip")
|
17
17
|
|
data/spec/integration_spec.rb
CHANGED
@@ -1,37 +1,57 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe "
|
4
|
-
|
3
|
+
describe "paperclip-storage-ftp", :integration => true do
|
4
|
+
|
5
|
+
before(:all) do
|
5
6
|
require "support/integration/ftp_server"
|
6
7
|
require "support/integration/user"
|
7
|
-
FtpServer.clear
|
8
8
|
FtpServer.start
|
9
9
|
end
|
10
10
|
|
11
|
+
before(:each) do
|
12
|
+
FtpServer.clear
|
13
|
+
end
|
14
|
+
|
11
15
|
let(:file) { File.new(File.expand_path("../support/integration/avatar.jpg", __FILE__), "rb") }
|
16
|
+
let(:user) { User.new }
|
17
|
+
|
18
|
+
let(:uploaded_file_server1) { FtpServer::USER1_PATH + "/#{user.id}/original/avatar.jpg" }
|
19
|
+
let(:uploaded_file_server1_medium) { FtpServer::USER1_PATH + "/#{user.id}/medium/avatar.jpg" }
|
20
|
+
let(:uploaded_file_server1_thumb) { FtpServer::USER1_PATH + "/#{user.id}/thumb/avatar.jpg" }
|
21
|
+
let(:uploaded_file_server2) { FtpServer::USER2_PATH + "/#{user.id}/original/avatar.jpg" }
|
22
|
+
let(:uploaded_file_server2_medium) { FtpServer::USER2_PATH + "/#{user.id}/medium/avatar.jpg" }
|
23
|
+
let(:uploaded_file_server2_thumb) { FtpServer::USER2_PATH + "/#{user.id}/thumb/avatar.jpg" }
|
12
24
|
|
13
25
|
it "stores the attachment on the ftp servers" do
|
14
|
-
user = User.new
|
15
26
|
user.avatar = file
|
16
27
|
user.save!
|
17
|
-
file.close
|
18
28
|
|
19
|
-
File.exists?(
|
29
|
+
File.exists?(uploaded_file_server1).should be_true
|
30
|
+
File.exists?(uploaded_file_server1_medium).should be_true
|
31
|
+
File.exists?(uploaded_file_server1_thumb).should be_true
|
32
|
+
File.exists?(uploaded_file_server2).should be_true
|
33
|
+
File.exists?(uploaded_file_server2_medium).should be_true
|
34
|
+
File.exists?(uploaded_file_server2_thumb).should be_true
|
35
|
+
|
36
|
+
file.size.should == File.size(uploaded_file_server1)
|
37
|
+
file.size.should == File.size(uploaded_file_server2)
|
20
38
|
end
|
21
39
|
|
22
40
|
it "deletes an attachment from the ftp servers" do
|
23
|
-
user = User.new
|
24
41
|
user.avatar = file
|
25
42
|
user.save!
|
26
|
-
file.close
|
27
43
|
|
28
44
|
user.destroy
|
29
45
|
|
30
|
-
File.exists?(
|
46
|
+
File.exists?(uploaded_file_server1).should be_false
|
47
|
+
File.exists?(uploaded_file_server1_medium).should be_false
|
48
|
+
File.exists?(uploaded_file_server1_thumb).should be_false
|
49
|
+
File.exists?(uploaded_file_server2).should be_false
|
50
|
+
File.exists?(uploaded_file_server2_medium).should be_false
|
51
|
+
File.exists?(uploaded_file_server2_thumb).should be_false
|
31
52
|
end
|
32
53
|
|
33
54
|
it "survives temporarily closed ftp connections" do
|
34
|
-
user = User.new
|
35
55
|
user.avatar = file
|
36
56
|
user.save!
|
37
57
|
|
@@ -42,8 +62,8 @@ describe "Integration", :integration => true do
|
|
42
62
|
|
43
63
|
user.avatar = file
|
44
64
|
user.save!
|
45
|
-
file.close
|
46
65
|
|
47
|
-
File.exists?(
|
66
|
+
File.exists?(uploaded_file_server1).should be_true
|
67
|
+
File.exists?(uploaded_file_server2).should be_true
|
48
68
|
end
|
49
69
|
end
|
@@ -1,10 +1,6 @@
|
|
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
|
-
|
8
4
|
let(:server) { Paperclip::Storage::Ftp::Server.new }
|
9
5
|
|
10
6
|
context "initialize" do
|
@@ -14,7 +10,7 @@ describe Paperclip::Storage::Ftp::Server do
|
|
14
10
|
:user => "user",
|
15
11
|
:password => "password",
|
16
12
|
:port => 2121,
|
17
|
-
:passive =>
|
13
|
+
:passive => false
|
18
14
|
}
|
19
15
|
server = Paperclip::Storage::Ftp::Server.new(options)
|
20
16
|
server.host.should == options[:host]
|
@@ -28,6 +24,11 @@ describe Paperclip::Storage::Ftp::Server do
|
|
28
24
|
server = Paperclip::Storage::Ftp::Server.new
|
29
25
|
server.port.should == Net::FTP::FTP_PORT
|
30
26
|
end
|
27
|
+
|
28
|
+
it "sets passive to true by default" do
|
29
|
+
server = Paperclip::Storage::Ftp::Server.new
|
30
|
+
server.passive.should be_true
|
31
|
+
end
|
31
32
|
end
|
32
33
|
|
33
34
|
context "#file_exists?" do
|
@@ -90,24 +91,15 @@ describe Paperclip::Storage::Ftp::Server do
|
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
93
|
-
context "#
|
94
|
-
it "
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
context "#build_connection" do
|
105
|
-
it "returns an ftp connection for the given server" do
|
106
|
-
connection = double("connection")
|
107
|
-
Net::FTP.should_receive(:new).and_return(connection)
|
108
|
-
connection.should_receive(:passive=).with(server.passive)
|
109
|
-
connection.should_receive(:connect).with(server.host, server.port)
|
110
|
-
server.build_connection.should == connection
|
94
|
+
context "#establish_connection" do
|
95
|
+
it "creates the ftp connection for the given server" do
|
96
|
+
ftp = double("ftp")
|
97
|
+
Net::FTP.should_receive(:new).and_return(ftp)
|
98
|
+
ftp.should_receive(:passive=).with(server.passive)
|
99
|
+
ftp.should_receive(:connect).with(server.host, server.port)
|
100
|
+
ftp.should_receive(:login).with(server.user, server.password)
|
101
|
+
server.establish_connection
|
102
|
+
server.connection.should == ftp
|
111
103
|
end
|
112
104
|
end
|
113
105
|
|
@@ -26,6 +26,9 @@ describe Paperclip::Storage::Ftp do
|
|
26
26
|
})
|
27
27
|
end
|
28
28
|
|
29
|
+
let(:first_server) { Paperclip::Storage::Ftp::Server.new }
|
30
|
+
let(:second_server) { Paperclip::Storage::Ftp::Server.new }
|
31
|
+
|
29
32
|
context "#exists?" do
|
30
33
|
it "returns false if original_filename not set" do
|
31
34
|
attachment.stub(:original_filename).and_return(nil)
|
@@ -33,12 +36,14 @@ describe Paperclip::Storage::Ftp do
|
|
33
36
|
end
|
34
37
|
|
35
38
|
it "returns true if the file exists on the primary server" do
|
36
|
-
|
39
|
+
first_server.should_receive(:file_exists?).with("/files/original/foo.jpg").and_return(true)
|
40
|
+
attachment.should_receive(:with_primary_ftp_server).and_yield(first_server)
|
37
41
|
attachment.exists?.should be_true
|
38
42
|
end
|
39
43
|
|
40
44
|
it "accepts an optional style_name parameter to build the correct file path" do
|
41
|
-
|
45
|
+
first_server.should_receive(:file_exists?).with("/files/thumb/foo.jpg").and_return(true)
|
46
|
+
attachment.should_receive(:with_primary_ftp_server).and_yield(first_server)
|
42
47
|
attachment.exists?(:thumb)
|
43
48
|
end
|
44
49
|
end
|
@@ -49,7 +54,8 @@ describe Paperclip::Storage::Ftp do
|
|
49
54
|
tempfile.should_receive(:path).and_return("/tmp/foo")
|
50
55
|
tempfile.should_receive(:rewind).with(no_args)
|
51
56
|
Tempfile.should_receive(:new).with(["foo", ".jpg"]).and_return(tempfile)
|
52
|
-
|
57
|
+
first_server.should_receive(:get_file).with("/files/original/foo.jpg", "/tmp/foo").and_return(:foo)
|
58
|
+
attachment.should_receive(:with_primary_ftp_server).and_yield(first_server)
|
53
59
|
attachment.to_file.should == tempfile
|
54
60
|
end
|
55
61
|
|
@@ -58,7 +64,8 @@ describe Paperclip::Storage::Ftp do
|
|
58
64
|
tempfile.should_receive(:path).and_return("/tmp/foo")
|
59
65
|
tempfile.should_receive(:rewind).with(no_args)
|
60
66
|
Tempfile.should_receive(:new).with(["foo", ".jpg"]).and_return(tempfile)
|
61
|
-
|
67
|
+
first_server.should_receive(:get_file).with("/files/thumb/foo.jpg", anything)
|
68
|
+
attachment.should_receive(:with_primary_ftp_server).and_yield(first_server)
|
62
69
|
attachment.to_file(:thumb)
|
63
70
|
end
|
64
71
|
|
@@ -80,12 +87,13 @@ describe Paperclip::Storage::Ftp do
|
|
80
87
|
:thumb => thumb_file
|
81
88
|
})
|
82
89
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
attachment.
|
90
|
+
first_server.should_receive(:put_file).with("/tmp/original/foo.jpg", "/files/original/foo.jpg")
|
91
|
+
first_server.should_receive(:put_file).with("/tmp/thumb/foo.jpg", "/files/thumb/foo.jpg")
|
92
|
+
second_server.should_receive(:put_file).with("/tmp/original/foo.jpg", "/files/original/foo.jpg")
|
93
|
+
second_server.should_receive(:put_file).with("/tmp/thumb/foo.jpg", "/files/thumb/foo.jpg")
|
94
|
+
|
95
|
+
attachment.should_receive(:with_ftp_servers).and_yield([first_server, second_server])
|
96
|
+
|
89
97
|
attachment.should_receive(:after_flush_writes).with(no_args)
|
90
98
|
|
91
99
|
attachment.flush_writes
|
@@ -100,10 +108,13 @@ describe Paperclip::Storage::Ftp do
|
|
100
108
|
"/files/original/foo.jpg",
|
101
109
|
"/files/thumb/foo.jpg"
|
102
110
|
])
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
111
|
+
|
112
|
+
first_server.should_receive(:delete_file).with("/files/original/foo.jpg")
|
113
|
+
first_server.should_receive(:delete_file).with("/files/thumb/foo.jpg")
|
114
|
+
second_server.should_receive(:delete_file).with("/files/original/foo.jpg")
|
115
|
+
second_server.should_receive(:delete_file).with("/files/thumb/foo.jpg")
|
116
|
+
|
117
|
+
attachment.should_receive(:with_ftp_servers).and_yield([first_server, second_server])
|
107
118
|
|
108
119
|
attachment.flush_deletes
|
109
120
|
|
@@ -112,17 +123,47 @@ describe Paperclip::Storage::Ftp do
|
|
112
123
|
end
|
113
124
|
|
114
125
|
context "#copy_to_local_file" do
|
126
|
+
before do
|
127
|
+
attachment.should_receive(:with_primary_ftp_server).and_yield(first_server)
|
128
|
+
end
|
129
|
+
|
115
130
|
it "returns the file from the primary server and stores it in the path specified" do
|
116
|
-
|
117
|
-
attachment.copy_to_local_file(:original, "/local/foo")
|
131
|
+
first_server.should_receive(:get_file).with("/files/original/foo.jpg", "/local/foo").and_return(:foo)
|
132
|
+
attachment.copy_to_local_file(:original, "/local/foo").should == :foo
|
118
133
|
end
|
119
134
|
|
120
135
|
it "accepts the style parameter to build the correct path" do
|
121
|
-
|
136
|
+
first_server.should_receive(:get_file).with("/files/thumb/foo.jpg", "/local/thumb/foo")
|
122
137
|
attachment.copy_to_local_file(:thumb, "/local/thumb/foo")
|
123
138
|
end
|
124
139
|
end
|
125
140
|
|
141
|
+
context "#with_primary_ftp_server" do
|
142
|
+
it "yields the connected primary ftp server, closes the connection afterwards" do
|
143
|
+
attachment.stub(:primary_ftp_server).and_return(first_server)
|
144
|
+
first_server.should_receive(:establish_connection).ordered
|
145
|
+
first_server.should_receive(:close_connection).ordered
|
146
|
+
expect { |b| attachment.with_primary_ftp_server(&b) }.to yield_with_args(first_server)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "#primary_ftp_server" do
|
151
|
+
it "returns the first server in the list" do
|
152
|
+
attachment.primary_ftp_server.should equal(attachment.ftp_servers.first)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "#with_ftp_servers" do
|
157
|
+
it "yields the connected ftp servers, closes the connections afterwards" do
|
158
|
+
attachment.stub(:ftp_servers).and_return([first_server, second_server])
|
159
|
+
first_server.should_receive(:establish_connection).ordered
|
160
|
+
second_server.should_receive(:establish_connection).ordered
|
161
|
+
first_server.should_receive(:close_connection).ordered
|
162
|
+
second_server.should_receive(:close_connection).ordered
|
163
|
+
expect { |b| attachment.with_ftp_servers(&b) }.to yield_with_args([first_server, second_server])
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
126
167
|
context "#ftp_servers" do
|
127
168
|
it "returns the configured ftp servers" do
|
128
169
|
attachment.ftp_servers.first.host.should == "ftp1.example.com"
|
@@ -135,10 +176,4 @@ describe Paperclip::Storage::Ftp do
|
|
135
176
|
attachment.ftp_servers.second.passive.should == true
|
136
177
|
end
|
137
178
|
end
|
138
|
-
|
139
|
-
context "#primary_ftp_server" do
|
140
|
-
it "returns the first server in the list" do
|
141
|
-
attachment.primary_ftp_server.should == attachment.ftp_servers.first
|
142
|
-
end
|
143
|
-
end
|
144
179
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,7 +3,8 @@ require "daemon_controller"
|
|
3
3
|
class FtpServer
|
4
4
|
|
5
5
|
INSTALL_PATH = File.expand_path("../../../../vendor/apache-ftpserver", __FILE__)
|
6
|
-
|
6
|
+
USER1_PATH = INSTALL_PATH + "/res/user1"
|
7
|
+
USER2_PATH = INSTALL_PATH + "/res/user2"
|
7
8
|
|
8
9
|
def self.start
|
9
10
|
daemon_controller.start unless daemon_controller.running?
|
@@ -14,7 +15,8 @@ class FtpServer
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def self.clear
|
17
|
-
FileUtils.rm_r(Dir.glob(
|
18
|
+
FileUtils.rm_r(Dir.glob(USER1_PATH + "/*"))
|
19
|
+
FileUtils.rm_r(Dir.glob(USER2_PATH + "/*"))
|
18
20
|
end
|
19
21
|
|
20
22
|
private
|
@@ -19,12 +19,19 @@ class User < ActiveRecord::Base
|
|
19
19
|
|
20
20
|
has_attached_file :avatar,
|
21
21
|
:storage => :ftp,
|
22
|
+
:styles => { :medium => "50x50>", :thumb => "10x10>" },
|
22
23
|
:path => "/:id/:style/:filename",
|
23
24
|
:ftp_servers => [
|
24
25
|
{
|
25
26
|
:host => "127.0.0.1",
|
26
|
-
:user => "
|
27
|
-
:password => "
|
27
|
+
:user => "user1",
|
28
|
+
:password => "secret1",
|
29
|
+
:port => 2121
|
30
|
+
},
|
31
|
+
{
|
32
|
+
:host => "127.0.0.1",
|
33
|
+
:user => "user2",
|
34
|
+
:password => "secret2",
|
28
35
|
:port => 2121
|
29
36
|
}
|
30
37
|
]
|
@@ -15,23 +15,24 @@
|
|
15
15
|
# specific language governing permissions and limitations
|
16
16
|
# under the License.
|
17
17
|
|
18
|
-
# Password is "
|
19
|
-
ftpserver.user.
|
20
|
-
ftpserver.user.
|
21
|
-
ftpserver.user.
|
22
|
-
ftpserver.user.
|
23
|
-
ftpserver.user.
|
24
|
-
ftpserver.user.
|
25
|
-
ftpserver.user.
|
26
|
-
ftpserver.user.
|
27
|
-
ftpserver.user.
|
18
|
+
# Password is "secret1"
|
19
|
+
ftpserver.user.user1.userpassword=E52D98C459819A11775936D8DFBB7929
|
20
|
+
ftpserver.user.user1.homedirectory=./res/user1
|
21
|
+
ftpserver.user.user1.enableflag=true
|
22
|
+
ftpserver.user.user1.writepermission=true
|
23
|
+
ftpserver.user.user1.maxloginnumber=0
|
24
|
+
ftpserver.user.user1.maxloginperip=0
|
25
|
+
ftpserver.user.user1.idletime=0
|
26
|
+
ftpserver.user.user1.uploadrate=0
|
27
|
+
ftpserver.user.user1.downloadrate=0
|
28
28
|
|
29
|
-
|
30
|
-
ftpserver.user.
|
31
|
-
ftpserver.user.
|
32
|
-
ftpserver.user.
|
33
|
-
ftpserver.user.
|
34
|
-
ftpserver.user.
|
35
|
-
ftpserver.user.
|
36
|
-
ftpserver.user.
|
37
|
-
ftpserver.user.
|
29
|
+
# Password is "secret2"
|
30
|
+
ftpserver.user.user2.userpassword=E54CFB3714F76CEDD4B27889E1F6A174
|
31
|
+
ftpserver.user.user2.homedirectory=./res/user2
|
32
|
+
ftpserver.user.user2.enableflag=true
|
33
|
+
ftpserver.user.user2.writepermission=true
|
34
|
+
ftpserver.user.user2.maxloginnumber=0
|
35
|
+
ftpserver.user.user2.maxloginperip=0
|
36
|
+
ftpserver.user.user2.idletime=0
|
37
|
+
ftpserver.user.user2.uploadrate=0
|
38
|
+
ftpserver.user.user2.downloadrate=0
|
metadata
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paperclip-storage-ftp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
version: 1.0.
|
4
|
+
prerelease: 6
|
5
|
+
version: 1.1.0.rc1
|
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: 2013-
|
12
|
+
date: 2013-07-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: paperclip
|
16
|
+
type: :runtime
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
17
18
|
requirements:
|
18
19
|
- - ! '>='
|
19
20
|
- !ruby/object:Gem::Version
|
20
21
|
version: '0'
|
21
22
|
none: false
|
22
|
-
type: :runtime
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ! '>='
|
@@ -29,13 +29,13 @@ dependencies:
|
|
29
29
|
prerelease: false
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: rspec
|
32
|
+
type: :development
|
32
33
|
requirement: !ruby/object:Gem::Requirement
|
33
34
|
requirements:
|
34
35
|
- - ! '>='
|
35
36
|
- !ruby/object:Gem::Version
|
36
37
|
version: '0'
|
37
38
|
none: false
|
38
|
-
type: :development
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -45,13 +45,13 @@ dependencies:
|
|
45
45
|
prerelease: false
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: rake
|
48
|
+
type: :development
|
48
49
|
requirement: !ruby/object:Gem::Requirement
|
49
50
|
requirements:
|
50
51
|
- - ! '>='
|
51
52
|
- !ruby/object:Gem::Version
|
52
53
|
version: '0'
|
53
54
|
none: false
|
54
|
-
type: :development
|
55
55
|
version_requirements: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
57
|
- - ! '>='
|
@@ -61,13 +61,13 @@ dependencies:
|
|
61
61
|
prerelease: false
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: daemon_controller
|
64
|
+
type: :development
|
64
65
|
requirement: !ruby/object:Gem::Requirement
|
65
66
|
requirements:
|
66
67
|
- - ! '>='
|
67
68
|
- !ruby/object:Gem::Version
|
68
69
|
version: 1.1.0
|
69
70
|
none: false
|
70
|
-
type: :development
|
71
71
|
version_requirements: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ! '>='
|
@@ -77,13 +77,13 @@ dependencies:
|
|
77
77
|
prerelease: false
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: activerecord
|
80
|
+
type: :development
|
80
81
|
requirement: !ruby/object:Gem::Requirement
|
81
82
|
requirements:
|
82
83
|
- - ! '>='
|
83
84
|
- !ruby/object:Gem::Version
|
84
85
|
version: '0'
|
85
86
|
none: false
|
86
|
-
type: :development
|
87
87
|
version_requirements: !ruby/object:Gem::Requirement
|
88
88
|
requirements:
|
89
89
|
- - ! '>='
|
@@ -158,17 +158,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
158
158
|
- !ruby/object:Gem::Version
|
159
159
|
segments:
|
160
160
|
- 0
|
161
|
-
hash: -
|
161
|
+
hash: -1768079343982146071
|
162
162
|
version: '0'
|
163
163
|
none: false
|
164
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
165
|
requirements:
|
166
|
-
- - ! '
|
166
|
+
- - ! '>'
|
167
167
|
- !ruby/object:Gem::Version
|
168
|
-
|
169
|
-
- 0
|
170
|
-
hash: -3461514716041370557
|
171
|
-
version: '0'
|
168
|
+
version: 1.3.1
|
172
169
|
none: false
|
173
170
|
requirements: []
|
174
171
|
rubyforge_project:
|