progstr-filer 0.8.7 → 0.8.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.
- data/Gemfile +2 -2
- data/Gemfile.lock +48 -22
- data/Rakefile +0 -12
- data/VERSION +1 -1
- data/lib/filer/activerecord.rb +17 -6
- data/lib/filer/attachment.rb +75 -10
- data/lib/filer/config.rb +25 -3
- data/lib/filer/file_info.rb +0 -3
- data/lib/filer/uploader.rb +0 -1
- data/lib/filer/views/form_html.rb +23 -0
- data/lib/filer/views/html.rb +69 -0
- data/lib/progstr-filer.rb +2 -0
- data/test/{file_like.rb → file_mock.rb} +2 -2
- data/test/test_attachment_url.rb +12 -1
- data/test/test_file_mount.rb +22 -4
- data/test/test_helper.rb +1 -1
- data/test/test_http_upload.rb +2 -4
- data/test/test_id_generation.rb +3 -3
- data/test/test_upload_on_save.rb +26 -5
- data/test/test_validation.rb +5 -5
- metadata +44 -42
data/Gemfile
CHANGED
@@ -12,14 +12,14 @@ group :development do
|
|
12
12
|
gem "libnotify"
|
13
13
|
gem "shoulda", ">= 0"
|
14
14
|
#gem "rspec", "~> 2.3.0"
|
15
|
-
gem "bundler", "
|
15
|
+
gem "bundler", ">= 1.0.0"
|
16
16
|
gem "jeweler", "~> 1.6.4"
|
17
|
-
gem "rcov", ">= 0"
|
18
17
|
gem "rdoc", ">= 0"
|
19
18
|
end
|
20
19
|
|
21
20
|
gem "activerecord", ">=3.0.0"
|
22
21
|
gem "activemodel", ">=3.0.0"
|
22
|
+
gem "actionpack", ">=3.0.0"
|
23
23
|
gem "uuid"
|
24
24
|
gem "rest-client"
|
25
25
|
gem "multi_json"
|
data/Gemfile.lock
CHANGED
@@ -1,68 +1,94 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
|
5
|
-
|
4
|
+
actionpack (3.2.3)
|
5
|
+
activemodel (= 3.2.3)
|
6
|
+
activesupport (= 3.2.3)
|
6
7
|
builder (~> 3.0.0)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
erubis (~> 2.7.0)
|
9
|
+
journey (~> 1.0.1)
|
10
|
+
rack (~> 1.4.0)
|
11
|
+
rack-cache (~> 1.2)
|
12
|
+
rack-test (~> 0.6.1)
|
13
|
+
sprockets (~> 2.1.2)
|
14
|
+
activemodel (3.2.3)
|
15
|
+
activesupport (= 3.2.3)
|
16
|
+
builder (~> 3.0.0)
|
17
|
+
activerecord (3.2.3)
|
18
|
+
activemodel (= 3.2.3)
|
19
|
+
activesupport (= 3.2.3)
|
20
|
+
arel (~> 3.0.2)
|
12
21
|
tzinfo (~> 0.3.29)
|
13
|
-
activesupport (3.
|
22
|
+
activesupport (3.2.3)
|
23
|
+
i18n (~> 0.6)
|
14
24
|
multi_json (~> 1.0)
|
15
|
-
arel (
|
25
|
+
arel (3.0.2)
|
16
26
|
builder (3.0.0)
|
27
|
+
erubis (2.7.0)
|
17
28
|
ffi (1.0.11)
|
18
29
|
git (1.2.5)
|
19
|
-
guard (0.
|
30
|
+
guard (1.0.1)
|
20
31
|
ffi (>= 0.5.0)
|
21
32
|
thor (~> 0.14.6)
|
22
33
|
guard-test (0.4.3)
|
23
34
|
guard (>= 0.4)
|
24
35
|
test-unit (~> 2.2)
|
36
|
+
hike (1.2.1)
|
25
37
|
i18n (0.6.0)
|
26
38
|
jeweler (1.6.4)
|
27
39
|
bundler (~> 1.0)
|
28
40
|
git (>= 1.2.5)
|
29
41
|
rake
|
30
|
-
|
31
|
-
|
42
|
+
journey (1.0.3)
|
43
|
+
json (1.6.6)
|
44
|
+
libnotify (0.7.2)
|
32
45
|
macaddr (1.5.0)
|
33
46
|
systemu (>= 2.4.0)
|
34
|
-
mime-types (1.
|
35
|
-
multi_json (1.0
|
47
|
+
mime-types (1.18)
|
48
|
+
multi_json (1.3.0)
|
49
|
+
rack (1.4.1)
|
50
|
+
rack-cache (1.2)
|
51
|
+
rack (>= 0.4)
|
52
|
+
rack-test (0.6.1)
|
53
|
+
rack (>= 1.0)
|
36
54
|
rake (0.9.2.2)
|
37
55
|
rb-inotify (0.8.8)
|
38
56
|
ffi (>= 0.5.0)
|
39
|
-
rcov (0.9.11)
|
40
57
|
rdoc (3.12)
|
41
58
|
json (~> 1.4)
|
42
59
|
rest-client (1.6.7)
|
43
60
|
mime-types (>= 1.16)
|
44
|
-
shoulda (
|
61
|
+
shoulda (3.0.1)
|
62
|
+
shoulda-context (~> 1.0.0)
|
63
|
+
shoulda-matchers (~> 1.0.0)
|
64
|
+
shoulda-context (1.0.0)
|
65
|
+
shoulda-matchers (1.0.0)
|
66
|
+
sprockets (2.1.2)
|
67
|
+
hike (~> 1.2)
|
68
|
+
rack (~> 1.0)
|
69
|
+
tilt (~> 1.1, != 1.3.0)
|
45
70
|
sqlite3 (1.3.5)
|
46
|
-
systemu (2.
|
47
|
-
test-unit (2.4.
|
71
|
+
systemu (2.5.0)
|
72
|
+
test-unit (2.4.8)
|
48
73
|
thor (0.14.6)
|
49
|
-
|
50
|
-
|
74
|
+
tilt (1.3.3)
|
75
|
+
tzinfo (0.3.33)
|
76
|
+
uuid (2.3.5)
|
51
77
|
macaddr (~> 1.0)
|
52
78
|
|
53
79
|
PLATFORMS
|
54
80
|
ruby
|
55
81
|
|
56
82
|
DEPENDENCIES
|
83
|
+
actionpack (>= 3.0.0)
|
57
84
|
activemodel (>= 3.0.0)
|
58
85
|
activerecord (>= 3.0.0)
|
59
|
-
bundler (
|
86
|
+
bundler (>= 1.0.0)
|
60
87
|
guard-test
|
61
88
|
jeweler (~> 1.6.4)
|
62
89
|
libnotify
|
63
90
|
multi_json
|
64
91
|
rb-inotify
|
65
|
-
rcov
|
66
92
|
rdoc
|
67
93
|
rest-client
|
68
94
|
shoulda
|
data/Rakefile
CHANGED
@@ -38,18 +38,6 @@ Rake::TestTask.new(:test) do |test|
|
|
38
38
|
test.verbose = true
|
39
39
|
end
|
40
40
|
|
41
|
-
#RSpec::Core::RakeTask.new(:rcov) do |spec|
|
42
|
-
#spec.pattern = 'spec/**/*_spec.rb'
|
43
|
-
#spec.rcov = true
|
44
|
-
#end
|
45
|
-
require 'rcov/rcovtask'
|
46
|
-
Rcov::RcovTask.new do |test|
|
47
|
-
test.libs << 'test'
|
48
|
-
test.pattern = 'test/**/test_*.rb'
|
49
|
-
test.verbose = true
|
50
|
-
test.rcov_opts << '--exclude "gems/*"'
|
51
|
-
end
|
52
|
-
|
53
41
|
task :default => :spec
|
54
42
|
|
55
43
|
require 'rdoc/task'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.8
|
data/lib/filer/activerecord.rb
CHANGED
@@ -46,24 +46,35 @@ module Progstr
|
|
46
46
|
def _get_attachment(attribute)
|
47
47
|
if _attachments[attribute].nil?
|
48
48
|
id = read_attribute(attribute)
|
49
|
+
uploader_class = self.class._uploaders[attribute].class
|
49
50
|
if id.nil?
|
50
|
-
_attachments[attribute] = Attachment.empty
|
51
|
+
_attachments[attribute] = Attachment.empty(uploader_class)
|
51
52
|
else
|
52
|
-
_attachments[attribute] = Attachment.from_id(attribute, id)
|
53
|
+
_attachments[attribute] = Attachment.from_id(uploader_class, attribute, id)
|
53
54
|
end
|
54
55
|
else
|
55
56
|
_attachments[attribute]
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
59
|
-
def _set_attachment(attribute,
|
60
|
+
def _set_attachment(attribute, value)
|
60
61
|
old_attachment = _get_attachment(attribute)
|
61
62
|
unless old_attachment.blank?
|
62
63
|
_attachments_to_delete << old_attachment
|
63
64
|
end
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
uploader_class = self.class._uploaders[attribute].class
|
67
|
+
if value.kind_of?(String)
|
68
|
+
attachment = nil
|
69
|
+
if value.include?("{")
|
70
|
+
attachment = Attachment.from_json(uploader_class, attribute, value)
|
71
|
+
else
|
72
|
+
attachment = Attachment.from_id(uploader_class, attribute, value)
|
73
|
+
end
|
74
|
+
_attachments[attribute] = attachment
|
75
|
+
write_attribute(attribute, attachment.id)
|
76
|
+
elsif !value.nil? #file-like
|
77
|
+
attachment = Attachment.from_file(uploader_class, attribute, value)
|
67
78
|
_attachments[attribute] = attachment
|
68
79
|
write_attribute(attribute, attachment.id)
|
69
80
|
else
|
@@ -81,7 +92,7 @@ module Progstr
|
|
81
92
|
|
82
93
|
def _upload_attachment(attribute)
|
83
94
|
attachment = _get_attachment(attribute)
|
84
|
-
if
|
95
|
+
if attachment.need_upload?
|
85
96
|
uploader = self.class._uploaders[attribute]
|
86
97
|
uploader.upload_attachment(attachment) unless uploader.nil?
|
87
98
|
end
|
data/lib/filer/attachment.rb
CHANGED
@@ -1,7 +1,25 @@
|
|
1
1
|
module Progstr
|
2
2
|
module Filer
|
3
|
+
class FileLike
|
4
|
+
def initialize(json)
|
5
|
+
@values = MultiJson.decode(json)
|
6
|
+
end
|
7
|
+
|
8
|
+
def id
|
9
|
+
@values["id"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def path
|
13
|
+
@values["name"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def size
|
17
|
+
@values["size"]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
3
21
|
class Attachment
|
4
|
-
attr_accessor :id, :attribute, :file, :pre_validated
|
22
|
+
attr_accessor :id, :uploader_class, :attribute, :file, :pre_validated
|
5
23
|
|
6
24
|
@@id_generator = ::UUID.new
|
7
25
|
|
@@ -9,34 +27,58 @@ module Progstr
|
|
9
27
|
def blank?
|
10
28
|
true
|
11
29
|
end
|
12
|
-
|
13
30
|
def size
|
14
31
|
0
|
15
32
|
end
|
16
|
-
|
17
33
|
def path
|
18
34
|
""
|
19
35
|
end
|
20
|
-
|
21
36
|
def extension
|
22
37
|
""
|
23
38
|
end
|
39
|
+
def display_hash
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
def display_json
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
def need_upload?
|
46
|
+
false
|
47
|
+
end
|
24
48
|
end
|
25
49
|
|
26
|
-
def self.empty
|
27
|
-
EmptyAttachment.new
|
50
|
+
def self.empty(uploader_class)
|
51
|
+
result = EmptyAttachment.new
|
52
|
+
result.uploader_class = uploader_class
|
53
|
+
result
|
28
54
|
end
|
29
55
|
|
30
|
-
def self.
|
56
|
+
def self.from_json(uploader_class, attribute, json)
|
57
|
+
file = FileLike.new(json)
|
58
|
+
result = from_file(uploader_class, attribute, file)
|
59
|
+
result.pre_validated = true
|
60
|
+
return result
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.from_file(uploader_class, attribute, file)
|
31
64
|
result = Attachment.new
|
32
|
-
result.id =
|
65
|
+
result.id = file_id(file)
|
33
66
|
result.attribute = attribute
|
67
|
+
result.uploader_class = uploader_class
|
34
68
|
|
35
69
|
result.file = file
|
36
70
|
result.pre_validated = false
|
37
71
|
result
|
38
72
|
end
|
39
73
|
|
74
|
+
def self.file_id(file)
|
75
|
+
if file.respond_to?(:id)
|
76
|
+
file.id
|
77
|
+
else
|
78
|
+
generate_id
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
40
82
|
def self.generate_id
|
41
83
|
uuid = @@id_generator.generate
|
42
84
|
uuid.gsub("-", "")
|
@@ -56,10 +98,11 @@ module Progstr
|
|
56
98
|
from_file.sub(".", "")
|
57
99
|
end
|
58
100
|
|
59
|
-
def self.from_id(attribute, id)
|
101
|
+
def self.from_id(uploader_class, attribute, id)
|
60
102
|
result = Attachment.new
|
61
103
|
result.id = id
|
62
104
|
result.attribute = attribute
|
105
|
+
result.uploader_class = uploader_class
|
63
106
|
|
64
107
|
result.pre_validated = true
|
65
108
|
result
|
@@ -71,7 +114,7 @@ module Progstr
|
|
71
114
|
|
72
115
|
def url
|
73
116
|
if !blank?
|
74
|
-
token = Progstr::Filer.
|
117
|
+
token = Progstr::Filer.generate_download_auth_token(id)
|
75
118
|
"#{Progstr::Filer.url_prefix}files/data/#{Progstr::Filer.access_key}/#{id}?auth=#{token}"
|
76
119
|
else
|
77
120
|
""
|
@@ -85,6 +128,28 @@ module Progstr
|
|
85
128
|
""
|
86
129
|
end
|
87
130
|
end
|
131
|
+
|
132
|
+
def display_json
|
133
|
+
MultiJson.encode(display_hash)
|
134
|
+
end
|
135
|
+
|
136
|
+
def display_hash
|
137
|
+
{
|
138
|
+
"name" => path,
|
139
|
+
"size" => size,
|
140
|
+
"id" => id
|
141
|
+
}
|
142
|
+
end
|
143
|
+
|
144
|
+
def need_upload?
|
145
|
+
if file.nil?
|
146
|
+
false
|
147
|
+
elsif file.kind_of?(FileLike)
|
148
|
+
false
|
149
|
+
else
|
150
|
+
true
|
151
|
+
end
|
152
|
+
end
|
88
153
|
end
|
89
154
|
end
|
90
155
|
end
|
data/lib/filer/config.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
module Progstr
|
3
3
|
module Filer
|
4
4
|
class << self
|
5
|
-
attr_accessor :host, :port, :path_prefix, :session_timeout
|
5
|
+
attr_accessor :host, :port, :path_prefix, :session_timeout, :asset_url_prefix, :upload_url, :use_ssl
|
6
6
|
attr_writer :access_key, :secret_key
|
7
7
|
|
8
8
|
def access_key
|
@@ -16,6 +16,21 @@ module Progstr
|
|
16
16
|
def host
|
17
17
|
@host ||= "filer-api.progstr.com"
|
18
18
|
end
|
19
|
+
|
20
|
+
def default_asset_url_prefix
|
21
|
+
insecure_prefix = "http://cdn.progstr.com/upload/"
|
22
|
+
secure_prefix = "https://s3.amazonaws.com/cdn.progstr.com/upload/"
|
23
|
+
javascript_version = "1.0"
|
24
|
+
|
25
|
+
prefix = insecure_prefix
|
26
|
+
prefix = secure_prefix if use_ssl
|
27
|
+
prefix + javascript_version
|
28
|
+
end
|
29
|
+
|
30
|
+
def default_upload_url
|
31
|
+
"http://#{Progstr::Filer.host}/upload/new"
|
32
|
+
end
|
33
|
+
|
19
34
|
def port
|
20
35
|
@port || 80
|
21
36
|
end
|
@@ -23,7 +38,7 @@ module Progstr
|
|
23
38
|
@path_prefix ||= '/'
|
24
39
|
end
|
25
40
|
def session_timeout
|
26
|
-
@
|
41
|
+
@session_timeout ||= 30 * 60 # 30 minutes
|
27
42
|
end
|
28
43
|
|
29
44
|
def generate_auth_token
|
@@ -33,13 +48,20 @@ module Progstr
|
|
33
48
|
"#{access_key}-#{expiration}-#{signature}"
|
34
49
|
end
|
35
50
|
|
36
|
-
def
|
51
|
+
def generate_download_auth_token(file_id)
|
37
52
|
expiration = expiration_time
|
38
53
|
to_sign = "#{access_key}-#{file_id}-#{expiration}-#{secret_key}"
|
39
54
|
signature = Digest::SHA1.hexdigest(to_sign)
|
40
55
|
"#{access_key}-#{expiration}-#{signature}"
|
41
56
|
end
|
42
57
|
|
58
|
+
def generate_upload_auth_token(uploader)
|
59
|
+
expiration = expiration_time
|
60
|
+
to_sign = "#{access_key}-#{uploader}-#{expiration}-#{secret_key}"
|
61
|
+
signature = Digest::SHA1.hexdigest(to_sign)
|
62
|
+
"#{access_key}-#{expiration}-#{signature}"
|
63
|
+
end
|
64
|
+
|
43
65
|
def url_prefix
|
44
66
|
prefix = "http://#{Progstr::Filer.host}:#{Progstr::Filer.port}#{Progstr::Filer.path_prefix}"
|
45
67
|
if prefix.end_with? "/"
|
data/lib/filer/file_info.rb
CHANGED
data/lib/filer/uploader.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Progstr
|
2
|
+
module Filer
|
3
|
+
module FormHtml
|
4
|
+
|
5
|
+
def filer_upload_field(method, options = {})
|
6
|
+
unless options.key? :file_input_name
|
7
|
+
sanitized_method_name = method.to_s.sub(/\?$/,"")
|
8
|
+
input_name = "#{@object_name}[#{sanitized_method_name}]"
|
9
|
+
options[:file_input_name] = input_name
|
10
|
+
end
|
11
|
+
attachment = @object.send(method)
|
12
|
+
|
13
|
+
@template.filer_upload(attachment, options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
require "action_view"
|
20
|
+
form_builder = ActionView::Base.default_form_builder
|
21
|
+
form_builder.class_eval do
|
22
|
+
include Progstr::Filer::FormHtml
|
23
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Progstr
|
2
|
+
module Filer
|
3
|
+
module Html
|
4
|
+
def filer_upload(attachment, options = {})
|
5
|
+
client_id = generate_container_id
|
6
|
+
register_scripts
|
7
|
+
|
8
|
+
client_options = prepare_client_options(attachment, options)
|
9
|
+
client_options_json = MultiJson.encode(client_options)
|
10
|
+
|
11
|
+
init_script = <<EOJSON
|
12
|
+
$(function(){
|
13
|
+
$('\##{client_id}').filerUpload(#{client_options_json})
|
14
|
+
})
|
15
|
+
EOJSON
|
16
|
+
|
17
|
+
tag("div", "id" => client_id) +
|
18
|
+
javascript_tag(init_script)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def filer_scripts
|
23
|
+
prefix = Progstr::Filer.asset_url_prefix || Progstr::Filer.default_asset_url_prefix
|
24
|
+
|
25
|
+
scripts = [
|
26
|
+
"/upload.js",
|
27
|
+
"/pl/flash.support.js",
|
28
|
+
]
|
29
|
+
tags = scripts.map do |script|
|
30
|
+
javascript_include_tag (prefix + script)
|
31
|
+
end
|
32
|
+
tags.join("\r\n").html_safe
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def generate_container_id
|
37
|
+
request.env["PROGSTR_FILER_UPLOAD_INSTANCES"] ||= 1
|
38
|
+
instances = request.env["PROGSTR_FILER_UPLOAD_INSTANCES"]
|
39
|
+
request.env["PROGSTR_FILER_UPLOAD_INSTANCES"] += 1
|
40
|
+
"filer_upload_container_#{instances}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def prepare_client_options(attachment, options)
|
44
|
+
client_options = {}
|
45
|
+
options.each do |k, v|
|
46
|
+
client_options[k.to_s.camelize(:lower)] = v
|
47
|
+
end
|
48
|
+
uploader_name = attachment.uploader_class.name
|
49
|
+
client_options["uploader"] = uploader_name
|
50
|
+
client_options["initialFiles"] = [attachment.display_hash] unless attachment.blank?
|
51
|
+
client_options["authToken"] = Progstr::Filer.generate_upload_auth_token(uploader_name)
|
52
|
+
client_options["uploadUrl"] = Progstr::Filer.upload_url unless Progstr::Filer.upload_url.nil?
|
53
|
+
|
54
|
+
client_options
|
55
|
+
end
|
56
|
+
|
57
|
+
def register_scripts
|
58
|
+
unless request.env.key? "PROGSTR_FILER_SCRIPTS_INCLUDED"
|
59
|
+
request.env["PROGSTR_FILER_SCRIPTS_INCLUDED"] = true
|
60
|
+
|
61
|
+
content_for :filer_scripts, filer_scripts
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
require "action_controller"
|
69
|
+
ActionController::Base.helper(Progstr::Filer::Html)
|
data/lib/progstr-filer.rb
CHANGED
data/test/test_attachment_url.rb
CHANGED
@@ -2,10 +2,21 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class TestIdGeneration < Test::Unit::TestCase
|
4
4
|
should "generate file URLs using accessKey and file ID" do
|
5
|
-
a = Progstr::Filer::Attachment.from_id(:avatar, "some-attachment-id")
|
5
|
+
a = Progstr::Filer::Attachment.from_id(MockUploader, :avatar, "some-attachment-id")
|
6
6
|
|
7
7
|
assert_match "/files/data/DEMO/some-attachment-id", a.url
|
8
8
|
assert_match Progstr::Filer.host, a.url
|
9
9
|
assert_match Progstr::Filer.host, a.url
|
10
10
|
end
|
11
|
+
|
12
|
+
should "roundtrip from and to JSON" do
|
13
|
+
json = '{"id":"7933ad9a0f93457ab625a070fec3544f","name":"test.png","size":100}'
|
14
|
+
a = Progstr::Filer::Attachment.from_json(MockUploader, :avatar, json)
|
15
|
+
|
16
|
+
new_json = a.display_json
|
17
|
+
|
18
|
+
assert_match "7933ad9a0f93457ab625a070fec3544f", new_json
|
19
|
+
assert_match "test.png", new_json
|
20
|
+
assert_match "100", new_json
|
21
|
+
end
|
11
22
|
end
|
data/test/test_file_mount.rb
CHANGED
@@ -8,20 +8,38 @@ class TestFileMount < UserTest
|
|
8
8
|
|
9
9
|
should "create an uploader when given a file" do
|
10
10
|
non_empty = User.new
|
11
|
-
non_empty.avatar =
|
11
|
+
non_empty.avatar = FileMock.new
|
12
12
|
assert_false non_empty.avatar.blank?
|
13
13
|
end
|
14
14
|
|
15
|
-
should "
|
15
|
+
should "create an uploader when given an id string" do
|
16
|
+
non_empty = User.new
|
17
|
+
non_empty.avatar = "some-string-id"
|
18
|
+
assert_false non_empty.avatar.blank?
|
19
|
+
assert_equal "some-string-id", non_empty.avatar.id
|
20
|
+
end
|
21
|
+
|
22
|
+
should "create an uploader when given file info JSON string" do
|
23
|
+
json = '{"id":"7933ad9a0f93457ab625a070fec3544f","name":"test.png","size":100}'
|
24
|
+
|
25
|
+
non_empty = User.new
|
26
|
+
non_empty.avatar = json
|
27
|
+
assert_false non_empty.avatar.blank?
|
28
|
+
assert_equal "7933ad9a0f93457ab625a070fec3544f", non_empty.avatar.id
|
29
|
+
assert_equal "test.png", non_empty.avatar.path
|
30
|
+
assert_equal 100, non_empty.avatar.size
|
31
|
+
end
|
32
|
+
|
33
|
+
should "persist attachment id only" do
|
16
34
|
u = User.new
|
17
|
-
u.avatar =
|
35
|
+
u.avatar = FileMock.new
|
18
36
|
assert_not_nil u.avatar.id, "attachment id generated"
|
19
37
|
assert_equal u.read_attribute(:avatar), u.avatar.id, "attachment id saved to db"
|
20
38
|
end
|
21
39
|
|
22
40
|
should "save and load attachment id to db" do
|
23
41
|
u = User.new
|
24
|
-
u.avatar =
|
42
|
+
u.avatar = FileMock.new
|
25
43
|
u.save!
|
26
44
|
|
27
45
|
loaded = User.find(u.id)
|
data/test/test_helper.rb
CHANGED
data/test/test_http_upload.rb
CHANGED
@@ -6,12 +6,11 @@ end
|
|
6
6
|
class TestHttpUpload < Test::Unit::TestCase
|
7
7
|
# The mother of all tests calling the real API
|
8
8
|
test "upload attachment" do
|
9
|
-
attachment = Progstr::Filer::Attachment.from_file(:version, File.open("VERSION"))
|
9
|
+
attachment = Progstr::Filer::Attachment.from_file(MockUploader, :version, File.open("VERSION"))
|
10
10
|
uploader = DemoUploader.new
|
11
11
|
response = uploader.upload_attachment attachment
|
12
12
|
|
13
13
|
assert_equal response.name, "VERSION"
|
14
|
-
assert_equal response.success, true
|
15
14
|
assert_equal response.message, "OK"
|
16
15
|
|
17
16
|
info = uploader.file_info attachment
|
@@ -19,7 +18,6 @@ class TestHttpUpload < Test::Unit::TestCase
|
|
19
18
|
assert_equal info.name, "VERSION"
|
20
19
|
assert_equal info.id, attachment.id
|
21
20
|
assert_equal info.content_type, "text/plain"
|
22
|
-
assert_equal info.property, "version"
|
23
21
|
assert_equal info.uploader, "DemoUploader"
|
24
22
|
assert_true info.size > 0
|
25
23
|
|
@@ -31,7 +29,7 @@ class TestHttpUpload < Test::Unit::TestCase
|
|
31
29
|
begin
|
32
30
|
Progstr::Filer.secret_key = "BROKEN"
|
33
31
|
|
34
|
-
attachment = Progstr::Filer::Attachment.from_file(:version, File.open("VERSION"))
|
32
|
+
attachment = Progstr::Filer::Attachment.from_file(MockUploader, :version, File.open("VERSION"))
|
35
33
|
uploader = DemoUploader.new
|
36
34
|
begin
|
37
35
|
response = uploader.upload_attachment attachment
|
data/test/test_id_generation.rb
CHANGED
@@ -2,8 +2,8 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class TestIdGeneration < Test::Unit::TestCase
|
4
4
|
should "use UUIDs for attachment IDs" do
|
5
|
-
a = Progstr::Filer::Attachment.from_file(:avatar,
|
6
|
-
b = Progstr::Filer::Attachment.from_file(:avatar,
|
5
|
+
a = Progstr::Filer::Attachment.from_file(MockUploader, :avatar, FileMock.new)
|
6
|
+
b = Progstr::Filer::Attachment.from_file(MockUploader, :avatar, FileMock.new)
|
7
7
|
|
8
8
|
assert_not_nil a.id
|
9
9
|
assert_not_nil b.id
|
@@ -11,7 +11,7 @@ class TestIdGeneration < Test::Unit::TestCase
|
|
11
11
|
end
|
12
12
|
|
13
13
|
should "have attachment IDs with no hyphens" do
|
14
|
-
a = Progstr::Filer::Attachment.from_file(:avatar,
|
14
|
+
a = Progstr::Filer::Attachment.from_file(MockUploader, :avatar, FileMock.new)
|
15
15
|
assert_match /^[^-]+$/, a.id, "IDs should contain no hyphens"
|
16
16
|
end
|
17
17
|
end
|
data/test/test_upload_on_save.rb
CHANGED
@@ -3,20 +3,41 @@ require 'test_helper'
|
|
3
3
|
class TestUploadOnSave < UserTest
|
4
4
|
should "upload file on record save" do
|
5
5
|
u = User.new
|
6
|
-
f =
|
6
|
+
f = FileMock.new
|
7
7
|
u.avatar = f
|
8
8
|
|
9
9
|
u.save!
|
10
10
|
assert_same $lastUploadedAtachment.file, f, "avatar file sent to uploader"
|
11
11
|
end
|
12
12
|
|
13
|
+
should "not upload JSON-created attachments" do
|
14
|
+
$lastUploadedAtachment = nil
|
15
|
+
|
16
|
+
u = User.new
|
17
|
+
json = '{"id":"7933ad9a0f93457ab625a070fec3544f","name":"test.png","size":100}'
|
18
|
+
u.avatar = json
|
19
|
+
|
20
|
+
u.save!
|
21
|
+
assert_nil $lastUploadedAtachment
|
22
|
+
end
|
23
|
+
|
24
|
+
should "save id only when JSON-created" do
|
25
|
+
$lastUploadedAtachment = nil
|
26
|
+
|
27
|
+
u = User.new
|
28
|
+
json = '{"id":"7933ad9a0f93457ab625a070fec3544f","name":"test.png","size":100}'
|
29
|
+
u.avatar = json
|
30
|
+
saved_id = u.read_attribute(:avatar)
|
31
|
+
assert_equal "7933ad9a0f93457ab625a070fec3544f", saved_id
|
32
|
+
end
|
33
|
+
|
13
34
|
should "delete the previous attachment on save" do
|
14
35
|
u = User.new
|
15
|
-
f1 =
|
36
|
+
f1 = FileMock.new
|
16
37
|
u.avatar = f1
|
17
38
|
u.save!
|
18
39
|
|
19
|
-
f2 =
|
40
|
+
f2 = FileMock.new
|
20
41
|
u.avatar = f2
|
21
42
|
|
22
43
|
u.save!
|
@@ -25,7 +46,7 @@ class TestUploadOnSave < UserTest
|
|
25
46
|
|
26
47
|
should "delete previous attachment and null attribute if set to nil" do
|
27
48
|
u = User.new
|
28
|
-
f1 =
|
49
|
+
f1 = FileMock.new
|
29
50
|
u.avatar = f1
|
30
51
|
u.save!
|
31
52
|
|
@@ -39,7 +60,7 @@ class TestUploadOnSave < UserTest
|
|
39
60
|
|
40
61
|
should "delete attachments on record delete" do
|
41
62
|
u = User.new
|
42
|
-
f1 =
|
63
|
+
f1 = FileMock.new
|
43
64
|
u.avatar = f1
|
44
65
|
u.save!
|
45
66
|
|
data/test/test_validation.rb
CHANGED
@@ -8,7 +8,7 @@ class TestValidation < UserTest
|
|
8
8
|
|
9
9
|
test "don't store if size greater than 2MB" do
|
10
10
|
u = ValidatedUser.new
|
11
|
-
too_big =
|
11
|
+
too_big = FileMock.new
|
12
12
|
too_big.path = "too_big.png"
|
13
13
|
too_big.size = 5 * 1024 * 1024
|
14
14
|
u.avatar = too_big
|
@@ -18,7 +18,7 @@ class TestValidation < UserTest
|
|
18
18
|
|
19
19
|
test "don't store if extension not allowed" do
|
20
20
|
u = ValidatedUser.new
|
21
|
-
exe =
|
21
|
+
exe = FileMock.new
|
22
22
|
exe.path = "virus_infected.exe"
|
23
23
|
u.avatar = exe
|
24
24
|
|
@@ -28,7 +28,7 @@ class TestValidation < UserTest
|
|
28
28
|
|
29
29
|
test "use original_filename on file objects if present" do
|
30
30
|
u = ValidatedUser.new
|
31
|
-
exe =
|
31
|
+
exe = UploadedFileMock.new
|
32
32
|
exe.original_filename = "virus_infected.exe"
|
33
33
|
u.avatar = exe
|
34
34
|
|
@@ -38,7 +38,7 @@ class TestValidation < UserTest
|
|
38
38
|
|
39
39
|
test "don't store files without an extension" do
|
40
40
|
u = ValidatedUser.new
|
41
|
-
exe =
|
41
|
+
exe = FileMock.new
|
42
42
|
exe.path = "noextension"
|
43
43
|
u.avatar = exe
|
44
44
|
|
@@ -62,7 +62,7 @@ class TestValidation < UserTest
|
|
62
62
|
|
63
63
|
test "validation passes" do
|
64
64
|
u = ValidatedUser.new
|
65
|
-
jpg =
|
65
|
+
jpg = FileMock.new
|
66
66
|
jpg.path = "avatar.jpg"
|
67
67
|
u.avatar = jpg
|
68
68
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: progstr-filer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.8
|
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: 2012-
|
12
|
+
date: 2012-05-10 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
|
-
requirement: &
|
16
|
+
requirement: &24236220 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *24236220
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activemodel
|
27
|
-
requirement: &
|
27
|
+
requirement: &24235640 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,21 @@ dependencies:
|
|
32
32
|
version: 3.0.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *24235640
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: actionpack
|
38
|
+
requirement: &24235040 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 3.0.0
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *24235040
|
36
47
|
- !ruby/object:Gem::Dependency
|
37
48
|
name: uuid
|
38
|
-
requirement: &
|
49
|
+
requirement: &24234320 !ruby/object:Gem::Requirement
|
39
50
|
none: false
|
40
51
|
requirements:
|
41
52
|
- - ! '>='
|
@@ -43,10 +54,10 @@ dependencies:
|
|
43
54
|
version: '0'
|
44
55
|
type: :runtime
|
45
56
|
prerelease: false
|
46
|
-
version_requirements: *
|
57
|
+
version_requirements: *24234320
|
47
58
|
- !ruby/object:Gem::Dependency
|
48
59
|
name: rest-client
|
49
|
-
requirement: &
|
60
|
+
requirement: &24233600 !ruby/object:Gem::Requirement
|
50
61
|
none: false
|
51
62
|
requirements:
|
52
63
|
- - ! '>='
|
@@ -54,10 +65,10 @@ dependencies:
|
|
54
65
|
version: '0'
|
55
66
|
type: :runtime
|
56
67
|
prerelease: false
|
57
|
-
version_requirements: *
|
68
|
+
version_requirements: *24233600
|
58
69
|
- !ruby/object:Gem::Dependency
|
59
70
|
name: multi_json
|
60
|
-
requirement: &
|
71
|
+
requirement: &24227220 !ruby/object:Gem::Requirement
|
61
72
|
none: false
|
62
73
|
requirements:
|
63
74
|
- - ! '>='
|
@@ -65,10 +76,10 @@ dependencies:
|
|
65
76
|
version: '0'
|
66
77
|
type: :runtime
|
67
78
|
prerelease: false
|
68
|
-
version_requirements: *
|
79
|
+
version_requirements: *24227220
|
69
80
|
- !ruby/object:Gem::Dependency
|
70
81
|
name: sqlite3
|
71
|
-
requirement: &
|
82
|
+
requirement: &24226500 !ruby/object:Gem::Requirement
|
72
83
|
none: false
|
73
84
|
requirements:
|
74
85
|
- - ! '>='
|
@@ -76,10 +87,10 @@ dependencies:
|
|
76
87
|
version: '0'
|
77
88
|
type: :development
|
78
89
|
prerelease: false
|
79
|
-
version_requirements: *
|
90
|
+
version_requirements: *24226500
|
80
91
|
- !ruby/object:Gem::Dependency
|
81
92
|
name: guard-test
|
82
|
-
requirement: &
|
93
|
+
requirement: &24225800 !ruby/object:Gem::Requirement
|
83
94
|
none: false
|
84
95
|
requirements:
|
85
96
|
- - ! '>='
|
@@ -87,10 +98,10 @@ dependencies:
|
|
87
98
|
version: '0'
|
88
99
|
type: :development
|
89
100
|
prerelease: false
|
90
|
-
version_requirements: *
|
101
|
+
version_requirements: *24225800
|
91
102
|
- !ruby/object:Gem::Dependency
|
92
103
|
name: rb-inotify
|
93
|
-
requirement: &
|
104
|
+
requirement: &24224980 !ruby/object:Gem::Requirement
|
94
105
|
none: false
|
95
106
|
requirements:
|
96
107
|
- - ! '>='
|
@@ -98,10 +109,10 @@ dependencies:
|
|
98
109
|
version: '0'
|
99
110
|
type: :development
|
100
111
|
prerelease: false
|
101
|
-
version_requirements: *
|
112
|
+
version_requirements: *24224980
|
102
113
|
- !ruby/object:Gem::Dependency
|
103
114
|
name: libnotify
|
104
|
-
requirement: &
|
115
|
+
requirement: &24224220 !ruby/object:Gem::Requirement
|
105
116
|
none: false
|
106
117
|
requirements:
|
107
118
|
- - ! '>='
|
@@ -109,10 +120,10 @@ dependencies:
|
|
109
120
|
version: '0'
|
110
121
|
type: :development
|
111
122
|
prerelease: false
|
112
|
-
version_requirements: *
|
123
|
+
version_requirements: *24224220
|
113
124
|
- !ruby/object:Gem::Dependency
|
114
125
|
name: shoulda
|
115
|
-
requirement: &
|
126
|
+
requirement: &24223540 !ruby/object:Gem::Requirement
|
116
127
|
none: false
|
117
128
|
requirements:
|
118
129
|
- - ! '>='
|
@@ -120,21 +131,21 @@ dependencies:
|
|
120
131
|
version: '0'
|
121
132
|
type: :development
|
122
133
|
prerelease: false
|
123
|
-
version_requirements: *
|
134
|
+
version_requirements: *24223540
|
124
135
|
- !ruby/object:Gem::Dependency
|
125
136
|
name: bundler
|
126
|
-
requirement: &
|
137
|
+
requirement: &24222840 !ruby/object:Gem::Requirement
|
127
138
|
none: false
|
128
139
|
requirements:
|
129
|
-
- -
|
140
|
+
- - ! '>='
|
130
141
|
- !ruby/object:Gem::Version
|
131
142
|
version: 1.0.0
|
132
143
|
type: :development
|
133
144
|
prerelease: false
|
134
|
-
version_requirements: *
|
145
|
+
version_requirements: *24222840
|
135
146
|
- !ruby/object:Gem::Dependency
|
136
147
|
name: jeweler
|
137
|
-
requirement: &
|
148
|
+
requirement: &24222200 !ruby/object:Gem::Requirement
|
138
149
|
none: false
|
139
150
|
requirements:
|
140
151
|
- - ~>
|
@@ -142,21 +153,10 @@ dependencies:
|
|
142
153
|
version: 1.6.4
|
143
154
|
type: :development
|
144
155
|
prerelease: false
|
145
|
-
version_requirements: *
|
146
|
-
- !ruby/object:Gem::Dependency
|
147
|
-
name: rcov
|
148
|
-
requirement: &23842540 !ruby/object:Gem::Requirement
|
149
|
-
none: false
|
150
|
-
requirements:
|
151
|
-
- - ! '>='
|
152
|
-
- !ruby/object:Gem::Version
|
153
|
-
version: '0'
|
154
|
-
type: :development
|
155
|
-
prerelease: false
|
156
|
-
version_requirements: *23842540
|
156
|
+
version_requirements: *24222200
|
157
157
|
- !ruby/object:Gem::Dependency
|
158
158
|
name: rdoc
|
159
|
-
requirement: &
|
159
|
+
requirement: &24221480 !ruby/object:Gem::Requirement
|
160
160
|
none: false
|
161
161
|
requirements:
|
162
162
|
- - ! '>='
|
@@ -164,7 +164,7 @@ dependencies:
|
|
164
164
|
version: '0'
|
165
165
|
type: :development
|
166
166
|
prerelease: false
|
167
|
-
version_requirements: *
|
167
|
+
version_requirements: *24221480
|
168
168
|
description: Progstr Filer is a developer-friendly file and attachment hosting service
|
169
169
|
that lets you easily build apps that store and share files.
|
170
170
|
email: hristo@deshev.com
|
@@ -189,9 +189,11 @@ files:
|
|
189
189
|
- lib/filer/file_info.rb
|
190
190
|
- lib/filer/uploader.rb
|
191
191
|
- lib/filer/validation.rb
|
192
|
+
- lib/filer/views/form_html.rb
|
193
|
+
- lib/filer/views/html.rb
|
192
194
|
- lib/progstr-filer.rb
|
193
195
|
- test/adium-green-duckling.png
|
194
|
-
- test/
|
196
|
+
- test/file_mock.rb
|
195
197
|
- test/test_attachment_url.rb
|
196
198
|
- test/test_file_mount.rb
|
197
199
|
- test/test_helper.rb
|
@@ -215,7 +217,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
215
217
|
version: '0'
|
216
218
|
segments:
|
217
219
|
- 0
|
218
|
-
hash:
|
220
|
+
hash: -4458103190430304874
|
219
221
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
220
222
|
none: false
|
221
223
|
requirements:
|