uploadbox 0.0.7 → 0.0.8
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 +4 -4
- data/app/assets/javascripts/_image_uploader.coffee +59 -14
- data/app/assets/javascripts/cors/jquery.postmessage-transport.js +118 -0
- data/app/assets/javascripts/cors/jquery.xdr-transport.js +87 -0
- data/app/assets/javascripts/jquery.fileupload.js +23 -5
- data/app/assets/javascripts/jquery.iframe-transport.js +0 -0
- data/app/assets/javascripts/uploadbox.coffee +2 -0
- data/app/controllers/uploadbox/images_controller.rb +10 -2
- data/app/jobs/process_image.rb +9 -0
- data/app/models/image.rb +3 -3
- data/app/views/uploadbox/images/_uploader.html.slim +10 -1
- data/app/views/uploadbox/images/find.json.jbuilder +9 -0
- data/config/routes.rb +5 -1
- data/lib/generators/uploadbox/image/image_generator.rb +1 -2
- data/lib/generators/uploadbox/image/templates/initializers/uploadbox.rb +27 -0
- data/lib/generators/uploadbox/image/templates/migrate/create_images.rb +2 -1
- data/lib/heroku_resque_auto_scale.rb +65 -0
- data/lib/tasks/uploadbox_tasks.rake +6 -4
- data/lib/uploadbox/engine.rb +2 -0
- data/lib/uploadbox/image_uploader.rb +0 -11
- data/lib/uploadbox/version.rb +1 -1
- metadata +37 -6
- data/app/views/uploadbox/images/create.json.jbuilder +0 -7
- data/lib/generators/uploadbox/image/templates/initializers/carrierwave.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 605fe90f8d3f385da36ee21257ab2c4d6783b513
|
4
|
+
data.tar.gz: fcb1983a55e7e3c103c45271a10229e720fe35e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35a73a6ce9ed2127ecd4199833210d53036afe2a2989988ccca30c281545a066bbc537de43d9c67e4b2b00e6402392642d117b9532146dd870c69bf00292f584
|
7
|
+
data.tar.gz: 668beadd3a2ddf04cfbf1d4a88e4b499d7136c9284e5842d4d43e3539440e33b88225945659319aa1815d0f99339babcf2cc81729f003b7fe3b93a9434c58625
|
@@ -7,13 +7,13 @@ class @ImageUploader
|
|
7
7
|
@idInput = @container.find('[data-item="id"]')
|
8
8
|
@container.find('a.btn.fileupload-exists').bind('ajax:success', @delete)
|
9
9
|
@thumbContainer = @container.find('.fileupload-preview.thumbnail')
|
10
|
+
|
10
11
|
@fileInput.fileupload
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
]
|
12
|
+
type: 'POST'
|
13
|
+
dataType: 'xml'
|
14
|
+
replaceFileInput: false
|
15
|
+
autoUpload: true
|
16
|
+
formData: @getFormData
|
17
17
|
add: @add
|
18
18
|
progress: @progress
|
19
19
|
done: @done
|
@@ -23,12 +23,62 @@ class @ImageUploader
|
|
23
23
|
@preview.prepend(@loader.fadeIn())
|
24
24
|
data.submit()
|
25
25
|
|
26
|
+
getFormData: (arg) =>
|
27
|
+
file = @fileInput.get(0).files[0]
|
28
|
+
@filePath = @container.find('input[name="key"]').val() + file.name
|
29
|
+
[
|
30
|
+
{ name: 'key', value: @filePath },
|
31
|
+
{ name: 'acl', value: @container.find('input[name="acl"]').val() },
|
32
|
+
{ name: 'Content-Type', value: file.type },
|
33
|
+
{ name: 'AWSAccessKeyId', value: @container.find('input[name="AWSAccessKeyId"]').val() },
|
34
|
+
{ name: 'policy', value: @container.find('input[name="policy"]').val() },
|
35
|
+
{ name: 'signature', value: @container.find('input[name="signature"]').val() },
|
36
|
+
{ name: "file", value: file }
|
37
|
+
]
|
38
|
+
|
26
39
|
progress: (e, data) =>
|
27
40
|
progress = parseInt(data.loaded / data.total * 100, 10)
|
28
41
|
@loader.find('.bar').css({width: progress + '%'})
|
29
42
|
|
30
43
|
done: (e, data) =>
|
31
|
-
|
44
|
+
$.ajax
|
45
|
+
type: 'POST'
|
46
|
+
url: @fileInput.data('callback-url')
|
47
|
+
data:
|
48
|
+
'image[remote_file_url]': @fileInput.data('url') + @filePath
|
49
|
+
'image[imageable_type]': @typeInput.val()
|
50
|
+
'image[upload_name]': @uploadNameInput.val()
|
51
|
+
'image[secure_random]': @fileInput.data('secure-random')
|
52
|
+
complete: =>
|
53
|
+
@verifyProcessingInterval = setInterval(@verifyProcessing, 5000)
|
54
|
+
|
55
|
+
verifyProcessing: =>
|
56
|
+
arr = @filePath.split('/')
|
57
|
+
filename = arr[arr.length - 1]
|
58
|
+
$.ajax
|
59
|
+
type: 'GET'
|
60
|
+
dataType: 'json'
|
61
|
+
url: @fileInput.data('find-url')
|
62
|
+
data:
|
63
|
+
'name': filename
|
64
|
+
'imageable_type': @typeInput.val()
|
65
|
+
'upload_name': @uploadNameInput.val()
|
66
|
+
'secure_random': @fileInput.data('secure-random')
|
67
|
+
|
68
|
+
complete: (data) =>
|
69
|
+
if data.responseJSON.hasOwnProperty('id')
|
70
|
+
clearInterval(@verifyProcessingInterval)
|
71
|
+
@showThumb(data.responseJSON)
|
72
|
+
|
73
|
+
delete: =>
|
74
|
+
@idInput.val('')
|
75
|
+
@container.find('.fileupload-preview.thumbnail img').detach()
|
76
|
+
@container.find('.fileupload').addClass('fileupload-new').removeClass('fileupload-exists')
|
77
|
+
|
78
|
+
fail: (e, data) =>
|
79
|
+
console.log('fail')
|
80
|
+
|
81
|
+
showThumb: (image) =>
|
32
82
|
@loader.detach()
|
33
83
|
@idInput.val(image.id)
|
34
84
|
@container.find('a.btn.fileupload-exists').attr('href', image.url)
|
@@ -36,16 +86,11 @@ class @ImageUploader
|
|
36
86
|
img = $('<img/>')
|
37
87
|
img.attr('src', image.versions[@thumbContainer.data('version')])
|
38
88
|
img.attr('width', @thumbContainer.data('width'))
|
39
|
-
img.attr('height', @thumbContainer.data('height'))
|
40
|
-
@container.find('.fileupload-preview.thumbnail').append(img)
|
89
|
+
img.attr('height', @thumbContainer.data('height')).hide()
|
90
|
+
@container.find('.fileupload-preview.thumbnail').append(img.fadeIn())
|
41
91
|
@container.find('.fileupload').removeClass('fileupload-new').addClass('fileupload-exists')
|
42
92
|
|
43
|
-
delete: =>
|
44
|
-
@idInput.val('')
|
45
|
-
@container.find('.fileupload-preview.thumbnail img').detach()
|
46
|
-
@container.find('.fileupload').addClass('fileupload-new').removeClass('fileupload-exists')
|
47
93
|
|
48
94
|
$ ->
|
49
95
|
$('[data-component="ImageUploader"]').each (i, el) ->
|
50
96
|
$(el).data('image_uploader', new ImageUploader($(el)))
|
51
|
-
|
@@ -0,0 +1,118 @@
|
|
1
|
+
/*
|
2
|
+
* jQuery postMessage Transport Plugin 1.1.1
|
3
|
+
* https://github.com/blueimp/jQuery-File-Upload
|
4
|
+
*
|
5
|
+
* Copyright 2011, Sebastian Tschan
|
6
|
+
* https://blueimp.net
|
7
|
+
*
|
8
|
+
* Licensed under the MIT license:
|
9
|
+
* http://www.opensource.org/licenses/MIT
|
10
|
+
*/
|
11
|
+
|
12
|
+
/*jslint unparam: true, nomen: true */
|
13
|
+
/*global define, window, document */
|
14
|
+
|
15
|
+
(function (factory) {
|
16
|
+
'use strict';
|
17
|
+
if (typeof define === 'function' && define.amd) {
|
18
|
+
// Register as an anonymous AMD module:
|
19
|
+
define(['jquery'], factory);
|
20
|
+
} else {
|
21
|
+
// Browser globals:
|
22
|
+
factory(window.jQuery);
|
23
|
+
}
|
24
|
+
}(function ($) {
|
25
|
+
'use strict';
|
26
|
+
|
27
|
+
var counter = 0,
|
28
|
+
names = [
|
29
|
+
'accepts',
|
30
|
+
'cache',
|
31
|
+
'contents',
|
32
|
+
'contentType',
|
33
|
+
'crossDomain',
|
34
|
+
'data',
|
35
|
+
'dataType',
|
36
|
+
'headers',
|
37
|
+
'ifModified',
|
38
|
+
'mimeType',
|
39
|
+
'password',
|
40
|
+
'processData',
|
41
|
+
'timeout',
|
42
|
+
'traditional',
|
43
|
+
'type',
|
44
|
+
'url',
|
45
|
+
'username'
|
46
|
+
],
|
47
|
+
convert = function (p) {
|
48
|
+
return p;
|
49
|
+
};
|
50
|
+
|
51
|
+
$.ajaxSetup({
|
52
|
+
converters: {
|
53
|
+
'postmessage text': convert,
|
54
|
+
'postmessage json': convert,
|
55
|
+
'postmessage html': convert
|
56
|
+
}
|
57
|
+
});
|
58
|
+
|
59
|
+
$.ajaxTransport('postmessage', function (options) {
|
60
|
+
if (options.postMessage && window.postMessage) {
|
61
|
+
var iframe,
|
62
|
+
loc = $('<a>').prop('href', options.postMessage)[0],
|
63
|
+
target = loc.protocol + '//' + loc.host,
|
64
|
+
xhrUpload = options.xhr().upload;
|
65
|
+
return {
|
66
|
+
send: function (_, completeCallback) {
|
67
|
+
counter += 1;
|
68
|
+
var message = {
|
69
|
+
id: 'postmessage-transport-' + counter
|
70
|
+
},
|
71
|
+
eventName = 'message.' + message.id;
|
72
|
+
iframe = $(
|
73
|
+
'<iframe style="display:none;" src="' +
|
74
|
+
options.postMessage + '" name="' +
|
75
|
+
message.id + '"></iframe>'
|
76
|
+
).bind('load', function () {
|
77
|
+
$.each(names, function (i, name) {
|
78
|
+
message[name] = options[name];
|
79
|
+
});
|
80
|
+
message.dataType = message.dataType.replace('postmessage ', '');
|
81
|
+
$(window).bind(eventName, function (e) {
|
82
|
+
e = e.originalEvent;
|
83
|
+
var data = e.data,
|
84
|
+
ev;
|
85
|
+
if (e.origin === target && data.id === message.id) {
|
86
|
+
if (data.type === 'progress') {
|
87
|
+
ev = document.createEvent('Event');
|
88
|
+
ev.initEvent(data.type, false, true);
|
89
|
+
$.extend(ev, data);
|
90
|
+
xhrUpload.dispatchEvent(ev);
|
91
|
+
} else {
|
92
|
+
completeCallback(
|
93
|
+
data.status,
|
94
|
+
data.statusText,
|
95
|
+
{postmessage: data.result},
|
96
|
+
data.headers
|
97
|
+
);
|
98
|
+
iframe.remove();
|
99
|
+
$(window).unbind(eventName);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
});
|
103
|
+
iframe[0].contentWindow.postMessage(
|
104
|
+
message,
|
105
|
+
target
|
106
|
+
);
|
107
|
+
}).appendTo(document.body);
|
108
|
+
},
|
109
|
+
abort: function () {
|
110
|
+
if (iframe) {
|
111
|
+
iframe.remove();
|
112
|
+
}
|
113
|
+
}
|
114
|
+
};
|
115
|
+
}
|
116
|
+
});
|
117
|
+
|
118
|
+
}));
|
@@ -0,0 +1,87 @@
|
|
1
|
+
/*
|
2
|
+
* jQuery XDomainRequest Transport Plugin 1.1.3
|
3
|
+
* https://github.com/blueimp/jQuery-File-Upload
|
4
|
+
*
|
5
|
+
* Copyright 2011, Sebastian Tschan
|
6
|
+
* https://blueimp.net
|
7
|
+
*
|
8
|
+
* Licensed under the MIT license:
|
9
|
+
* http://www.opensource.org/licenses/MIT
|
10
|
+
*
|
11
|
+
* Based on Julian Aubourg's ajaxHooks xdr.js:
|
12
|
+
* https://github.com/jaubourg/ajaxHooks/
|
13
|
+
*/
|
14
|
+
|
15
|
+
/*jslint unparam: true */
|
16
|
+
/*global define, window, XDomainRequest */
|
17
|
+
|
18
|
+
(function (factory) {
|
19
|
+
'use strict';
|
20
|
+
if (typeof define === 'function' && define.amd) {
|
21
|
+
// Register as an anonymous AMD module:
|
22
|
+
define(['jquery'], factory);
|
23
|
+
} else {
|
24
|
+
// Browser globals:
|
25
|
+
factory(window.jQuery);
|
26
|
+
}
|
27
|
+
}(function ($) {
|
28
|
+
'use strict';
|
29
|
+
if (window.XDomainRequest && !$.support.cors) {
|
30
|
+
$.ajaxTransport(function (s) {
|
31
|
+
if (s.crossDomain && s.async) {
|
32
|
+
if (s.timeout) {
|
33
|
+
s.xdrTimeout = s.timeout;
|
34
|
+
delete s.timeout;
|
35
|
+
}
|
36
|
+
var xdr;
|
37
|
+
return {
|
38
|
+
send: function (headers, completeCallback) {
|
39
|
+
var addParamChar = /\?/.test(s.url) ? '&' : '?';
|
40
|
+
function callback(status, statusText, responses, responseHeaders) {
|
41
|
+
xdr.onload = xdr.onerror = xdr.ontimeout = $.noop;
|
42
|
+
xdr = null;
|
43
|
+
completeCallback(status, statusText, responses, responseHeaders);
|
44
|
+
}
|
45
|
+
xdr = new XDomainRequest();
|
46
|
+
// XDomainRequest only supports GET and POST:
|
47
|
+
if (s.type === 'DELETE') {
|
48
|
+
s.url = s.url + addParamChar + '_method=DELETE';
|
49
|
+
s.type = 'POST';
|
50
|
+
} else if (s.type === 'PUT') {
|
51
|
+
s.url = s.url + addParamChar + '_method=PUT';
|
52
|
+
s.type = 'POST';
|
53
|
+
} else if (s.type === 'PATCH') {
|
54
|
+
s.url = s.url + addParamChar + '_method=PATCH';
|
55
|
+
s.type = 'POST';
|
56
|
+
}
|
57
|
+
xdr.open(s.type, s.url);
|
58
|
+
xdr.onload = function () {
|
59
|
+
callback(
|
60
|
+
200,
|
61
|
+
'OK',
|
62
|
+
{text: xdr.responseText},
|
63
|
+
'Content-Type: ' + xdr.contentType
|
64
|
+
);
|
65
|
+
};
|
66
|
+
xdr.onerror = function () {
|
67
|
+
callback(404, 'Not Found');
|
68
|
+
};
|
69
|
+
if (s.xdrTimeout) {
|
70
|
+
xdr.ontimeout = function () {
|
71
|
+
callback(0, 'timeout');
|
72
|
+
};
|
73
|
+
xdr.timeout = s.xdrTimeout;
|
74
|
+
}
|
75
|
+
xdr.send((s.hasContent && s.data) || null);
|
76
|
+
},
|
77
|
+
abort: function () {
|
78
|
+
if (xdr) {
|
79
|
+
xdr.onerror = $.noop();
|
80
|
+
xdr.abort();
|
81
|
+
}
|
82
|
+
}
|
83
|
+
};
|
84
|
+
}
|
85
|
+
});
|
86
|
+
}
|
87
|
+
}));
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* jQuery File Upload Plugin 5.
|
2
|
+
* jQuery File Upload Plugin 5.32.3
|
3
3
|
* https://github.com/blueimp/jQuery-File-Upload
|
4
4
|
*
|
5
5
|
* Copyright 2010, Sebastian Tschan
|
@@ -27,6 +27,18 @@
|
|
27
27
|
}(function ($) {
|
28
28
|
'use strict';
|
29
29
|
|
30
|
+
// Detect file input support, based on
|
31
|
+
// http://viljamis.com/blog/2012/file-upload-support-on-mobile/
|
32
|
+
$.support.fileInput = !(new RegExp(
|
33
|
+
// Handle devices which give false positives for the feature detection:
|
34
|
+
'(Android (1\\.[0156]|2\\.[01]))' +
|
35
|
+
'|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' +
|
36
|
+
'|(w(eb)?OSBrowser)|(webOS)' +
|
37
|
+
'|(Kindle/(1\\.0|2\\.[05]|3\\.0))'
|
38
|
+
).test(window.navigator.userAgent) ||
|
39
|
+
// Feature detection for all other devices:
|
40
|
+
$('<input type="file">').prop('disabled'));
|
41
|
+
|
30
42
|
// The FileReader API is not actually used, but works as feature detection,
|
31
43
|
// as e.g. Safari supports XHR file uploads via the FormData API,
|
32
44
|
// but not non-multipart XHR file uploads:
|
@@ -387,7 +399,7 @@
|
|
387
399
|
// Ignore non-multipart setting if not supported:
|
388
400
|
multipart = options.multipart || !$.support.xhrFileUpload,
|
389
401
|
paramName = options.paramName[0];
|
390
|
-
options.headers = options.headers
|
402
|
+
options.headers = $.extend({}, options.headers);
|
391
403
|
if (options.contentRange) {
|
392
404
|
options.headers['Content-Range'] = options.contentRange;
|
393
405
|
}
|
@@ -1153,9 +1165,11 @@
|
|
1153
1165
|
paste: this._onPaste
|
1154
1166
|
});
|
1155
1167
|
}
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1168
|
+
if ($.support.fileInput) {
|
1169
|
+
this._on(this.options.fileInput, {
|
1170
|
+
change: this._onChange
|
1171
|
+
});
|
1172
|
+
}
|
1159
1173
|
},
|
1160
1174
|
|
1161
1175
|
_destroyEventHandlers: function () {
|
@@ -1289,6 +1303,10 @@
|
|
1289
1303
|
if (aborted) {
|
1290
1304
|
return;
|
1291
1305
|
}
|
1306
|
+
if (!files.length) {
|
1307
|
+
dfd.reject();
|
1308
|
+
return;
|
1309
|
+
}
|
1292
1310
|
data.files = files;
|
1293
1311
|
jqXHR = that._onSend(null, data).then(
|
1294
1312
|
function (result, textStatus, jqXHR) {
|
File without changes
|
@@ -3,7 +3,15 @@ module Uploadbox
|
|
3
3
|
layout false
|
4
4
|
|
5
5
|
def create
|
6
|
-
|
6
|
+
Resque.enqueue(ProcessImage, image_params)
|
7
|
+
render nothing: true
|
8
|
+
end
|
9
|
+
|
10
|
+
def find
|
11
|
+
params[:imageable_type].constantize # load class
|
12
|
+
|
13
|
+
upload_class_name = params[:imageable_type] + params[:upload_name].camelize
|
14
|
+
@image = Uploadbox.const_get(upload_class_name).find_by(secure_random: params[:secure_random], file: params[:name])
|
7
15
|
end
|
8
16
|
|
9
17
|
def destroy
|
@@ -12,7 +20,7 @@ module Uploadbox
|
|
12
20
|
|
13
21
|
private
|
14
22
|
def image_params
|
15
|
-
params.require(:image).permit(:
|
23
|
+
params.require(:image).permit(:remote_file_url, :imageable_type, :upload_name, :secure_random)
|
16
24
|
end
|
17
25
|
end
|
18
26
|
end
|
data/app/models/image.rb
CHANGED
@@ -2,10 +2,10 @@ class Image < ActiveRecord::Base
|
|
2
2
|
belongs_to :imageable, polymorphic: true
|
3
3
|
|
4
4
|
def self.create_upload(attributes)
|
5
|
-
attributes[
|
5
|
+
attributes["imageable_type"].constantize # load class
|
6
6
|
|
7
|
-
upload_class_name = attributes[
|
8
|
-
attributes.delete(
|
7
|
+
upload_class_name = attributes["imageable_type"] + attributes["upload_name"].camelize
|
8
|
+
attributes.delete("upload_name")
|
9
9
|
Uploadbox.const_get(upload_class_name).create!(attributes)
|
10
10
|
end
|
11
11
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
= form.fields_for :image do
|
2
|
+
- secure_random = SecureRandom.uuid
|
2
3
|
.uploadbox-image-uploader data-component="ImageUploader"
|
3
4
|
- if namespace
|
4
5
|
input name="[#{namespace}]#{upload_name}_id" data-item="id" type="hidden" value="#{resource.send(upload_name).try :id}"
|
@@ -10,11 +11,19 @@
|
|
10
11
|
= img resource.send(upload_name).send(version)
|
11
12
|
- elsif default
|
12
13
|
= image_tag default, width: width, height: height
|
14
|
+
|
13
15
|
.fileupload-actions
|
14
16
|
span.btn.btn-file
|
15
17
|
span.fileupload-new = choose_label
|
16
18
|
span.fileupload-exists = update_label
|
17
|
-
|
19
|
+
|
20
|
+
input type="file" name="image[file]" data-callback-url="#{uploadbox.images_path}" data-find-url="#{uploadbox.find_images_path(format: :json)}" data-url="https://#{ENV['S3_BUCKET']}.s3.amazonaws.com/" data-secure-random="#{secure_random}"
|
21
|
+
input type="hidden" name="policy" value="#{policy}"
|
22
|
+
input type="hidden" name="signature" value="#{signature}"
|
23
|
+
input type="hidden" name="AWSAccessKeyId" value="#{ENV['S3_KEY']}"
|
24
|
+
input type="hidden" name="acl" value="public-read"
|
25
|
+
input type="hidden" name="key" value="uploads/#{secure_random}/"
|
26
|
+
|
18
27
|
input type="hidden" name="image[imageable_type]" value="#{resource.class}"
|
19
28
|
input type="hidden" name="image[upload_name]" value="#{upload_name}"
|
20
29
|
- if removable
|
data/config/routes.rb
CHANGED
@@ -5,14 +5,13 @@ module Uploadbox
|
|
5
5
|
source_root File.expand_path('../templates', __FILE__)
|
6
6
|
|
7
7
|
def create_initializers
|
8
|
-
copy_file 'initializers/carrierwave.rb', 'config/initializers/carrierwave.rb'
|
9
8
|
copy_file 'initializers/uploadbox.rb', 'config/initializers/uploadbox.rb'
|
10
9
|
end
|
11
10
|
|
12
11
|
def update_gitignore
|
13
12
|
return unless File.exist?('.gitignore')
|
14
13
|
|
15
|
-
append_to_file '.gitignore',
|
14
|
+
append_to_file '.gitignore', "\npublic/uploads"
|
16
15
|
end
|
17
16
|
|
18
17
|
def create_migration
|
@@ -2,3 +2,30 @@ Uploadbox.retina = true
|
|
2
2
|
Uploadbox.retina_quality = 30
|
3
3
|
Uploadbox.image_quality = 70
|
4
4
|
|
5
|
+
if Rails.env.production?
|
6
|
+
REDIS = Redis.connect url: ENV["OPENREDIS_URL"]
|
7
|
+
Resque.redis = REDIS
|
8
|
+
end
|
9
|
+
|
10
|
+
if Rails.env.production?
|
11
|
+
CarrierWave.configure do |config|
|
12
|
+
config.storage = :fog
|
13
|
+
|
14
|
+
config.fog_credentials = {
|
15
|
+
provider: 'AWS',
|
16
|
+
aws_access_key_id: ENV['S3_KEY'],
|
17
|
+
aws_secret_access_key: ENV['S3_SECRET'],
|
18
|
+
region: ENV['S3_REGION']
|
19
|
+
}
|
20
|
+
|
21
|
+
config.fog_directory = ENV['S3_BUCKET']
|
22
|
+
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if Rails.env.test?
|
27
|
+
CarrierWave.configure do |config|
|
28
|
+
config.storage :file
|
29
|
+
config.enable_processing = false
|
30
|
+
end
|
31
|
+
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
class CreateImages < ActiveRecord::Migration
|
2
2
|
def change
|
3
3
|
create_table :images do |t|
|
4
|
-
t.string :file
|
4
|
+
t.string :file, index: true
|
5
5
|
t.references :imageable, polymorphic: true, index: true
|
6
6
|
t.integer :width
|
7
7
|
t.integer :height
|
8
8
|
t.boolean :retina, default: false
|
9
9
|
t.string :upload_name
|
10
|
+
t.string :secure_random, index: true
|
10
11
|
|
11
12
|
t.timestamps
|
12
13
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'heroku-api'
|
2
|
+
|
3
|
+
module HerokuResqueAutoScale
|
4
|
+
if Rails.env.production?
|
5
|
+
module Scaler
|
6
|
+
class << self
|
7
|
+
@@heroku = Heroku::API.new(api_key: ENV['HEROKU_API_KEY'])
|
8
|
+
|
9
|
+
def workers
|
10
|
+
@@heroku.get_ps(ENV['HEROKU_APP']).body.count { |a| a["process"] =~ /worker/ }
|
11
|
+
end
|
12
|
+
|
13
|
+
def workers=(qty)
|
14
|
+
@@heroku.post_ps_scale(ENV['HEROKU_APP'], 'worker', qty)
|
15
|
+
end
|
16
|
+
|
17
|
+
def job_count
|
18
|
+
Resque.info[:pending].to_i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def after_perform_scale_down(*args)
|
24
|
+
# Nothing fancy, just shut everything down if we have no jobs
|
25
|
+
Scaler.workers = 0 if Scaler.job_count.zero?
|
26
|
+
end
|
27
|
+
|
28
|
+
def after_enqueue_scale_up(*args)
|
29
|
+
[
|
30
|
+
{
|
31
|
+
:workers => 1, # This many workers
|
32
|
+
:job_count => 1 # For this many jobs or more, until the next level
|
33
|
+
},
|
34
|
+
{
|
35
|
+
:workers => 2,
|
36
|
+
:job_count => 5
|
37
|
+
},
|
38
|
+
{
|
39
|
+
:workers => 3,
|
40
|
+
:job_count => 15
|
41
|
+
},
|
42
|
+
{
|
43
|
+
:workers => 4,
|
44
|
+
:job_count => 20
|
45
|
+
},
|
46
|
+
{
|
47
|
+
:workers => 5,
|
48
|
+
:job_count => 25
|
49
|
+
}
|
50
|
+
].reverse_each do |scale_info|
|
51
|
+
# Run backwards so it gets set to the highest value first
|
52
|
+
# Otherwise if there were 70 jobs, it would get set to 1, then 2, then 3, etc
|
53
|
+
|
54
|
+
# If we have a job count greater than or equal to the job limit for this scale info
|
55
|
+
if Scaler.job_count >= scale_info[:job_count]
|
56
|
+
# Set the number of workers unless they are already set to a level we want. Don't scale down here!
|
57
|
+
if Scaler.workers <= scale_info[:workers]
|
58
|
+
Scaler.workers = scale_info[:workers]
|
59
|
+
end
|
60
|
+
break # We've set or ensured that the worker count is high enough
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
require "resque/tasks"
|
2
|
+
task "resque:setup" => :environment do
|
3
|
+
ENV['QUEUE'] ||= '*'
|
4
|
+
end
|
5
|
+
desc "Alias for resque:work (To run workers on Heroku)"
|
6
|
+
task "jobs:work" => "resque:work"
|
data/lib/uploadbox/engine.rb
CHANGED
@@ -51,17 +51,6 @@ module Uploadbox
|
|
51
51
|
options[:removable]
|
52
52
|
end
|
53
53
|
|
54
|
-
# Uploadbox::PostPicture < Image
|
55
|
-
# upload_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
56
|
-
# def self.versions
|
57
|
-
# #{upload_versions}
|
58
|
-
# end
|
59
|
-
|
60
|
-
# def self.removable?
|
61
|
-
# #{options[:removable]}
|
62
|
-
# end
|
63
|
-
# RUBY
|
64
|
-
|
65
54
|
upload_class.instance_eval do
|
66
55
|
delegate *upload_versions.keys, to: :file
|
67
56
|
|
data/lib/uploadbox/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uploadbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julio Protzek
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-10-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -73,14 +73,14 @@ dependencies:
|
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: 1.
|
76
|
+
version: 1.15.0
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - ~>
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: 1.
|
83
|
+
version: 1.15.0
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: carrierwave
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,6 +137,34 @@ dependencies:
|
|
137
137
|
- - ~>
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: 1.5.0
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: resque
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ~>
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 1.25.0
|
147
|
+
type: :runtime
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ~>
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 1.25.0
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: heroku-api
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ~>
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: 0.3.15
|
161
|
+
type: :runtime
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ~>
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: 0.3.15
|
140
168
|
- !ruby/object:Gem::Dependency
|
141
169
|
name: jquery-rails
|
142
170
|
requirement: !ruby/object:Gem::Requirement
|
@@ -300,6 +328,8 @@ extensions: []
|
|
300
328
|
extra_rdoc_files: []
|
301
329
|
files:
|
302
330
|
- app/assets/javascripts/_image_uploader.coffee
|
331
|
+
- app/assets/javascripts/cors/jquery.postmessage-transport.js
|
332
|
+
- app/assets/javascripts/cors/jquery.xdr-transport.js
|
303
333
|
- app/assets/javascripts/jquery.fileupload.js
|
304
334
|
- app/assets/javascripts/jquery.iframe-transport.js
|
305
335
|
- app/assets/javascripts/jquery.ui.widget.js
|
@@ -310,19 +340,20 @@ files:
|
|
310
340
|
- app/controllers/uploadbox/images_controller.rb
|
311
341
|
- app/helpers/uploadbox/application_helper.rb
|
312
342
|
- app/helpers/uploadbox/img_helper.rb
|
343
|
+
- app/jobs/process_image.rb
|
313
344
|
- app/models/image.rb
|
314
345
|
- app/uploaders/uploadbox/image_processing_uploader.rb
|
315
346
|
- app/views/layouts/uploadbox/application.html.erb
|
316
347
|
- app/views/uploadbox/images/_uploader.html.slim
|
317
|
-
- app/views/uploadbox/images/
|
348
|
+
- app/views/uploadbox/images/find.json.jbuilder
|
318
349
|
- config/routes.rb
|
319
350
|
- lib/form_builder.rb
|
320
351
|
- lib/generators/uploadbox/image/image_generator.rb
|
321
|
-
- lib/generators/uploadbox/image/templates/initializers/carrierwave.rb
|
322
352
|
- lib/generators/uploadbox/image/templates/initializers/uploadbox.rb
|
323
353
|
- lib/generators/uploadbox/image/templates/migrate/create_images.rb
|
324
354
|
- lib/generators/uploadbox/image/templates/models/image.rb
|
325
355
|
- lib/generators/uploadbox/image/USAGE
|
356
|
+
- lib/heroku_resque_auto_scale.rb
|
326
357
|
- lib/tasks/uploadbox_tasks.rake
|
327
358
|
- lib/uploadbox/engine.rb
|
328
359
|
- lib/uploadbox/image_uploader.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
if Rails.env.production?
|
2
|
-
CarrierWave.configure do |config|
|
3
|
-
config.storage = :fog
|
4
|
-
|
5
|
-
config.fog_credentials = {
|
6
|
-
provider: 'AWS',
|
7
|
-
aws_access_key_id: ENV['S3_KEY'],
|
8
|
-
aws_secret_access_key: ENV['S3_SECRET'],
|
9
|
-
region: ENV['S3_REGION']
|
10
|
-
}
|
11
|
-
|
12
|
-
config.fog_directory = ENV['S3_BUCKET']
|
13
|
-
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'}
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
if Rails.env.test?
|
18
|
-
CarrierWave.configure do |config|
|
19
|
-
config.storage :file
|
20
|
-
config.enable_processing = false
|
21
|
-
end
|
22
|
-
end
|