carrierwave_direct 0.0.12 → 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/README.md +319 -221
- data/lib/carrierwave_direct/form_builder.rb +13 -7
- data/lib/carrierwave_direct/uploader.rb +18 -9
- data/lib/carrierwave_direct/uploader/configuration.rb +5 -0
- data/lib/carrierwave_direct/version.rb +1 -1
- data/spec/form_builder_spec.rb +38 -5
- data/spec/support/form_builder_helpers.rb +10 -1
- data/spec/uploader_spec.rb +47 -6
- metadata +23 -41
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3ba4e8171bac7dffd59212cdb0d05567072cae76
|
4
|
+
data.tar.gz: 0a1e05710c23fa992faf63773afc079187389e8b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8263b034630c1cbc1cdf8a92a276973dc70b879273cee525246813822702c045b7aab00a933279ccfbf7828010639f227fbab3d9cf12d26137f3c95e4a2bc43a
|
7
|
+
data.tar.gz: 43e72d866f555d57db0dc258116a9b23ac5358f4c7d80e7dd19e9527f8e1050c04cffb89e07436ca2b8f024ed5f63a4a7571bed707fb235fb7e46ea8410d5ae3
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -6,6 +6,33 @@
|
|
6
6
|
|
7
7
|
[CarrierWaveDirect](https://github.com/dwilkie/carrierwave_direct) works on top of [CarrierWave](https://github.com/jnicklas/carrierwave) and provides a simple way to achieve this.
|
8
8
|
|
9
|
+
## Project Maintainer(s) Wanted
|
10
|
+
|
11
|
+
Meh. [I just want to use it already.](https://github.com/dwilkie/carrierwave_direct#example-application)
|
12
|
+
|
13
|
+
### Why can't you do it?
|
14
|
+
|
15
|
+
I'm no longer involved in building apps which require file uploads. Therefore I no longer feel that I can do a good job maintaining this project. I just want the community to take it where it needs to go.
|
16
|
+
|
17
|
+
### What's in it for me?
|
18
|
+
|
19
|
+
* Everything
|
20
|
+
* Job Applications
|
21
|
+
* Not much
|
22
|
+
* What you make of it
|
23
|
+
|
24
|
+
### What do I need to do?
|
25
|
+
|
26
|
+
You can help by simply accepting pull requests and bumping versions. Or if you want to be more involved you could help resolve outstanding issues or develop new features.
|
27
|
+
|
28
|
+
### Who are you looking for?
|
29
|
+
|
30
|
+
Anybody who has previously contributed to CarrierWaveDirect (with tests) and/or who anybody who really wants to.
|
31
|
+
|
32
|
+
### How can I apply?
|
33
|
+
|
34
|
+
This is not a job application. I you want to maintain it, you've basically got the job. Just comment on this issue: https://github.com/dwilkie/carrierwave_direct/issues/83 and link to a contribution you've made on this gem, or some other gem.
|
35
|
+
|
9
36
|
## Example Application
|
10
37
|
|
11
38
|
For a concrete example on how to use [CarrierWaveDirect](https://github.com/dwilkie/carrierwave_direct) in a Rails application check out the [Example Application](https://github.com/dwilkie/carrierwave_direct_example).
|
@@ -24,7 +51,9 @@ Install the latest release:
|
|
24
51
|
|
25
52
|
In Rails, add it to your Gemfile:
|
26
53
|
|
27
|
-
|
54
|
+
```ruby
|
55
|
+
gem 'carrierwave_direct'
|
56
|
+
```
|
28
57
|
|
29
58
|
Note that CarrierWaveDirect is not compatible with Rails 2.
|
30
59
|
|
@@ -34,17 +63,19 @@ Please read the [CarrierWave readme](https://github.com/jnicklas/carrierwave) fi
|
|
34
63
|
|
35
64
|
CarrierWaveDirect works with [fog](https://github.com/fog/fog) so make sure you have [CarrierWave](https://github.com/jnicklas/carrierwave) set up and initialized with your fog credentials, for example:
|
36
65
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
66
|
+
```ruby
|
67
|
+
CarrierWave.configure do |config|
|
68
|
+
config.fog_credentials = {
|
69
|
+
:provider => 'AWS', # required
|
70
|
+
:aws_access_key_id => 'xxx', # required
|
71
|
+
:aws_secret_access_key => 'yyy', # required
|
72
|
+
:region => 'eu-west-1' # optional, defaults to 'us-east-1'
|
73
|
+
}
|
74
|
+
config.fog_directory = 'name_of_your_aws_bucket' # required
|
75
|
+
# see https://github.com/jnicklas/carrierwave#using-amazon-s3
|
76
|
+
# for more optional configuration
|
77
|
+
end
|
78
|
+
```
|
48
79
|
|
49
80
|
If you haven't already done so generate an uploader
|
50
81
|
|
@@ -56,15 +87,19 @@ this should give you a file in:
|
|
56
87
|
|
57
88
|
Check out this file for some hints on how you can customize your uploader. It should look something like this:
|
58
89
|
|
59
|
-
|
60
|
-
|
61
|
-
|
90
|
+
```ruby
|
91
|
+
class AvatarUploader < CarrierWave::Uploader::Base
|
92
|
+
storage :file
|
93
|
+
end
|
94
|
+
```
|
62
95
|
|
63
96
|
Remove the line `storage :file` and replace it with `include CarrierWaveDirect::Uploader` so it should look something like:
|
64
97
|
|
65
|
-
|
66
|
-
|
67
|
-
|
98
|
+
```ruby
|
99
|
+
class AvatarUploader < CarrierWave::Uploader::Base
|
100
|
+
include CarrierWaveDirect::Uploader
|
101
|
+
end
|
102
|
+
```
|
68
103
|
|
69
104
|
This adds the extra functionality for direct uploading.
|
70
105
|
|
@@ -73,100 +108,118 @@ This adds the extra functionality for direct uploading.
|
|
73
108
|
/uploads/<unique_guid>/foo.png
|
74
109
|
|
75
110
|
|
76
|
-
If you're *not* using Rails you can generate a direct upload form to S3 similar to [this example](http://doc.s3.amazonaws.com/proposals/post.html#A_Sample_Form)
|
111
|
+
If you're *not* using Rails you can generate a direct upload form to S3 similar to [this example](http://doc.s3.amazonaws.com/proposals/post.html#A_Sample_Form) by making use of the CarrierWaveDirect helper methods.
|
77
112
|
|
78
113
|
### Sinatra
|
79
114
|
|
80
115
|
Here is an example using Sinatra and Haml
|
81
116
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
+
```ruby
|
118
|
+
# uploader_test.rb
|
119
|
+
|
120
|
+
CarrierWave.configure do |config|
|
121
|
+
config.fog_credentials = {
|
122
|
+
:provider => 'AWS',
|
123
|
+
:aws_access_key_id => ENV['AWS_ACCESS_KEY_ID'],
|
124
|
+
:aws_secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
|
125
|
+
}
|
126
|
+
config.fog_directory = ENV['AWS_FOG_DIRECTORY'] # bucket name
|
127
|
+
end
|
128
|
+
|
129
|
+
class ImageUploader < CarrierWave::Uploader::Base
|
130
|
+
include CarrierWaveDirect::Uploader
|
131
|
+
end
|
132
|
+
|
133
|
+
class UploaderTest < Sinatra::Base
|
134
|
+
get "/" do
|
135
|
+
@uploader = ImageUploader.new
|
136
|
+
@uploader.success_action_redirect = request.url
|
137
|
+
haml :index
|
138
|
+
end
|
139
|
+
end
|
140
|
+
```
|
141
|
+
```haml
|
142
|
+
# index.haml
|
143
|
+
|
144
|
+
%form{:action => @uploader.direct_fog_url, :method => "post", :enctype => "multipart/form-data"}
|
145
|
+
%input{:name => "utf8", :type => "hidden"}
|
146
|
+
%input{:type => "hidden", :name => "key", :value => @uploader.key}
|
147
|
+
%input{:type => "hidden", :name => "AWSAccessKeyId", :value => @uploader.aws_access_key_id}
|
148
|
+
%input{:type => "hidden", :name => "acl", :value => @uploader.acl}
|
149
|
+
%input{:type => "hidden", :name => "success_action_redirect", :value => @uploader.success_action_redirect}
|
150
|
+
%input{:type => "hidden", :name => "policy", :value => @uploader.policy}
|
151
|
+
%input{:type => "hidden", :name => "signature", :value => @uploader.signature}
|
152
|
+
%input{:name => "file", :type => "file"}
|
153
|
+
%input{:type => "submit", :value => "Upload to S3"}
|
154
|
+
```
|
117
155
|
|
118
156
|
### Rails
|
119
157
|
|
120
158
|
If you *are* using Rails and you've mounted your uploader like this:
|
121
159
|
|
122
|
-
|
123
|
-
|
124
|
-
|
160
|
+
```ruby
|
161
|
+
class User < ActiveRecord::Base
|
162
|
+
mount_uploader :avatar, AvatarUploader
|
163
|
+
end
|
164
|
+
```
|
125
165
|
|
126
166
|
things just got a whole lot easier. You can generate a direct upload form like this:
|
127
167
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
168
|
+
```ruby
|
169
|
+
class AvatarController < ApplicationController
|
170
|
+
def new
|
171
|
+
@uploader = User.new.avatar
|
172
|
+
@uploader.success_action_redirect = new_user_url
|
173
|
+
end
|
174
|
+
end
|
175
|
+
```
|
176
|
+
```erb
|
177
|
+
<%= direct_upload_form_for @uploader do |f| %>
|
178
|
+
<%= f.file_field :avatar %>
|
179
|
+
<%= f.submit %>
|
180
|
+
<% end %>
|
181
|
+
```
|
139
182
|
|
140
183
|
After uploading to S3, You'll need to update the uploader object with the returned key in the controller action that corresponds to `new_user_url`:
|
141
184
|
|
142
|
-
|
185
|
+
```ruby
|
186
|
+
@uploader.update_attribute :key, params[:key]
|
187
|
+
```
|
143
188
|
|
144
189
|
You can also pass html options like this:
|
145
190
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
191
|
+
```erb
|
192
|
+
<%= direct_upload_form_for @uploader, :html => { :target => "_blank_iframe" } do |f| %>
|
193
|
+
<%= f.file_field :avatar %>
|
194
|
+
<%= f.submit %>
|
195
|
+
<% end %>
|
196
|
+
```
|
150
197
|
|
151
198
|
Note if `User` is not an ActiveRecord object e.g.
|
152
199
|
|
153
|
-
|
154
|
-
|
155
|
-
|
200
|
+
```ruby
|
201
|
+
class User
|
202
|
+
mount_uploader :avatar, AvatarUploader
|
203
|
+
end
|
204
|
+
```
|
156
205
|
|
157
206
|
you can still use the form helper by including the ActiveModel modules your uploader:
|
158
207
|
|
159
|
-
|
160
|
-
|
208
|
+
```ruby
|
209
|
+
class AvatarUploader < CarrierWave::Uploader::Base
|
210
|
+
include CarrierWaveDirect::Uploader
|
161
211
|
|
162
|
-
|
163
|
-
|
164
|
-
|
212
|
+
include ActiveModel::Conversion
|
213
|
+
extend ActiveModel::Naming
|
214
|
+
end
|
215
|
+
```
|
165
216
|
|
166
217
|
Note if you're using Rails 3.0.x you'll also need to disable forgery protection
|
167
218
|
|
168
|
-
|
169
|
-
|
219
|
+
```ruby
|
220
|
+
# config/application.rb
|
221
|
+
config.action_controller.allow_forgery_protection = false
|
222
|
+
```
|
170
223
|
|
171
224
|
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.
|
172
225
|
|
@@ -176,34 +229,40 @@ The default amazon content-type is "binary/octet-stream" and for many cases this
|
|
176
229
|
|
177
230
|
First, tell CarrierWaveDirect that you will include your content type manually by adding to your initializer:
|
178
231
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
232
|
+
```ruby
|
233
|
+
CarrierWave.configure do |config|
|
234
|
+
# ... fog configuration and other options ...
|
235
|
+
config.will_include_content_type = true
|
236
|
+
end
|
237
|
+
```
|
183
238
|
|
184
239
|
Then, just add a content-type element to the form.
|
185
240
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
241
|
+
```erb
|
242
|
+
<%= direct_upload_form_for @uploader do |f| %>
|
243
|
+
<%= text_field_tag 'Content-Type', 'video/mpeg' %><br>
|
244
|
+
<%= f.file_field :avatar %>
|
245
|
+
<%= f.submit %>
|
246
|
+
<% end %>
|
247
|
+
```
|
191
248
|
|
192
249
|
You could use a select as well.
|
193
250
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
251
|
+
```erb
|
252
|
+
<%= direct_upload_form_for @uploader do |f| %>
|
253
|
+
<%= select_tag 'Content-Type', options_for_select([
|
254
|
+
['Video','video/mpeg'],
|
255
|
+
['Audio','audio/mpeg'],
|
256
|
+
['Image','image/jpeg']
|
257
|
+
], 'video/mpeg') %><br>
|
258
|
+
<%= f.file_field :avatar %>
|
259
|
+
<%= f.submit %>
|
260
|
+
<% end %>
|
261
|
+
```
|
203
262
|
|
204
263
|
## Processing and referencing files in a background process
|
205
264
|
|
206
|
-
Processing and saving file uploads are typically long running tasks and should be done in a background process. CarrierWaveDirect gives you a few methods to help you do this with your favorite background processor such as [DelayedJob](https://github.com/collectiveidea/delayed_job) or [Resque](https://github.com/
|
265
|
+
Processing and saving file uploads are typically long running tasks and should be done in a background process. CarrierWaveDirect gives you a few methods to help you do this with your favorite background processor such as [DelayedJob](https://github.com/collectiveidea/delayed_job) or [Resque](https://github.com/resque/resque).
|
207
266
|
|
208
267
|
If your upload was successful then you will be redirected to the `success_action_redirect` url you specified in your uploader. S3 replies with a redirect like this: `http://example.com?bucket=your_fog_directory&key=uploads%2Fguid%2Ffile.ext&etag=%22d41d8cd98f00b204e9800998ecf8427%22`
|
209
268
|
|
@@ -211,60 +270,67 @@ The `key` is the most important piece of information as we can use it for valida
|
|
211
270
|
|
212
271
|
If you're using ActiveRecord, CarrierWaveDirect will by default validate the file extension based off your `extension_white_list` in your uploader. See the [CarrierWave readme](https://github.com/jnicklas/carrierwave) for more info. You can then use the helper `filename_valid?` to check if the filename is valid. e.g.
|
213
272
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
end
|
273
|
+
```ruby
|
274
|
+
class UsersController < ApplicationController
|
275
|
+
def new
|
276
|
+
@user = User.new(params)
|
277
|
+
unless @user.filename_valid?
|
278
|
+
flash[:error] = @user.errors.full_messages.to_sentence
|
279
|
+
redirect_to new_avatar_path
|
222
280
|
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
```
|
223
284
|
|
224
285
|
CarrierWaveDirect automatically gives you an accessible `key` attribute in your mounted model when using ActiveRecord. You can use this to put a hidden field for the `key` into your model's form.
|
225
286
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
287
|
+
```erb
|
288
|
+
<%= form_for @user do |f| %>
|
289
|
+
<%= f.hidden_field :key %>
|
290
|
+
<%= f.label :email %>
|
291
|
+
<%= f.text_field :email %>
|
292
|
+
<%= f.submit %>
|
293
|
+
<% end %>
|
294
|
+
```
|
233
295
|
then in your controller you can do something like this:
|
234
296
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
297
|
+
```ruby
|
298
|
+
def create
|
299
|
+
@user = User.new(params[:user])
|
300
|
+
if @user.save_and_process_avatar
|
301
|
+
flash[:notice] = "User being created"
|
302
|
+
redirect_to :action => :index
|
303
|
+
else
|
304
|
+
render :new
|
305
|
+
end
|
306
|
+
end
|
307
|
+
```
|
244
308
|
|
245
309
|
### Background processing
|
246
310
|
|
247
|
-
Now that the basic building blocks are in place you can process and save your avatar in the background. This example uses [Resque](https://github.com/
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
end
|
311
|
+
Now that the basic building blocks are in place you can process and save your avatar in the background. This example uses [Resque](https://github.com/resque/resque) but the same logic could be applied to [DelayedJob](https://github.com/collectiveidea/delayed_job) or any other background processor.
|
312
|
+
|
313
|
+
```ruby
|
314
|
+
class User < ActiveRecord::Base
|
315
|
+
def save_and_process_avatar(options = {})
|
316
|
+
if options[:now]
|
317
|
+
self.remote_avatar_url = avatar.direct_fog_url(:with_path => true)
|
318
|
+
save
|
319
|
+
else
|
320
|
+
Resque.enqueue(AvatarProcessor, attributes)
|
258
321
|
end
|
322
|
+
end
|
323
|
+
end
|
259
324
|
|
260
|
-
|
261
|
-
|
325
|
+
class AvatarProcessor
|
326
|
+
@queue = :avatar_processor_queue
|
262
327
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
328
|
+
def self.perform(attributes)
|
329
|
+
user = User.new(attributes)
|
330
|
+
user.save_and_process_avatar(:now => true)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
```
|
268
334
|
|
269
335
|
The method `self.remote_avatar_url=` from [CarrierWave](https://github.com/jnicklas/carrierwave) downloads the avatar from S3 and processes it. `save` then re-uploads the processed avatar to to S3
|
270
336
|
|
@@ -272,49 +338,60 @@ The method `self.remote_avatar_url=` from [CarrierWave](https://github.com/jnick
|
|
272
338
|
|
273
339
|
Your users may find it convenient to upload a file from a location on the Internet via a URL. CarrierWaveDirect gives you another accessor to achieve this.
|
274
340
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
end
|
341
|
+
```erb
|
342
|
+
<%= form_for @user do |f| %>
|
343
|
+
<%= f.hidden_field :key %>
|
344
|
+
<% unless @user.has_avatar_upload? %>
|
345
|
+
<%= f.label :remote_avatar_net_url %>
|
346
|
+
<%= f.text_field :remote_avatar_net_url %>
|
347
|
+
<%= f.submit %>
|
348
|
+
<% end %>
|
349
|
+
```
|
350
|
+
```ruby
|
351
|
+
class User < ActiveRecord::Base
|
352
|
+
def save_and_process_avatar(options = {})
|
353
|
+
if options[:now]
|
354
|
+
self.remote_avatar_url = has_remote_avatar_net_url? ? remote_avatar_net_url : avatar.direct_fog_url(:with_path => true)
|
355
|
+
save
|
356
|
+
else
|
357
|
+
Resque.enqueue(AvatarProcessor, attributes)
|
293
358
|
end
|
294
|
-
|
359
|
+
end
|
360
|
+
end
|
361
|
+
```
|
295
362
|
The methods `has_avatar_upload?`, `remote_avatar_net_url` and `has_remote_avatar_net_url?` are automatically added to your mounted model
|
296
363
|
|
297
364
|
## Validations
|
298
365
|
|
299
366
|
Along with validating the extension of the filename, CarrierWaveDirect also gives you some other validations:
|
300
367
|
|
301
|
-
|
368
|
+
```ruby
|
369
|
+
validates :avatar :is_uploaded => true
|
370
|
+
```
|
302
371
|
|
303
372
|
Validates that your mounted model has an avatar uploaded from file or specified by remote url. It does not check that an your mounted model actually has a valid avatar after the download has taken place. Turned *off* by default
|
304
373
|
|
305
|
-
|
374
|
+
```ruby
|
375
|
+
validates :avatar, :is_attached => true
|
376
|
+
```
|
306
377
|
|
307
378
|
Validates that your mounted model has an avatar attached. This checks whether there is an actual avatar attached to the mounted model after downloading. Turned *off* by default
|
308
379
|
|
309
|
-
|
380
|
+
```ruby
|
381
|
+
validates :avatar, :filename_uniqueness => true
|
382
|
+
```
|
310
383
|
|
311
384
|
Validates that the filename in the database is unique. Turned *on* by default
|
312
385
|
|
313
|
-
|
386
|
+
```ruby
|
387
|
+
validates :avatar, :filename_format => true
|
388
|
+
```
|
314
389
|
|
315
390
|
Validates that the uploaded filename is valid. As well as validating the extension against the `extension_white_list` it also validates that the `upload_dir` is correct. Turned *on* by default
|
316
391
|
|
317
|
-
|
392
|
+
```ruby
|
393
|
+
validates :avatar, :remote_net_url_format => true
|
394
|
+
```
|
318
395
|
|
319
396
|
Validates that the remote net url is valid. As well as validating the extension against the `extension_white_list` it also validates that url is valid and has only the schemes specified in the `url_scheme_whitelist`. Turned *on* by default
|
320
397
|
|
@@ -322,60 +399,71 @@ Validates that the remote net url is valid. As well as validating the extension
|
|
322
399
|
|
323
400
|
As well as the built in validations CarrierWaveDirect provides, some validations, such as max file size and upload expiration can be performed on the S3 side.
|
324
401
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
402
|
+
```ruby
|
403
|
+
CarrierWave.configure do |config|
|
404
|
+
config.validate_is_attached = true # defaults to false
|
405
|
+
config.validate_is_uploaded = true # defaults to false
|
406
|
+
config.validate_unique_filename = false # defaults to true
|
407
|
+
config.validate_filename_format = false # defaults to true
|
408
|
+
config.validate_remote_net_url_format = false # defaults to true
|
409
|
+
|
410
|
+
config.min_file_size = 5.kilobytes # defaults to 1.byte
|
411
|
+
config.max_file_size = 10.megabytes # defaults to 5.megabytes
|
412
|
+
config.upload_expiration = 1.hour # defaults to 10.hours
|
413
|
+
config.will_include_content_type = true # defaults to false; if true, content-type will be set
|
414
|
+
# on s3, but you must include an input field named
|
415
|
+
# Content-Type on every direct upload form
|
416
|
+
end
|
417
|
+
```
|
340
418
|
## Testing with CarrierWaveDirect
|
341
419
|
|
342
420
|
CarrierWaveDirect provides a couple of helpers to help with integration and unit testing. You don't want to contact the Internet during your tests as this is slow, expensive and unreliable. You should first put fog into mock mode by doing something like this.
|
343
421
|
|
344
|
-
|
422
|
+
```ruby
|
423
|
+
Fog.mock!
|
345
424
|
|
346
|
-
|
347
|
-
|
348
|
-
|
425
|
+
def fog_directory
|
426
|
+
ENV['AWS_FOG_DIRECTORY']
|
427
|
+
end
|
349
428
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
429
|
+
connection = ::Fog::Storage.new(
|
430
|
+
:aws_access_key_id => ENV['AWS_ACCESS_KEY_ID'],
|
431
|
+
:aws_secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'],
|
432
|
+
:provider => 'AWS'
|
433
|
+
)
|
355
434
|
|
356
|
-
|
435
|
+
connection.directories.create(:key => fog_directory)
|
436
|
+
```
|
357
437
|
|
358
438
|
### Using Capybara
|
359
439
|
|
360
|
-
If
|
440
|
+
If you're using Capybara with Cucumber or RSpec, CarrierWaveDirect gives you a few useful helpers. To get the Capybara helpers, include the module into your test file or helper
|
361
441
|
|
362
|
-
|
363
|
-
|
364
|
-
|
442
|
+
```ruby
|
443
|
+
describe AvatarUploadSpec
|
444
|
+
include CarrierWaveDirect::Test::CapybaraHelpers
|
445
|
+
end
|
446
|
+
```
|
365
447
|
|
366
448
|
To attach a file to the direct upload form you can use
|
367
449
|
|
368
|
-
|
450
|
+
```ruby
|
451
|
+
attach_file_for_direct_upload('path/to/file.ext')
|
452
|
+
```
|
369
453
|
|
370
454
|
To simulate a successful upload and redirect to S3 you can use
|
371
455
|
|
372
|
-
|
456
|
+
```ruby
|
457
|
+
upload_directly(AvatarUploader.new, "Upload to S3")
|
458
|
+
```
|
373
459
|
|
374
460
|
This will click the Upload to S3 button on the form and redirect you to the `success_action_redirect` url (in the form) with a sample response from S3
|
375
461
|
|
376
462
|
To simulate an unsuccessful upload you can pass `:success => false` and you'll remain on the upload page e.g.
|
377
463
|
|
378
|
-
|
464
|
+
```ruby
|
465
|
+
upload_directly(AvatarUploader.new, "Upload to S3", :success => false)
|
466
|
+
```
|
379
467
|
|
380
468
|
You can also use `find_key` and `find_upload_path` to get the key and upload path from the form
|
381
469
|
|
@@ -383,12 +471,14 @@ You can also use `find_key` and `find_upload_path` to get the key and upload pat
|
|
383
471
|
|
384
472
|
If your mounted model validates a file is uploaded you might want to make use of the `sample_key` method
|
385
473
|
|
386
|
-
|
474
|
+
```ruby
|
475
|
+
include CarrierWaveDirect::Test::Helpers
|
387
476
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
477
|
+
Factory.define :user |f|
|
478
|
+
f.email "some1@example.com"
|
479
|
+
f.key { sample_key(AvatarUploader.new) }
|
480
|
+
end
|
481
|
+
```
|
392
482
|
|
393
483
|
This will return a valid key based off your `upload_dir` and your `extension_white_list`
|
394
484
|
|
@@ -396,30 +486,34 @@ This will return a valid key based off your `upload_dir` and your `extension_whi
|
|
396
486
|
|
397
487
|
If you wanted to fake a download in the background you could do something like this
|
398
488
|
|
399
|
-
|
489
|
+
```ruby
|
490
|
+
uploader = AvatarUploader.new
|
400
491
|
|
401
|
-
|
402
|
-
|
492
|
+
upload_path = find_upload_path
|
493
|
+
redirect_key = sample_key(:base => find_key, :filename => File.basename(upload_path))
|
403
494
|
|
404
|
-
|
405
|
-
|
495
|
+
uploader.key = redirect_key
|
496
|
+
download_url = uploader.direct_fog_url(:with_path => true)
|
406
497
|
|
407
|
-
|
408
|
-
|
498
|
+
# Register the download url and return the uploaded file in the body
|
499
|
+
FakeWeb.register_uri(:get, download_url, :body => File.open(upload_path))
|
500
|
+
```
|
409
501
|
|
410
502
|
## i18n
|
411
503
|
|
412
504
|
The Active Record validations use the Rails i18n framework. Add these keys to your translations file:
|
413
505
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
506
|
+
```yml
|
507
|
+
en:
|
508
|
+
errors:
|
509
|
+
messages:
|
510
|
+
carrierwave_direct_filename_taken: filename was already taken
|
511
|
+
carrierwave_direct_upload_missing: upload is missing
|
512
|
+
carrierwave_direct_attachment_missing: attachment is missing
|
513
|
+
carrierwave_direct_filename_invalid: "is invalid. "
|
514
|
+
carrierwave_direct_allowed_extensions: Allowed file types are %{extensions}
|
515
|
+
carrierwave_direct_allowed_schemes: Allowed schemes are %{schemes}
|
516
|
+
```
|
423
517
|
|
424
518
|
## Caveats
|
425
519
|
|
@@ -442,6 +536,10 @@ You should now be able to run the tests
|
|
442
536
|
|
443
537
|
After you have fixed a bug or added a feature please also use the [CarrierWaveDirect Sample Application](https://github.com/dwilkie/carrierwave_direct_example) to ensure that the gem still works correctly.
|
444
538
|
|
539
|
+
## Credits
|
540
|
+
|
541
|
+
Thank you to everybody who has contributed to [CarrierWaveDirect](https://github.com/dwilkie/carrierwave_direct). A special thanks to [colinyoung (Colin Young)](https://github.com/colinyoung) and [nddeluca (Nicholas DeLuca)](https://github.com/nddeluca) who help maintain the gem.
|
542
|
+
|
445
543
|
## Contributors
|
446
544
|
|
447
545
|
* [cblunt (Chris Blunt)](https://github.com/cblunt) - Support for passing html options
|
@@ -4,13 +4,19 @@ module CarrierWaveDirect
|
|
4
4
|
class FormBuilder < ActionView::Helpers::FormBuilder
|
5
5
|
def file_field(method, options = {})
|
6
6
|
options.merge!(:name => "file")
|
7
|
-
hidden_field(:key,
|
8
|
-
hidden_field(:aws_access_key_id,
|
9
|
-
hidden_field(:acl,
|
10
|
-
hidden_field(:
|
11
|
-
hidden_field(:
|
12
|
-
|
13
|
-
|
7
|
+
fields = hidden_field(:key, :name => "key")
|
8
|
+
fields << hidden_field(:aws_access_key_id, :name => "AWSAccessKeyId")
|
9
|
+
fields << hidden_field(:acl, :name => "acl")
|
10
|
+
fields << hidden_field(:policy, :name => "policy")
|
11
|
+
fields << hidden_field(:signature, :name => "signature")
|
12
|
+
|
13
|
+
if options[:use_action_status]
|
14
|
+
fields << hidden_field(:success_action_status, :name => "success_action_status")
|
15
|
+
else
|
16
|
+
fields << hidden_field(:success_action_redirect, :name => "success_action_redirect")
|
17
|
+
end
|
18
|
+
|
19
|
+
fields << super
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
@@ -11,6 +11,7 @@ module CarrierWaveDirect
|
|
11
11
|
storage :fog
|
12
12
|
|
13
13
|
attr_accessor :success_action_redirect
|
14
|
+
attr_accessor :success_action_status
|
14
15
|
|
15
16
|
fog_credentials.keys.each do |key|
|
16
17
|
define_method(key) do
|
@@ -41,8 +42,8 @@ module CarrierWaveDirect
|
|
41
42
|
|
42
43
|
def key
|
43
44
|
return @key if @key.present?
|
44
|
-
if
|
45
|
-
self.key = URI.parse(URI.encode(url)).path # explicitly set key
|
45
|
+
if present?
|
46
|
+
self.key = URI.parse(URI.encode(url)).path[1 .. -1] # explicitly set key
|
46
47
|
else
|
47
48
|
@key = "#{store_dir}/#{guid}/#{FILENAME_WILDCARD}"
|
48
49
|
end
|
@@ -62,18 +63,26 @@ module CarrierWaveDirect
|
|
62
63
|
options[:min_file_size] ||= self.class.min_file_size
|
63
64
|
options[:max_file_size] ||= self.class.max_file_size
|
64
65
|
|
65
|
-
conditions = [
|
66
|
+
conditions = [
|
67
|
+
["starts-with", "$utf8", ""],
|
68
|
+
["starts-with", "$key", key.sub(/#{Regexp.escape(FILENAME_WILDCARD)}\z/, "")]
|
69
|
+
]
|
66
70
|
conditions << ["starts-with", "$Content-Type", ""] if self.class.will_include_content_type
|
71
|
+
conditions << {"bucket" => fog_directory}
|
72
|
+
conditions << {"acl" => acl}
|
73
|
+
|
74
|
+
if self.class.use_action_status
|
75
|
+
conditions << {"success_action_status" => success_action_status}
|
76
|
+
else
|
77
|
+
conditions << {"success_action_redirect" => success_action_redirect}
|
78
|
+
end
|
79
|
+
|
80
|
+
conditions << ["content-length-range", options[:min_file_size], options[:max_file_size]]
|
67
81
|
|
68
82
|
Base64.encode64(
|
69
83
|
{
|
70
84
|
'expiration' => Time.now.utc + options[:expiration],
|
71
|
-
'conditions' => conditions
|
72
|
-
{"bucket" => fog_directory},
|
73
|
-
{"acl" => acl},
|
74
|
-
{"success_action_redirect" => success_action_redirect},
|
75
|
-
["content-length-range", options[:min_file_size], options[:max_file_size]]
|
76
|
-
]
|
85
|
+
'conditions' => conditions
|
77
86
|
}.to_json
|
78
87
|
).gsub("\n","")
|
79
88
|
end
|
@@ -17,6 +17,9 @@ module CarrierWaveDirect
|
|
17
17
|
add_config :max_file_size
|
18
18
|
add_config :upload_expiration
|
19
19
|
add_config :will_include_content_type
|
20
|
+
|
21
|
+
add_config :use_action_status
|
22
|
+
|
20
23
|
reset_direct_config
|
21
24
|
end
|
22
25
|
|
@@ -32,6 +35,8 @@ module CarrierWaveDirect
|
|
32
35
|
config.min_file_size = 1
|
33
36
|
config.max_file_size = 5242880
|
34
37
|
config.upload_expiration = 36000
|
38
|
+
|
39
|
+
config.use_action_status = false
|
35
40
|
end
|
36
41
|
end
|
37
42
|
end
|
data/spec/form_builder_spec.rb
CHANGED
@@ -7,11 +7,15 @@ describe CarrierWaveDirect::FormBuilder do
|
|
7
7
|
|
8
8
|
describe "#file_field" do
|
9
9
|
|
10
|
-
def
|
10
|
+
def form_with_default_file_field
|
11
11
|
form {|f| f.file_field :video }
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
def form_with_file_field_and_no_redirect
|
15
|
+
form {|f| f.file_field :video, use_action_status: true }
|
16
|
+
end
|
17
|
+
|
18
|
+
default_hidden_fields = [
|
15
19
|
:key,
|
16
20
|
{:aws_access_key_id => "AWSAccessKeyId"},
|
17
21
|
:acl,
|
@@ -19,11 +23,40 @@ describe CarrierWaveDirect::FormBuilder do
|
|
19
23
|
:policy,
|
20
24
|
:signature
|
21
25
|
]
|
26
|
+
status_hidden_fields = [
|
27
|
+
:key,
|
28
|
+
{:aws_access_key_id => "AWSAccessKeyId"},
|
29
|
+
:acl,
|
30
|
+
:success_action_status,
|
31
|
+
:policy,
|
32
|
+
:signature
|
33
|
+
]
|
22
34
|
|
23
35
|
# http://aws.amazon.com/articles/1434?_encoding=UTF8
|
24
36
|
context "form" do
|
25
37
|
|
26
|
-
|
38
|
+
default_hidden_fields.each do |input|
|
39
|
+
if input.is_a?(Hash)
|
40
|
+
key = input.keys.first
|
41
|
+
name = input[key]
|
42
|
+
else
|
43
|
+
key = name = input
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should have a hidden field for '#{name}'" do
|
47
|
+
direct_uploader.stub(key).and_return(key.to_s)
|
48
|
+
form_with_default_file_field.should have_input(
|
49
|
+
:direct_uploader,
|
50
|
+
key,
|
51
|
+
:type => :hidden,
|
52
|
+
:name => name,
|
53
|
+
:value => key,
|
54
|
+
:required => false
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
status_hidden_fields.each do |input|
|
27
60
|
if input.is_a?(Hash)
|
28
61
|
key = input.keys.first
|
29
62
|
name = input[key]
|
@@ -33,7 +66,7 @@ describe CarrierWaveDirect::FormBuilder do
|
|
33
66
|
|
34
67
|
it "should have a hidden field for '#{name}'" do
|
35
68
|
direct_uploader.stub(key).and_return(key.to_s)
|
36
|
-
|
69
|
+
form_with_file_field_and_no_redirect.should have_input(
|
37
70
|
:direct_uploader,
|
38
71
|
key,
|
39
72
|
:type => :hidden,
|
@@ -45,7 +78,7 @@ describe CarrierWaveDirect::FormBuilder do
|
|
45
78
|
end
|
46
79
|
|
47
80
|
it "should have an input for a file to upload" do
|
48
|
-
|
81
|
+
form_with_default_file_field.should have_input(
|
49
82
|
:direct_uploader,
|
50
83
|
:video,
|
51
84
|
:type => :file,
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'action_view'
|
4
4
|
require 'action_view/template'
|
5
|
+
require 'action_controller'
|
6
|
+
require 'active_model'
|
5
7
|
|
6
8
|
require File.join(File.dirname(__FILE__), 'view_helpers')
|
7
9
|
|
@@ -12,7 +14,14 @@ module FormBuilderHelpers
|
|
12
14
|
include ActionView::Helpers::FormHelper
|
13
15
|
include CarrierWaveDirect::ActionViewExtensions::FormHelper
|
14
16
|
include ActionView::Context
|
15
|
-
|
17
|
+
|
18
|
+
# Try ActionView::RecrodIentifier for Rails 4
|
19
|
+
# else use ActionController::RecordIdentifier for Rails 3.2
|
20
|
+
begin
|
21
|
+
include ActionView::RecordIdentifier
|
22
|
+
rescue
|
23
|
+
include ActionController::RecordIdentifier
|
24
|
+
end
|
16
25
|
|
17
26
|
include ::ViewHelpers
|
18
27
|
|
data/spec/uploader_spec.rb
CHANGED
@@ -68,6 +68,12 @@ describe CarrierWaveDirect::Uploader do
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
describe ".use_action_status" do
|
72
|
+
it "should be false" do
|
73
|
+
subject.class.use_action_status.should be_false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
71
77
|
DirectUploader.fog_credentials.keys.each do |key|
|
72
78
|
describe "##{key}" do
|
73
79
|
it "should return the #{key.to_s.capitalize}" do
|
@@ -81,6 +87,7 @@ describe CarrierWaveDirect::Uploader do
|
|
81
87
|
end
|
82
88
|
|
83
89
|
it_should_have_accessor(:success_action_redirect)
|
90
|
+
it_should_have_accessor(:success_action_status)
|
84
91
|
|
85
92
|
describe "#key=" do
|
86
93
|
before { subject.key = sample(:key) }
|
@@ -118,17 +125,26 @@ describe CarrierWaveDirect::Uploader do
|
|
118
125
|
end
|
119
126
|
end
|
120
127
|
|
128
|
+
context "and the uploaders url is #default_url" do
|
129
|
+
it "should return '*/\#\{guid\}/${filename}'" do
|
130
|
+
mounted_subject.stub(:url).and_return(sample(:s3_file_url))
|
131
|
+
mounted_subject.stub(:present?).and_return(false)
|
132
|
+
mounted_subject.key.should =~ /#{GUID_REGEXP}\/\$\{filename\}$/
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
121
136
|
context "but the uploaders url is '#{sample(:s3_file_url)}'" do
|
122
137
|
before do
|
123
138
|
mounted_subject.stub(:url).and_return(sample(:s3_file_url))
|
139
|
+
mounted_subject.stub(:present?).and_return(true)
|
124
140
|
end
|
125
141
|
|
126
|
-
it "should return '
|
127
|
-
mounted_subject.key.should ==
|
142
|
+
it "should return '#{sample(:s3_key)}'" do
|
143
|
+
mounted_subject.key.should == sample(:s3_key)
|
128
144
|
end
|
129
145
|
|
130
146
|
it "should set the key explicitly in order to update the version keys" do
|
131
|
-
mounted_subject.should_receive("key=").with(
|
147
|
+
mounted_subject.should_receive("key=").with(sample(:s3_key))
|
132
148
|
mounted_subject.key
|
133
149
|
end
|
134
150
|
end
|
@@ -415,13 +431,18 @@ describe CarrierWaveDirect::Uploader do
|
|
415
431
|
|
416
432
|
# S3 conditions
|
417
433
|
it "'key'" do
|
418
|
-
mounted_subject.stub(:
|
419
|
-
mounted_subject.key
|
434
|
+
mounted_subject.stub(:key).and_return(sample(:s3_key))
|
420
435
|
conditions(
|
421
436
|
:subject => mounted_subject
|
422
437
|
).should have_condition(:key, sample(:s3_key))
|
423
438
|
end
|
424
439
|
|
440
|
+
it "'key' without FILENAME_WILDCARD" do
|
441
|
+
conditions(
|
442
|
+
:subject => mounted_subject
|
443
|
+
).should have_condition(:key, mounted_subject.key.sub("${filename}", ""))
|
444
|
+
end
|
445
|
+
|
425
446
|
it "'bucket'" do
|
426
447
|
conditions.should have_condition("bucket" => subject.fog_directory)
|
427
448
|
end
|
@@ -434,11 +455,31 @@ describe CarrierWaveDirect::Uploader do
|
|
434
455
|
subject.success_action_redirect = "http://example.com/some_url"
|
435
456
|
conditions.should have_condition("success_action_redirect" => "http://example.com/some_url")
|
436
457
|
end
|
437
|
-
|
458
|
+
|
438
459
|
it "'content-type' only if enabled" do
|
439
460
|
conditions.should have_condition('Content-Type') if subject.class.will_include_content_type
|
440
461
|
end
|
441
462
|
|
463
|
+
context 'when use_action_status is true' do
|
464
|
+
before(:all) do
|
465
|
+
DirectUploader.use_action_status = true
|
466
|
+
end
|
467
|
+
|
468
|
+
after(:all) do
|
469
|
+
DirectUploader.use_action_status = false
|
470
|
+
end
|
471
|
+
|
472
|
+
it "'success_action_status'" do
|
473
|
+
subject.success_action_status = '200'
|
474
|
+
conditions.should have_condition("success_action_status" => "200")
|
475
|
+
end
|
476
|
+
|
477
|
+
it "does not have 'success_action_redirect'" do
|
478
|
+
subject.success_action_redirect = "http://example.com/some_url"
|
479
|
+
conditions.should_not have_condition("success_action_redirect" => "http://example.com/some_url")
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
442
483
|
context "'content-length-range of'" do
|
443
484
|
def have_content_length_range(options = {})
|
444
485
|
include([
|
metadata
CHANGED
@@ -1,142 +1,125 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: carrierwave_direct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.13
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- David Wilkie
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-07-07 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: carrierwave
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: uuidtools
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: fog
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: rspec
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - '>='
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - '>='
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: timecop
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - '>='
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - '>='
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: rails
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - '>='
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: 3.2.12
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - '>='
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: 3.2.12
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: sqlite3
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
|
-
- -
|
101
|
+
- - '>='
|
116
102
|
- !ruby/object:Gem::Version
|
117
103
|
version: '0'
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
|
-
- -
|
108
|
+
- - '>='
|
124
109
|
- !ruby/object:Gem::Version
|
125
110
|
version: '0'
|
126
111
|
- !ruby/object:Gem::Dependency
|
127
112
|
name: capybara
|
128
113
|
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
114
|
requirements:
|
131
|
-
- -
|
115
|
+
- - '>='
|
132
116
|
- !ruby/object:Gem::Version
|
133
117
|
version: '0'
|
134
118
|
type: :development
|
135
119
|
prerelease: false
|
136
120
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
121
|
requirements:
|
139
|
-
- -
|
122
|
+
- - '>='
|
140
123
|
- !ruby/object:Gem::Version
|
141
124
|
version: '0'
|
142
125
|
description: Process your uploads in the background by uploading directly to S3
|
@@ -184,27 +167,26 @@ files:
|
|
184
167
|
- spec/uploader_spec.rb
|
185
168
|
homepage: https://github.com/dwilkie/carrierwave_direct
|
186
169
|
licenses: []
|
170
|
+
metadata: {}
|
187
171
|
post_install_message:
|
188
172
|
rdoc_options: []
|
189
173
|
require_paths:
|
190
174
|
- lib
|
191
175
|
required_ruby_version: !ruby/object:Gem::Requirement
|
192
|
-
none: false
|
193
176
|
requirements:
|
194
|
-
- -
|
177
|
+
- - '>='
|
195
178
|
- !ruby/object:Gem::Version
|
196
179
|
version: 1.9.0
|
197
180
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
198
|
-
none: false
|
199
181
|
requirements:
|
200
|
-
- -
|
182
|
+
- - '>='
|
201
183
|
- !ruby/object:Gem::Version
|
202
184
|
version: '0'
|
203
185
|
requirements: []
|
204
186
|
rubyforge_project: carrierwave_direct
|
205
|
-
rubygems_version:
|
187
|
+
rubygems_version: 2.0.3
|
206
188
|
signing_key:
|
207
|
-
specification_version:
|
189
|
+
specification_version: 4
|
208
190
|
summary: Upload direct to S3 using CarrierWave
|
209
191
|
test_files:
|
210
192
|
- spec/action_view_extensions/form_helper_spec.rb
|