carrierwave-cascade 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c43112326672ab79459094a4a061d9c024ee1c86
4
+ data.tar.gz: 00a6b125f62061e5193d40c09e27ec5994ed7aba
5
+ SHA512:
6
+ metadata.gz: 9f023fffbf2763a83ddcc708b5a15a5485c850e7840e7277ccfbdb4b5af1e63a6a970f43f4a023021cf141ab09cf1e5e1c60abf1cafd01b391fd1b130b437e4e
7
+ data.tar.gz: df5b572946044c0d6faede7244539a35a6e95b6c64b7a1d40fabdefde4c79ed6f1de7ee10bfd0f96dabedd6da26370daa6f1ce47c0c25992ad82759ac9ed1e3b
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
5
+ - 2.0.0
6
+ script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in carrierwave-cascade.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Kevin Glowacz
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # Carrierwave::Cascade
2
+
3
+ [![Build Status](https://travis-ci.org/kjg/carrierwave-cascade.png?branch=master)](https://travis-ci.org/kjg/carrierwave-cascade)
4
+
5
+ A storage plugin for carrierwave that will retrieving files from a
6
+ secondary storage if the file is not present in the primary storage.
7
+ New files will always be stored in the primary storage. This is
8
+ perfect for use while migrating from one storage to another, or to
9
+ avoid polluting a production environment when running a staging
10
+ mirror.
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'carrierwave-cascade'
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ Configure carrierwave to use Cascade as its storage engine. Then set
23
+ primary and secondary storages to be used. Supply other
24
+ configuration as needed for the storages.
25
+
26
+ ```ruby
27
+ CarrierWave.configure do |config|
28
+ config.storage = :cascade
29
+ config.primary_storage = :file
30
+ config.secondary_storage = :fog
31
+
32
+ config.fog_credentials = {
33
+ :provider => 'AWS'
34
+ }
35
+ end
36
+ ```
37
+
38
+ By default, cascade will prevent files from being deleted out of the
39
+ secondary storage. If you wish secondary storage file to be deleted,
40
+ specify this in the configs.
41
+
42
+ ```ruby
43
+ CarrierWave.configure do |config|
44
+ config.allow_secondary_file_deletion = true
45
+ end
46
+ ```
47
+
48
+ ## Contributing
49
+
50
+ 1. Fork it
51
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
52
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
53
+ 4. Push to the branch (`git push origin my-new-feature`)
54
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'carrierwave/cascade/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "carrierwave-cascade"
8
+ spec.version = Carrierwave::Cascade::VERSION
9
+ spec.authors = ["Kevin Glowacz"]
10
+ spec.email = ["kevin@glowacz.info"]
11
+ spec.description = %q{A storage plugin for carrierwave that will
12
+ retrieving files from a secondary storageif the file is not present in the
13
+ primary storage. New files will always be stored in the primary storage.
14
+ This is perfect for use while migrating from one storage to another, or to
15
+ avoid polluting a production environment when running a staging mirror.
16
+ }
17
+ spec.summary = %q{Retrieve from a secondary storage when the file is
18
+ not in the primary storage.
19
+ }
20
+ spec.homepage = ""
21
+ spec.license = "MIT"
22
+
23
+ spec.files = `git ls-files`.split($/)
24
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
25
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
26
+ spec.require_paths = ["lib"]
27
+
28
+ spec.add_dependency 'carrierwave', '>= 0.5.8'
29
+
30
+ spec.add_development_dependency "bundler", "~> 1.3"
31
+ spec.add_development_dependency "rake"
32
+ spec.add_development_dependency 'rspec', '~> 2.12.0'
33
+ spec.add_development_dependency 'fog'
34
+ end
@@ -0,0 +1,20 @@
1
+ require 'carrierwave'
2
+ require 'carrierwave/cascade/version'
3
+ require 'carrierwave/storage/cascade'
4
+
5
+ if defined?(CarrierWave::Storage::Fog::File)
6
+ file = CarrierWave::Storage::Fog::File.new(nil,nil,nil)
7
+ unless file.respond_to?(:exists?)
8
+ require 'carrierwave/storage/fog/file_patch'
9
+ end
10
+ end
11
+
12
+ class CarrierWave::Uploader::Base
13
+ add_config :primary_storage
14
+ add_config :secondary_storage
15
+ add_config :allow_secondary_file_deletion
16
+
17
+ configure do |config|
18
+ config.storage_engines[:cascade] = 'CarrierWave::Storage::Cascade'
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module Carrierwave
2
+ module Cascade
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,62 @@
1
+ module CarrierWave
2
+ module Storage
3
+ class Cascade < Abstract
4
+ attr_reader :primary_storage, :secondary_storage
5
+
6
+ def initialize(*args)
7
+ super(*args)
8
+
9
+ @primary_storage = get_storage(uploader.class.primary_storage).new(*args)
10
+ @secondary_storage = get_storage(uploader.class.secondary_storage).new(*args)
11
+ end
12
+
13
+ def store!(*args)
14
+ primary_storage.store!(*args)
15
+ end
16
+
17
+ def retrieve!(*args)
18
+ primary_file = primary_storage.retrieve!(*args)
19
+ secondary_file = secondary_storage.retrieve!(*args)
20
+
21
+ if !primary_file.exists? && secondary_file.exists?
22
+ return SecondaryFileProxy.new(uploader, secondary_file)
23
+ else
24
+ return primary_file
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def get_storage(storage = nil)
31
+ storage.is_a?(Symbol) ? eval(uploader.storage_engines[storage]) : storage
32
+ end
33
+
34
+ class SecondaryFileProxy
35
+
36
+ attr_reader :real_file
37
+
38
+ def initialize(uploader, real_file)
39
+ @uploader = uploader
40
+ @real_file = real_file
41
+ end
42
+
43
+ def delete
44
+ if true === @uploader.allow_secondary_file_deletion
45
+ return real_file.delete
46
+ else
47
+ return true
48
+ end
49
+ end
50
+
51
+ def method_missing(*args, &block)
52
+ real_file.send(*args, &block)
53
+ end
54
+
55
+ def respond_to?(*args)
56
+ @real_file.respond_to?(*args)
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,11 @@
1
+ class CarrierWave::Storage::Fog::File
2
+ ##
3
+ # Check if the file exists on the remote service
4
+ #
5
+ # === Returns
6
+ #
7
+ # [Boolean] true if file exists or false
8
+ def exists?
9
+ !!directory.files.head(path)
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe CarrierWave::Uploader::Base do
4
+ it { should respond_to :primary_storage }
5
+ it { should respond_to :secondary_storage }
6
+ it { should respond_to :allow_secondary_file_deletion }
7
+
8
+ its(:storage_engines){ should have_key :cascade }
9
+ end
@@ -0,0 +1,158 @@
1
+ require 'spec_helper'
2
+
3
+ describe CarrierWave::Storage::Cascade do
4
+
5
+ let(:uploader){ CarrierWave::Uploader::Base.new }
6
+
7
+ before do
8
+ CarrierWave::Uploader::Base.configure do |config|
9
+ config.primary_storage = :fog
10
+ config.secondary_storage = :file
11
+ end
12
+ end
13
+
14
+ subject(:cascade){ CarrierWave::Storage::Cascade.new(uploader) }
15
+
16
+ describe "#initialize" do
17
+ its(:primary_storage){ should be_a(CarrierWave::Storage::Fog)}
18
+ its(:secondary_storage){ should be_a(CarrierWave::Storage::File)}
19
+ end
20
+
21
+ describe "#store!" do
22
+ let(:file){ CarrierWave::SanitizedFile.new("hello") }
23
+
24
+ before do
25
+ cascade.primary_storage.stub(:store! => file)
26
+ cascade.secondary_storage.stub(:store! => file)
27
+ end
28
+
29
+ it "stores to the primary_storage" do
30
+ cascade.primary_storage.should_receive(:store!).with(file)
31
+ cascade.store!(file)
32
+ end
33
+
34
+ it "does not store to the secondary_storage" do
35
+ cascade.secondary_storage.should_not_receive(:store!)
36
+ cascade.store!(file)
37
+ end
38
+ end
39
+
40
+ describe "#retrieve!" do
41
+ let(:primary_file){ CarrierWave::SanitizedFile.new("primary") }
42
+ let(:secondary_file){ CarrierWave::SanitizedFile.new("secondary") }
43
+
44
+ before do
45
+ cascade.primary_storage.stub(:retrieve! => primary_file)
46
+ cascade.secondary_storage.stub(:retrieve! => secondary_file)
47
+ end
48
+
49
+ context "when file exists in primary_storage" do
50
+ before do
51
+ primary_file.stub(:exists? => true)
52
+ end
53
+
54
+ context "when file exists in secondary_storage" do
55
+ before do
56
+ secondary_file.stub(:exists? => true)
57
+ end
58
+
59
+ it "returns the primary_file" do
60
+ cascade.retrieve!('file').should == primary_file
61
+ end
62
+ end
63
+
64
+ context "when file doesn't exist in secondary_storage" do
65
+ before do
66
+ secondary_file.stub(:exists? => false)
67
+ end
68
+
69
+ it "returns the primary_file" do
70
+ cascade.retrieve!('file').should == primary_file
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ context "when file doesn't exist in primary_storage" do
77
+ before do
78
+ primary_file.stub(:exists? => false)
79
+ end
80
+
81
+ context "when file exists in secondary_storage" do
82
+ before do
83
+ secondary_file.stub(:exists? => true)
84
+ end
85
+
86
+ it "returns a secondary_file proxy" do
87
+ cascade.retrieve!('file').should be_a(CarrierWave::Storage::Cascade::SecondaryFileProxy)
88
+ end
89
+
90
+ it "returns a proxy to the real secondary_file" do
91
+ cascade.retrieve!('file').real_file.should == secondary_file
92
+ end
93
+ end
94
+
95
+ context "when file doesn't exist in secondary_storage" do
96
+ before do
97
+ secondary_file.stub(:exists? => false)
98
+ end
99
+
100
+ it "returns the primary_file" do
101
+ cascade.retrieve!('file').should == primary_file
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ describe CarrierWave::Storage::Cascade::SecondaryFileProxy do
109
+ let(:uploader){ CarrierWave::Uploader::Base.new }
110
+ let(:file){ CarrierWave::SanitizedFile.new("file") }
111
+
112
+ subject(:cascade_file){ CarrierWave::Storage::Cascade::SecondaryFileProxy.new(uploader, file) }
113
+
114
+ before do
115
+ CarrierWave::Uploader::Base.configure do |config|
116
+ config.primary_storage = :fog
117
+ config.secondary_storage = :file
118
+ end
119
+ end
120
+
121
+ it "delegates all methods to the real file" do
122
+ file.should_receive(:foooooo)
123
+ cascade_file.foooooo
124
+ end
125
+
126
+ context "when allow_secondary_file_deletion is not set" do
127
+ it "doesn't delete the file" do
128
+ file.should_not_receive(:delete)
129
+ cascade_file.delete
130
+ end
131
+ end
132
+
133
+ context "when allow_secondary_file_deletion is false" do
134
+ before do
135
+ CarrierWave::Uploader::Base.configure do |config|
136
+ config.allow_secondary_file_deletion = false
137
+ end
138
+ end
139
+
140
+ it "doesn't delete the file" do
141
+ file.should_not_receive(:delete)
142
+ cascade_file.delete
143
+ end
144
+ end
145
+
146
+ context "when allow_secondary_file_deletion is true" do
147
+ before do
148
+ CarrierWave::Uploader::Base.configure do |config|
149
+ config.allow_secondary_file_deletion = true
150
+ end
151
+ end
152
+
153
+ it "does delete the file" do
154
+ file.should_receive(:delete)
155
+ cascade_file.delete
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,4 @@
1
+ require 'rspec'
2
+ require 'carrierwave'
3
+ require 'carrierwave-cascade'
4
+ require 'fog'
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: carrierwave-cascade
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Glowacz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-04-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: carrierwave
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.5.8
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.8
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.12.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 2.12.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: fog
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
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
+ description: "A storage plugin for carrierwave that will\n retrieving files from
84
+ a secondary storageif the file is not present in the\n primary storage. New files
85
+ will always be stored in the primary storage.\n This is perfect for use while
86
+ migrating from one storage to another, or to\n avoid polluting a production environment
87
+ when running a staging mirror.\n "
88
+ email:
89
+ - kevin@glowacz.info
90
+ executables: []
91
+ extensions: []
92
+ extra_rdoc_files: []
93
+ files:
94
+ - .gitignore
95
+ - .travis.yml
96
+ - Gemfile
97
+ - LICENSE.txt
98
+ - README.md
99
+ - Rakefile
100
+ - carrierwave-cascade.gemspec
101
+ - lib/carrierwave-cascade.rb
102
+ - lib/carrierwave/cascade/version.rb
103
+ - lib/carrierwave/storage/cascade.rb
104
+ - lib/carrierwave/storage/fog/file_patch.rb
105
+ - spec/carrierwave-cascade_spec.rb
106
+ - spec/carrierwave/storage/cascade_spec.rb
107
+ - spec/spec_helper.rb
108
+ homepage: ''
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.0.2
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Retrieve from a secondary storage when the file is not in the primary storage.
132
+ test_files:
133
+ - spec/carrierwave-cascade_spec.rb
134
+ - spec/carrierwave/storage/cascade_spec.rb
135
+ - spec/spec_helper.rb