paperclip-storage-ftp 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7ac0615dacb3edb9fd6ed435afa757d631e96946
4
- data.tar.gz: 78db92783d426bb615b9beef8133d2e717d69740
3
+ metadata.gz: 8ca9a1238f7b7f38cac421a942ccd513b637bd10
4
+ data.tar.gz: d48282fb301803804f7ae63f25eac3cb8f3f7555
5
5
  SHA512:
6
- metadata.gz: f42bcf600a6cddde9324da644dfbed5de0d4af895318041cd357772bd48a59a15c38537579037701e8fecbccc5578474efd19130c6842875f08fac4757644461
7
- data.tar.gz: ac45ef8e943368a069369c5c56d7645c740f1124d28b72e768205692653fda754bb323584baa5047fbfd1174fb0cffafcc9fe531193ba29cf5018a96734225bd
6
+ metadata.gz: 17a256d870d927dece3b64d96f00c9db3d2a020a7a399494d566d4c99300edd7ef9dae2feab33c4b697236fcf111efeb2a12ed867e837400ebc3ad751a37d8ca
7
+ data.tar.gz: 8f7fe427c147d1268b2d533be54c58a68c31b86bca1bbd3525d57ecdff0fed9b6ea43fc56211d896c9a6645224a837b26ec7dd6b5ab8d080e14165e959ebb7cf
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  *.rbc
3
3
  .bundle
4
4
  .config
5
+ .coveralls.yml
5
6
  .yardoc
6
7
  Gemfile.lock
7
8
  gemfiles/Gemfile.*.lock
data/.travis.yml CHANGED
@@ -1,8 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - 2.0.0
5
- - 2.1.0
4
+ - 2.1
6
5
  - jruby-19mode
7
6
  - rbx
8
7
  gemfile:
data/Gemfile CHANGED
@@ -6,6 +6,8 @@ gemspec
6
6
  group :test do
7
7
  gem "sqlite3", :platforms => :ruby
8
8
  gem "activerecord-jdbcsqlite3-adapter", "1.3.0.beta2", :platforms => :jruby
9
+
10
+ gem "coveralls", :require => false
9
11
  end
10
12
 
11
13
  platforms :rbx do
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
- ## Build status
6
+ ## Status
7
7
 
8
8
  [![Build Status](https://secure.travis-ci.org/xing/paperclip-storage-ftp.png)](http://travis-ci.org/xing/paperclip-storage-ftp)
9
+ [![Coverage Status](https://coveralls.io/repos/xing/paperclip-storage-ftp/badge.png?branch=master)](https://coveralls.io/r/xing/paperclip-storage-ftp?branch=master)
10
+ [![Gem Version](https://badge.fury.io/rb/paperclip-storage-ftp.png)](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 this option is of no more use.
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
- # If set to true and the connection to a particular server cannot be established,
73
- # the connection error will be ignored and the files will not be uploaded to that server.
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
@@ -9,6 +9,8 @@ group :test do
9
9
 
10
10
  gem "sqlite3", :platforms => :ruby
11
11
  gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
12
+
13
+ gem "coveralls", :require => false
12
14
  end
13
15
 
14
16
  platforms :rbx do
@@ -7,6 +7,8 @@ gem "paperclip", "~>3.0"
7
7
  group :test do
8
8
  gem "sqlite3", :platforms => :ruby
9
9
  gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
10
+
11
+ gem "coveralls", :require => false
10
12
  end
11
13
 
12
14
  platforms :rbx do
@@ -7,6 +7,8 @@ gem "paperclip", "~>4.0"
7
7
  group :test do
8
8
  gem "sqlite3", :platforms => :ruby
9
9
  gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
10
+
11
+ gem "coveralls", :require => false
10
12
  end
11
13
 
12
14
  platforms :rbx do
@@ -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.1"
15
+ gem.version = "1.2.2"
16
16
 
17
17
  gem.add_dependency("paperclip")
18
18
 
@@ -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 be_true
31
- File.exists?(uploaded_file_server1_medium).should be_true
32
- File.exists?(uploaded_file_server1_thumb).should be_true
33
- File.exists?(uploaded_file_server2).should be_true
34
- File.exists?(uploaded_file_server2_medium).should be_true
35
- File.exists?(uploaded_file_server2_thumb).should be_true
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 be_false
48
- File.exists?(uploaded_file_server1_medium).should be_false
49
- File.exists?(uploaded_file_server1_thumb).should be_false
50
- File.exists?(uploaded_file_server2).should be_false
51
- File.exists?(uploaded_file_server2_medium).should be_false
52
- File.exists?(uploaded_file_server2_thumb).should be_false
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 be_true
68
- File.exists?(uploaded_file_server2).should be_true
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 be_true
77
- File.exists?(uploaded_file_server1_medium).should be_true
78
- File.exists?(uploaded_file_server1_thumb).should be_true
79
- File.exists?(uploaded_file_server2).should be_false
80
- File.exists?(uploaded_file_server2_medium).should be_false
81
- File.exists?(uploaded_file_server2_thumb).should be_false
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 be_true
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 be_true
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 be_false
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 be_false
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 be_false
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 be_true
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
- # must be called after has_attached_file
44
- def self.setup_validation
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
- has_attached_file :avatar, avatar_options
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
- has_attached_file :avatar, avatar_options.merge(
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
- has_attached_file :avatar, avatar_options.merge(
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
- has_attached_file :avatar, avatar_options.merge(
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
@@ -14,7 +14,7 @@ else
14
14
  printf "ERROR: An RVM installation was not found.\n"
15
15
  fi
16
16
 
17
- for ruby in '1.9.3' '2.0.0' '2.1.0' 'jruby --1.9' 'rbx'
17
+ for ruby in '1.9.3' '2.1' 'jruby --1.9' 'rbx'
18
18
  do
19
19
  rvm try_install $ruby
20
20
  rvm use $ruby
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.1
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-02-10 00:00:00.000000000 Z
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
- - !ruby/object:Gem::Dependency
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
- prerelease: false
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
- - !ruby/object:Gem::Dependency
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
- prerelease: false
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
- - !ruby/object:Gem::Dependency
49
+ prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
51
  requirements:
58
- - - '>='
52
+ - - ">="
59
53
  - !ruby/object:Gem::Version
60
- version: 1.1.0
61
- prerelease: false
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
- - !ruby/object:Gem::Dependency
63
+ prerelease: false
70
64
  version_requirements: !ruby/object:Gem::Requirement
71
65
  requirements:
72
- - - '>='
66
+ - - ">="
73
67
  - !ruby/object:Gem::Version
74
- version: '0'
75
- prerelease: false
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.1
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