carrierwave_direct 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -0
- data/README.md +19 -1
- data/lib/carrierwave_direct.rb +1 -0
- data/lib/carrierwave_direct/action_view_extensions/form_helper.rb +6 -1
- data/lib/carrierwave_direct/locale/en.rb +2 -0
- data/lib/carrierwave_direct/mount.rb +2 -0
- data/lib/carrierwave_direct/uploader.rb +90 -94
- data/lib/carrierwave_direct/version.rb +1 -1
- data/spec/action_view_extensions/form_helper_spec.rb +7 -0
- data/spec/mount_spec.rb +2 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/carrier_wave_config.rb +2 -0
- data/spec/support/direct_uploader.rb +4 -0
- data/spec/support/form_builder_helpers.rb +5 -4
- data/spec/support/global_helpers.rb +2 -0
- data/spec/support/model_helpers.rb +2 -0
- data/spec/support/mounted_class.rb +2 -0
- data/spec/support/uploader_helpers.rb +2 -0
- data/spec/support/view_helpers.rb +2 -0
- data/spec/uploader_spec.rb +2 -0
- metadata +25 -19
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -10,6 +10,8 @@
|
|
10
10
|
|
11
11
|
Right now, CarrierWaveDirect works with [Amazon S3](http://aws.amazon.com/s3/). Adding support for [Google Storage for Developers](http://code.google.com/apis/storage/) should be fairly straight forward since the direct upload form is essentially the same. Please see the contributing section if you would like support for Google Storage for Developers or any other service that provides direct upload capabilities.
|
12
12
|
|
13
|
+
Please be aware that this gem (and S3 in general) only support single file uploads. If you want to upload multiple files simultaneously you'll have to use a javascript or flash uploader.
|
14
|
+
|
13
15
|
## Information
|
14
16
|
|
15
17
|
More information, and how-tos [available on the wiki](https://github.com/dwilkie/carrierwave_direct/wiki)
|
@@ -67,7 +69,7 @@ Remove the line `storage :file` and replace it with `include CarrierWaveDirect::
|
|
67
69
|
|
68
70
|
This adds the extra functionality for direct uploading.
|
69
71
|
|
70
|
-
If you're *not* using Rails you can generate a direct upload form to S3 similar to this:
|
72
|
+
If you're *not* using Rails you can generate a direct upload form to S3 similar to this (see also [http://doc.s3.amazonaws.com/proposals/post.html#A_Sample_Form](http://doc.s3.amazonaws.com/proposals/post.html#A_Sample_Form)):
|
71
73
|
|
72
74
|
<form action="https://s3-bucket.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
|
73
75
|
<input type="hidden" name="key" value="uploads/${filename}">
|
@@ -113,6 +115,13 @@ things just got a whole lot easier. You can generate a direct upload form like t
|
|
113
115
|
<%= f.submit %>
|
114
116
|
<% end %>
|
115
117
|
|
118
|
+
You can also pass html options like this:
|
119
|
+
|
120
|
+
<%= direct_upload_form_for @uploader, :html => { :target => "_blank_iframe" } do |f| %>
|
121
|
+
<%= f.file_field :avatar %>
|
122
|
+
<%= f.submit %>
|
123
|
+
<% end %>
|
124
|
+
|
116
125
|
Note if `User` is not an ActiveRecord object e.g.
|
117
126
|
|
118
127
|
class User
|
@@ -128,6 +137,11 @@ you can still use the form helper by including the ActiveModel modules your uplo
|
|
128
137
|
extend ActiveModel::Naming
|
129
138
|
end
|
130
139
|
|
140
|
+
Note if you're using Rails 3.0.x you'll also need to disable forgery protection
|
141
|
+
|
142
|
+
# config/application.rb
|
143
|
+
config.action_controller.allow_forgery_protection = false
|
144
|
+
|
131
145
|
Once you've uploaded your file directly to the cloud you'll probably need a way to reference it with an ORM and process it.
|
132
146
|
|
133
147
|
## Processing and referencing files in a background process
|
@@ -356,3 +370,7 @@ You should now be able to run the tests
|
|
356
370
|
|
357
371
|
bundle exec rake
|
358
372
|
|
373
|
+
## Contributors
|
374
|
+
|
375
|
+
* cblunt (Chris Blunt) - Support for passing html options
|
376
|
+
* robyurkowski (Rob Yurkowski) - Fix deprecation warnings for Rails 3.2
|
data/lib/carrierwave_direct.rb
CHANGED
@@ -16,12 +16,17 @@ module CarrierWaveDirect
|
|
16
16
|
|
17
17
|
def direct_upload_form_for(record, *args, &block)
|
18
18
|
options = args.extract_options!
|
19
|
+
|
20
|
+
html_options = {
|
21
|
+
:multipart => true
|
22
|
+
}.update(options[:html] || {})
|
23
|
+
|
19
24
|
form_for(
|
20
25
|
record,
|
21
26
|
*(args << options.merge(
|
22
27
|
:builder => CarrierWaveDirect::FormBuilder,
|
23
28
|
:url => record.direct_fog_url,
|
24
|
-
:html =>
|
29
|
+
:html => html_options,
|
25
30
|
:authenticity_token => false,
|
26
31
|
:include_id => false
|
27
32
|
)),
|
@@ -19,117 +19,113 @@ module CarrierWaveDirect
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
def guid
|
35
|
-
UUID.generate
|
36
|
-
end
|
22
|
+
def direct_fog_url(options = {})
|
23
|
+
fog_uri = CarrierWave::Storage::Fog::File.new(self, CarrierWave::Storage::Fog.new(self), nil).public_url
|
24
|
+
if options[:with_path]
|
25
|
+
uri = URI.parse(fog_uri)
|
26
|
+
path = "/#{key}"
|
27
|
+
uri.path = path
|
28
|
+
fog_uri = uri.to_s
|
29
|
+
end
|
30
|
+
fog_uri
|
31
|
+
end
|
37
32
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
33
|
+
def guid
|
34
|
+
UUID.generate
|
35
|
+
end
|
42
36
|
|
43
|
-
|
44
|
-
|
45
|
-
|
37
|
+
def key=(k)
|
38
|
+
@key = k
|
39
|
+
update_version_keys(:with => @key)
|
40
|
+
end
|
46
41
|
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
def key
|
43
|
+
@key ||= "#{store_dir}/#{guid}/#{FILENAME_WILDCARD}"
|
44
|
+
end
|
50
45
|
|
51
|
-
|
52
|
-
|
53
|
-
|
46
|
+
def has_key?
|
47
|
+
@key.present? && !(@key =~ /#{Regexp.escape(FILENAME_WILDCARD)}\z/)
|
48
|
+
end
|
54
49
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
Base64.encode64(
|
60
|
-
{
|
61
|
-
'expiration' => Time.now.utc + options[:expiration],
|
62
|
-
'conditions' => [
|
63
|
-
["starts-with", "$utf8", ""],
|
64
|
-
["starts-with", "$key", store_dir],
|
65
|
-
{"bucket" => fog_directory},
|
66
|
-
{"acl" => acl},
|
67
|
-
{"success_action_redirect" => success_action_redirect},
|
68
|
-
["content-length-range", 1, options[:max_file_size]]
|
69
|
-
]
|
70
|
-
}.to_json
|
71
|
-
).gsub("\n","")
|
72
|
-
end
|
50
|
+
def acl
|
51
|
+
s3_access_policy.to_s.gsub('_', '-')
|
52
|
+
end
|
73
53
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
54
|
+
def policy(options = {})
|
55
|
+
options[:expiration] ||= self.class.upload_expiration
|
56
|
+
options[:max_file_size] ||= self.class.max_file_size
|
57
|
+
|
58
|
+
Base64.encode64(
|
59
|
+
{
|
60
|
+
'expiration' => Time.now.utc + options[:expiration],
|
61
|
+
'conditions' => [
|
62
|
+
["starts-with", "$utf8", ""],
|
63
|
+
["starts-with", "$key", store_dir],
|
64
|
+
{"bucket" => fog_directory},
|
65
|
+
{"acl" => acl},
|
66
|
+
{"success_action_redirect" => success_action_redirect},
|
67
|
+
["content-length-range", 1, options[:max_file_size]]
|
68
|
+
]
|
69
|
+
}.to_json
|
70
|
+
).gsub("\n","")
|
71
|
+
end
|
82
72
|
|
83
|
-
|
84
|
-
|
85
|
-
|
73
|
+
def signature
|
74
|
+
Base64.encode64(
|
75
|
+
OpenSSL::HMAC.digest(
|
76
|
+
OpenSSL::Digest::Digest.new('sha1'),
|
77
|
+
aws_secret_access_key, policy
|
78
|
+
)
|
79
|
+
).gsub("\n","")
|
80
|
+
end
|
86
81
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
remote_url = model.send("remote_#{mounted_as}_url")
|
91
|
-
remote_url ? key_from_file(remote_url.split("/").pop) : return
|
92
|
-
end
|
82
|
+
def persisted?
|
83
|
+
false
|
84
|
+
end
|
93
85
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
filename_parts.join("/")
|
86
|
+
def filename
|
87
|
+
unless has_key?
|
88
|
+
# Use the attached models remote url to generate a new key otherwise return nil
|
89
|
+
remote_url = model.send("remote_#{mounted_as}_url")
|
90
|
+
remote_url ? key_from_file(remote_url.split("/").pop) : return
|
100
91
|
end
|
101
92
|
|
102
|
-
|
103
|
-
|
104
|
-
|
93
|
+
key_path = key.split("/")
|
94
|
+
filename_parts = []
|
95
|
+
filename_parts.unshift(key_path.pop)
|
96
|
+
unique_key = key_path.pop
|
97
|
+
filename_parts.unshift(unique_key) if unique_key
|
98
|
+
filename_parts.join("/")
|
99
|
+
end
|
105
100
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end
|
101
|
+
def key_regexp
|
102
|
+
/\A#{store_dir}\/[a-f\d\-]+\/.+\.#{extension_regexp}\z/
|
103
|
+
end
|
110
104
|
|
111
|
-
|
112
|
-
|
113
|
-
|
105
|
+
def extension_regexp
|
106
|
+
allowed_file_types = extension_white_list
|
107
|
+
extension_regexp = allowed_file_types.present? && allowed_file_types.any? ? "(#{allowed_file_types.join("|")})" : "\\w+"
|
108
|
+
end
|
114
109
|
|
115
|
-
|
110
|
+
def url_scheme_white_list
|
111
|
+
nil
|
112
|
+
end
|
116
113
|
|
117
|
-
|
118
|
-
new_key_parts = key.split("/")
|
119
|
-
new_key_parts.pop
|
120
|
-
new_key_parts << fname
|
121
|
-
self.key = new_key_parts.join("/")
|
122
|
-
end
|
114
|
+
private
|
123
115
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
end # InstanceMethods
|
116
|
+
def key_from_file(fname)
|
117
|
+
new_key_parts = key.split("/")
|
118
|
+
new_key_parts.pop
|
119
|
+
new_key_parts << fname
|
120
|
+
self.key = new_key_parts.join("/")
|
121
|
+
end
|
131
122
|
|
132
|
-
|
123
|
+
# Update the versions to use this key
|
124
|
+
def update_version_keys(options)
|
125
|
+
versions.each do |name, uploader|
|
126
|
+
uploader.key = options[:with]
|
127
|
+
end
|
128
|
+
end
|
133
129
|
|
134
130
|
# Put the version name at the end of the filename since the guid is also stored
|
135
131
|
# e.g. guid/filename_thumb.jpg instead of CarrierWave's default: thumb_guid/filename.jpg
|
@@ -22,7 +22,14 @@ describe CarrierWaveDirect::ActionViewExtensions::FormHelper do
|
|
22
22
|
:action => "http://example.com", :method => "post", :enctype => "multipart/form-data"
|
23
23
|
)
|
24
24
|
end
|
25
|
+
|
26
|
+
it "should include any html options passed as through :html" do
|
27
|
+
form(:html => { :target => "_blank_iframe" }).should submit_to(
|
28
|
+
:action => "http://example.com", :method => "post", :enctype => "multipart/form-data", :target => "_blank_iframe"
|
29
|
+
)
|
30
|
+
end
|
25
31
|
end
|
26
32
|
end
|
33
|
+
|
27
34
|
end
|
28
35
|
|
data/spec/mount_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
require 'action_view'
|
4
4
|
require 'action_view/template'
|
5
5
|
|
6
|
+
require File.join(File.dirname(__FILE__), 'view_helpers')
|
7
|
+
|
6
8
|
require 'carrierwave_direct/form_builder'
|
7
9
|
require 'carrierwave_direct/action_view_extensions/form_helper'
|
8
10
|
|
@@ -12,7 +14,7 @@ module FormBuilderHelpers
|
|
12
14
|
include ActionView::Context
|
13
15
|
include ActionController::RecordIdentifier
|
14
16
|
|
15
|
-
include ViewHelpers
|
17
|
+
include ::ViewHelpers
|
16
18
|
|
17
19
|
def direct_uploader
|
18
20
|
defined?(super) ? super : @direct_uploader ||= MountedClass.new.video
|
@@ -27,10 +29,9 @@ module FormBuilderHelpers
|
|
27
29
|
false
|
28
30
|
end
|
29
31
|
|
30
|
-
def form(&block)
|
32
|
+
def form(options = {}, &block)
|
31
33
|
blk = block_given? ? block : Proc.new {|f|}
|
32
|
-
direct_upload_form_for(direct_uploader, &blk)
|
34
|
+
direct_upload_form_for(direct_uploader, options, &blk)
|
33
35
|
end
|
34
|
-
|
35
36
|
end
|
36
37
|
|
data/spec/uploader_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: carrierwave_direct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-02-06 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: carrierwave
|
16
|
-
requirement: &
|
16
|
+
requirement: &85732130 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *85732130
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: uuid
|
27
|
-
requirement: &
|
27
|
+
requirement: &85731800 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *85731800
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: fog
|
38
|
-
requirement: &
|
38
|
+
requirement: &85731490 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *85731490
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &85731170 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *85731170
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: timecop
|
60
|
-
requirement: &
|
60
|
+
requirement: &85730900 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *85730900
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rails
|
71
|
-
requirement: &
|
71
|
+
requirement: &85730610 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *85730610
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: sqlite3
|
82
|
-
requirement: &
|
82
|
+
requirement: &85730290 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *85730290
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: capybara
|
93
|
-
requirement: &
|
93
|
+
requirement: &85729900 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *85729900
|
102
102
|
description: Process your uploads in the background by uploading directly to S3
|
103
103
|
email:
|
104
104
|
- dwilkie@gmail.com
|
@@ -154,15 +154,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
154
154
|
- - ! '>='
|
155
155
|
- !ruby/object:Gem::Version
|
156
156
|
version: '0'
|
157
|
+
segments:
|
158
|
+
- 0
|
159
|
+
hash: -831805485
|
157
160
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
161
|
none: false
|
159
162
|
requirements:
|
160
163
|
- - ! '>='
|
161
164
|
- !ruby/object:Gem::Version
|
162
165
|
version: '0'
|
166
|
+
segments:
|
167
|
+
- 0
|
168
|
+
hash: -831805485
|
163
169
|
requirements: []
|
164
170
|
rubyforge_project: carrierwave_direct
|
165
|
-
rubygems_version: 1.8.
|
171
|
+
rubygems_version: 1.8.10
|
166
172
|
signing_key:
|
167
173
|
specification_version: 3
|
168
174
|
summary: Upload direct to S3 using CarrierWave
|