carrierwave-cascade 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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