salebot_uploader 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +0 -0
  3. data/lib/generators/templates/uploader.rb.erb +9 -0
  4. data/lib/generators/uploader_generator.rb +7 -0
  5. data/lib/salebot_uploader/compatibility/paperclip.rb +104 -0
  6. data/lib/salebot_uploader/downloader/base.rb +101 -0
  7. data/lib/salebot_uploader/downloader/remote_file.rb +68 -0
  8. data/lib/salebot_uploader/error.rb +8 -0
  9. data/lib/salebot_uploader/locale/en.yml +17 -0
  10. data/lib/salebot_uploader/mount.rb +446 -0
  11. data/lib/salebot_uploader/mounter.rb +255 -0
  12. data/lib/salebot_uploader/orm/activerecord.rb +68 -0
  13. data/lib/salebot_uploader/processing/mini_magick.rb +194 -0
  14. data/lib/salebot_uploader/processing/rmagick.rb +402 -0
  15. data/lib/salebot_uploader/processing/vips.rb +284 -0
  16. data/lib/salebot_uploader/processing.rb +3 -0
  17. data/lib/salebot_uploader/sanitized_file.rb +357 -0
  18. data/lib/salebot_uploader/storage/abstract.rb +41 -0
  19. data/lib/salebot_uploader/storage/file.rb +124 -0
  20. data/lib/salebot_uploader/storage/fog.rb +547 -0
  21. data/lib/salebot_uploader/storage.rb +3 -0
  22. data/lib/salebot_uploader/test/matchers.rb +398 -0
  23. data/lib/salebot_uploader/uploader/cache.rb +223 -0
  24. data/lib/salebot_uploader/uploader/callbacks.rb +33 -0
  25. data/lib/salebot_uploader/uploader/configuration.rb +184 -0
  26. data/lib/salebot_uploader/uploader/content_type_allowlist.rb +61 -0
  27. data/lib/salebot_uploader/uploader/content_type_denylist.rb +62 -0
  28. data/lib/salebot_uploader/uploader/default_url.rb +17 -0
  29. data/lib/salebot_uploader/uploader/dimension.rb +66 -0
  30. data/lib/salebot_uploader/uploader/download.rb +24 -0
  31. data/lib/salebot_uploader/uploader/extension_allowlist.rb +63 -0
  32. data/lib/salebot_uploader/uploader/extension_denylist.rb +64 -0
  33. data/lib/salebot_uploader/uploader/file_size.rb +43 -0
  34. data/lib/salebot_uploader/uploader/mountable.rb +44 -0
  35. data/lib/salebot_uploader/uploader/processing.rb +125 -0
  36. data/lib/salebot_uploader/uploader/proxy.rb +99 -0
  37. data/lib/salebot_uploader/uploader/remove.rb +21 -0
  38. data/lib/salebot_uploader/uploader/serialization.rb +28 -0
  39. data/lib/salebot_uploader/uploader/store.rb +142 -0
  40. data/lib/salebot_uploader/uploader/url.rb +44 -0
  41. data/lib/salebot_uploader/uploader/versions.rb +350 -0
  42. data/lib/salebot_uploader/uploader.rb +53 -0
  43. data/lib/salebot_uploader/utilities/file_name.rb +47 -0
  44. data/lib/salebot_uploader/utilities/uri.rb +26 -0
  45. data/lib/salebot_uploader/utilities.rb +7 -0
  46. data/lib/salebot_uploader/validations/active_model.rb +76 -0
  47. data/lib/salebot_uploader/version.rb +3 -0
  48. data/lib/salebot_uploader.rb +62 -0
  49. metadata +392 -0
@@ -0,0 +1,184 @@
1
+ require 'salebot_uploader/downloader/base'
2
+
3
+ module SalebotUploader
4
+
5
+ module Uploader
6
+ module Configuration
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ class_attribute :_storage, :_cache_storage, :instance_writer => false
11
+
12
+ add_config :root
13
+ add_config :base_path
14
+ add_config :asset_host
15
+ add_config :permissions
16
+ add_config :directory_permissions
17
+ add_config :storage_engines
18
+ add_config :store_dir
19
+ add_config :cache_dir
20
+ add_config :enable_processing
21
+ add_config :ensure_multipart_form
22
+ add_config :delete_tmp_file_after_storage
23
+ add_config :move_to_cache
24
+ add_config :move_to_store
25
+ add_config :remove_previously_stored_files_after_update
26
+ add_config :downloader
27
+ add_config :force_extension
28
+
29
+ # fog
30
+ add_deprecated_config :fog_provider
31
+ add_config :fog_attributes
32
+ add_config :fog_credentials
33
+ add_config :fog_directory
34
+ add_config :fog_public
35
+ add_config :fog_authenticated_url_expiration
36
+ add_config :fog_use_ssl_for_aws
37
+ add_config :fog_aws_accelerate
38
+
39
+ # Mounting
40
+ add_config :ignore_integrity_errors
41
+ add_config :ignore_processing_errors
42
+ add_config :ignore_download_errors
43
+ add_config :validate_integrity
44
+ add_config :validate_processing
45
+ add_config :validate_download
46
+ add_config :mount_on
47
+ add_config :cache_only
48
+ add_config :download_retry_count
49
+ add_config :download_retry_wait_time
50
+ add_config :skip_ssrf_protection
51
+
52
+ # set default values
53
+ reset_config
54
+ end
55
+
56
+ module ClassMethods
57
+ def storage(storage = nil)
58
+ case storage
59
+ when Symbol
60
+ if (storage_engine = storage_engines[storage])
61
+ self._storage = eval storage_engine
62
+ else
63
+ raise SalebotUploader::UnknownStorageError, "Unknown storage: #{storage}"
64
+ end
65
+ when nil
66
+ storage
67
+ else
68
+ self._storage = storage
69
+ end
70
+ _storage
71
+ end
72
+ alias_method :storage=, :storage
73
+
74
+ def cache_storage(storage = false)
75
+ unless storage == false
76
+ self._cache_storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
77
+ end
78
+ _cache_storage
79
+ end
80
+ alias_method :cache_storage=, :cache_storage
81
+
82
+ def add_config(name)
83
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
84
+ @#{name} = nil
85
+
86
+ def self.#{name}(value=nil)
87
+ @#{name} = value unless value.nil?
88
+ return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
89
+ name = superclass.#{name}
90
+ return nil if name.nil? && !instance_variable_defined?(:@#{name})
91
+ @#{name} = name && !name.is_a?(Module) && !name.is_a?(Symbol) && !name.is_a?(Numeric) && !name.is_a?(TrueClass) && !name.is_a?(FalseClass) ? name.dup : name
92
+ end
93
+
94
+ def self.#{name}=(value)
95
+ @#{name} = value
96
+ end
97
+
98
+ def #{name}=(value)
99
+ @#{name} = value
100
+ end
101
+
102
+ def #{name}
103
+ value = @#{name} if instance_variable_defined?(:@#{name})
104
+ value = self.class.#{name} unless instance_variable_defined?(:@#{name})
105
+ if value.instance_of?(Proc)
106
+ value.arity >= 1 ? value.call(self) : value.call
107
+ else
108
+ value
109
+ end
110
+ end
111
+ RUBY
112
+ end
113
+
114
+ def add_deprecated_config(name)
115
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
116
+ def self.#{name}(value=nil)
117
+ ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
118
+ end
119
+
120
+ def self.#{name}=(value)
121
+ ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
122
+ end
123
+
124
+ def #{name}=(value)
125
+ ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
126
+ end
127
+
128
+ def #{name}
129
+ ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
130
+ end
131
+ RUBY
132
+ end
133
+
134
+ def configure
135
+ yield self
136
+ end
137
+
138
+ ##
139
+ # sets configuration back to default
140
+ #
141
+ def reset_config
142
+ configure do |config|
143
+ config.permissions = 0o644
144
+ config.directory_permissions = 0o755
145
+ config.storage_engines = {
146
+ :file => "SalebotUploader::Storage::File",
147
+ :fog => "SalebotUploader::Storage::Fog"
148
+ }
149
+ config.storage = :file
150
+ config.cache_storage = nil
151
+ config.fog_attributes = {}
152
+ config.fog_credentials = {}
153
+ config.fog_public = true
154
+ config.fog_authenticated_url_expiration = 600
155
+ config.fog_use_ssl_for_aws = true
156
+ config.fog_aws_accelerate = false
157
+ config.store_dir = 'uploads'
158
+ config.cache_dir = 'uploads/tmp'
159
+ config.delete_tmp_file_after_storage = true
160
+ config.move_to_cache = false
161
+ config.move_to_store = false
162
+ config.remove_previously_stored_files_after_update = true
163
+ config.downloader = SalebotUploader::Downloader::Base
164
+ config.force_extension = false
165
+ config.ignore_integrity_errors = true
166
+ config.ignore_processing_errors = true
167
+ config.ignore_download_errors = true
168
+ config.validate_integrity = true
169
+ config.validate_processing = true
170
+ config.validate_download = true
171
+ config.root = lambda { SalebotUploader.root }
172
+ config.base_path = SalebotUploader.base_path
173
+ config.enable_processing = true
174
+ config.ensure_multipart_form = true
175
+ config.download_retry_count = 0
176
+ config.download_retry_wait_time = 5
177
+ config.skip_ssrf_protection = false
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,61 @@
1
+ module SalebotUploader
2
+ module Uploader
3
+ module ContentTypeAllowlist
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before :cache, :check_content_type_allowlist!
8
+ end
9
+
10
+ ##
11
+ # Override this method in your uploader to provide an allowlist of files content types
12
+ # which are allowed to be uploaded.
13
+ # Not only strings but Regexp are allowed as well.
14
+ #
15
+ # === Returns
16
+ #
17
+ # [NilClass, String, Regexp, Array[String, Regexp]] an allowlist of content types which are allowed to be uploaded
18
+ #
19
+ # === Examples
20
+ #
21
+ # def content_type_allowlist
22
+ # %w(text/json application/json)
23
+ # end
24
+ #
25
+ # Basically the same, but using a Regexp:
26
+ #
27
+ # def content_type_allowlist
28
+ # [/(text|application)\/json/]
29
+ # end
30
+ #
31
+ def content_type_allowlist; end
32
+
33
+ private
34
+
35
+ def check_content_type_allowlist!(new_file)
36
+ allowlist = content_type_allowlist
37
+ if !allowlist && respond_to?(:content_type_whitelist) && content_type_whitelist
38
+ ActiveSupport::Deprecation.warn "#content_type_whitelist is deprecated, use #content_type_allowlist instead." unless instance_variable_defined?(:@content_type_whitelist_warned)
39
+ @content_type_whitelist_warned = true
40
+ allowlist = content_type_whitelist
41
+ end
42
+
43
+ return unless allowlist
44
+
45
+ content_type = new_file.content_type
46
+ if !allowlisted_content_type?(allowlist, content_type)
47
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.content_type_allowlist_error", content_type: content_type,
48
+ allowed_types: Array(allowlist).join(", "), default: :"errors.messages.content_type_whitelist_error")
49
+ end
50
+ end
51
+
52
+ def allowlisted_content_type?(allowlist, content_type)
53
+ Array(allowlist).any? do |item|
54
+ item = Regexp.quote(item) if item.class != Regexp
55
+ content_type =~ /\A#{item}/
56
+ end
57
+ end
58
+
59
+ end # ContentTypeAllowlist
60
+ end # Uploader
61
+ end # SalebotUploader
@@ -0,0 +1,62 @@
1
+ module SalebotUploader
2
+ module Uploader
3
+ module ContentTypeDenylist
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before :cache, :check_content_type_denylist!
8
+ end
9
+
10
+ ##
11
+ # Override this method in your uploader to provide a denylist of files content types
12
+ # which are not allowed to be uploaded.
13
+ # Not only strings but Regexp are allowed as well.
14
+ #
15
+ # === Returns
16
+ #
17
+ # [NilClass, String, Regexp, Array[String, Regexp]] a denylist of content types which are not allowed to be uploaded
18
+ #
19
+ # === Examples
20
+ #
21
+ # def content_type_denylist
22
+ # %w(text/json application/json)
23
+ # end
24
+ #
25
+ # Basically the same, but using a Regexp:
26
+ #
27
+ # def content_type_denylist
28
+ # [/(text|application)\/json/]
29
+ # end
30
+ #
31
+ def content_type_denylist
32
+ end
33
+
34
+ private
35
+
36
+ def check_content_type_denylist!(new_file)
37
+ denylist = content_type_denylist
38
+ if !denylist && respond_to?(:content_type_blacklist) && content_type_blacklist
39
+ ActiveSupport::Deprecation.warn "#content_type_blacklist is deprecated, use #content_type_denylist instead." unless instance_variable_defined?(:@content_type_blacklist_warned)
40
+ @content_type_blacklist_warned = true
41
+ denylist = content_type_blacklist
42
+ end
43
+
44
+ return unless denylist
45
+
46
+ ActiveSupport::Deprecation.warn "Use of #content_type_denylist is deprecated for the security reason, use #content_type_allowlist instead to explicitly state what are safe to accept" unless instance_variable_defined?(:@content_type_denylist_warned)
47
+ @content_type_denylist_warned = true
48
+
49
+ content_type = new_file.content_type
50
+ if denylisted_content_type?(denylist, content_type)
51
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.content_type_denylist_error",
52
+ content_type: content_type, default: :"errors.messages.content_type_blacklist_error")
53
+ end
54
+ end
55
+
56
+ def denylisted_content_type?(denylist, content_type)
57
+ Array(denylist).any? { |item| content_type =~ /#{item}/ }
58
+ end
59
+
60
+ end # ContentTypeDenylist
61
+ end # Uploader
62
+ end # SalebotUploader
@@ -0,0 +1,17 @@
1
+ module SalebotUploader
2
+ module Uploader
3
+ module DefaultUrl
4
+
5
+ def url(*args)
6
+ super || default_url(*args)
7
+ end
8
+
9
+ ##
10
+ # Override this method in your uploader to provide a default url
11
+ # in case no file has been cached/stored yet.
12
+ #
13
+ def default_url(*args); end
14
+
15
+ end # DefaultPath
16
+ end # Uploader
17
+ end # SalebotUploader
@@ -0,0 +1,66 @@
1
+ require 'active_support'
2
+
3
+ module SalebotUploader
4
+ module Uploader
5
+ module Dimension
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before :cache, :check_dimensions!
10
+ end
11
+
12
+ ##
13
+ # Override this method in your uploader to provide a Range of width which
14
+ # are allowed to be uploaded.
15
+ # === Returns
16
+ #
17
+ # [NilClass, Range] a width range which are permitted to be uploaded
18
+ #
19
+ # === Examples
20
+ #
21
+ # def width_range
22
+ # 1000..2000
23
+ # end
24
+ #
25
+ def width_range; end
26
+
27
+ ##
28
+ # Override this method in your uploader to provide a Range of height which
29
+ # are allowed to be uploaded.
30
+ # === Returns
31
+ #
32
+ # [NilClass, Range] a height range which are permitted to be uploaded
33
+ #
34
+ # === Examples
35
+ #
36
+ # def height_range
37
+ # 1000..
38
+ # end
39
+ #
40
+ def height_range; end
41
+
42
+ private
43
+
44
+ def check_dimensions!(new_file)
45
+ # NOTE: Skip the check for resized images
46
+ return if version_name.present?
47
+ return unless width_range || height_range
48
+
49
+ unless respond_to?(:width) || respond_to?(:height)
50
+ raise 'You need to include one of SalebotUploader::MiniMagick, SalebotUploader::RMagick, or SalebotUploader::Vips to perform image dimension validation'
51
+ end
52
+
53
+ if width_range&.begin && width < width_range.begin
54
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.min_width_error", :min_width => ActiveSupport::NumberHelper.number_to_delimited(width_range.begin))
55
+ elsif width_range&.end && width > width_range.end
56
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.max_width_error", :max_width => ActiveSupport::NumberHelper.number_to_delimited(width_range.end))
57
+ elsif height_range&.begin && height < height_range.begin
58
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.min_height_error", :min_height => ActiveSupport::NumberHelper.number_to_delimited(height_range.begin))
59
+ elsif height_range&.end && height > height_range.end
60
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.max_height_error", :max_height => ActiveSupport::NumberHelper.number_to_delimited(height_range.end))
61
+ end
62
+ end
63
+
64
+ end # Dimension
65
+ end # Uploader
66
+ end # SalebotUploader
@@ -0,0 +1,24 @@
1
+ module SalebotUploader
2
+ module Uploader
3
+ module Download
4
+ extend ActiveSupport::Concern
5
+
6
+ include SalebotUploader::Uploader::Callbacks
7
+ include SalebotUploader::Uploader::Configuration
8
+ include SalebotUploader::Uploader::Cache
9
+
10
+ ##
11
+ # Caches the file by downloading it from the given URL, using downloader.
12
+ #
13
+ # === Parameters
14
+ #
15
+ # [url (String)] The URL where the remote file is stored
16
+ # [remote_headers (Hash)] Request headers
17
+ #
18
+ def download!(uri, remote_headers = {})
19
+ file = downloader.new(self).download(uri, remote_headers)
20
+ cache!(file)
21
+ end
22
+ end # Download
23
+ end # Uploader
24
+ end # SalebotUploader
@@ -0,0 +1,63 @@
1
+ module SalebotUploader
2
+ module Uploader
3
+ module ExtensionAllowlist
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before :cache, :check_extension_allowlist!
8
+ end
9
+
10
+ ##
11
+ # Override this method in your uploader to provide an allowlist of extensions which
12
+ # are allowed to be uploaded. Compares the file's extension case insensitive.
13
+ # Furthermore, not only strings but Regexp are allowed as well.
14
+ #
15
+ # When using a Regexp in the allowlist, `\A` and `\z` are automatically added to
16
+ # the Regexp expression, also case insensitive.
17
+ #
18
+ # === Returns
19
+ #
20
+ # [NilClass, String, Regexp, Array[String, Regexp]] an allowlist of extensions which are allowed to be uploaded
21
+ #
22
+ # === Examples
23
+ #
24
+ # def extension_allowlist
25
+ # %w(jpg jpeg gif png)
26
+ # end
27
+ #
28
+ # Basically the same, but using a Regexp:
29
+ #
30
+ # def extension_allowlist
31
+ # [/jpe?g/, 'gif', 'png']
32
+ # end
33
+ #
34
+ def extension_allowlist
35
+ end
36
+
37
+ private
38
+
39
+ def check_extension_allowlist!(new_file)
40
+ allowlist = extension_allowlist
41
+ if !allowlist && respond_to?(:extension_whitelist) && extension_whitelist
42
+ ActiveSupport::Deprecation.warn "#extension_whitelist is deprecated, use #extension_allowlist instead." unless instance_variable_defined?(:@extension_whitelist_warned)
43
+ @extension_whitelist_warned = true
44
+ allowlist = extension_whitelist
45
+ end
46
+
47
+ return unless allowlist
48
+
49
+ extension = new_file.extension.to_s
50
+ if !allowlisted_extension?(allowlist, extension)
51
+ # Look for whitelist first, then fallback to allowlist
52
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.extension_allowlist_error", extension: new_file.extension.inspect,
53
+ allowed_types: Array(allowlist).join(", "), default: :"errors.messages.extension_whitelist_error")
54
+ end
55
+ end
56
+
57
+ def allowlisted_extension?(allowlist, extension)
58
+ downcase_extension = extension.downcase
59
+ Array(allowlist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
60
+ end
61
+ end # ExtensionAllowlist
62
+ end # Uploader
63
+ end # SalebotUploader
@@ -0,0 +1,64 @@
1
+ module SalebotUploader
2
+ module Uploader
3
+ module ExtensionDenylist
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before :cache, :check_extension_denylist!
8
+ end
9
+
10
+ ##
11
+ # Override this method in your uploader to provide a denylist of extensions which
12
+ # are prohibited to be uploaded. Compares the file's extension case insensitive.
13
+ # Furthermore, not only strings but Regexp are allowed as well.
14
+ #
15
+ # When using a Regexp in the denylist, `\A` and `\z` are automatically added to
16
+ # the Regexp expression, also case insensitive.
17
+ #
18
+ # === Returns
19
+
20
+ # [NilClass, String, Regexp, Array[String, Regexp]] a deny list of extensions which are prohibited to be uploaded
21
+ #
22
+ # === Examples
23
+ #
24
+ # def extension_denylist
25
+ # %w(swf tiff)
26
+ # end
27
+ #
28
+ # Basically the same, but using a Regexp:
29
+ #
30
+ # def extension_denylist
31
+ # [/swf/, 'tiff']
32
+ # end
33
+ #
34
+ def extension_denylist
35
+ end
36
+
37
+ private
38
+
39
+ def check_extension_denylist!(new_file)
40
+ denylist = extension_denylist
41
+ if !denylist && respond_to?(:extension_blacklist) && extension_blacklist
42
+ ActiveSupport::Deprecation.warn "#extension_blacklist is deprecated, use #extension_denylist instead." unless instance_variable_defined?(:@extension_blacklist_warned)
43
+ @extension_blacklist_warned = true
44
+ denylist = extension_blacklist
45
+ end
46
+
47
+ return unless denylist
48
+
49
+ ActiveSupport::Deprecation.warn "Use of #extension_denylist is deprecated for the security reason, use #extension_allowlist instead to explicitly state what are safe to accept" unless instance_variable_defined?(:@extension_denylist_warned)
50
+ @extension_denylist_warned = true
51
+
52
+ extension = new_file.extension.to_s
53
+ if denylisted_extension?(denylist, extension)
54
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.extension_denylist_error", extension: new_file.extension.inspect,
55
+ prohibited_types: Array(extension_denylist).join(", "), default: :"errors.messages.extension_blacklist_error")
56
+ end
57
+ end
58
+
59
+ def denylisted_extension?(denylist, extension)
60
+ Array(denylist).any? { |item| extension =~ /\A#{item}\z/i }
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,43 @@
1
+ require 'active_support'
2
+
3
+ module SalebotUploader
4
+ module Uploader
5
+ module FileSize
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before :cache, :check_size!
10
+ end
11
+
12
+ ##
13
+ # Override this method in your uploader to provide a Range of Size which
14
+ # are allowed to be uploaded.
15
+ # === Returns
16
+ #
17
+ # [NilClass, Range] a size range (in bytes) which are permitted to be uploaded
18
+ #
19
+ # === Examples
20
+ #
21
+ # def size_range
22
+ # 3256...5748
23
+ # end
24
+ #
25
+ def size_range; end
26
+
27
+ private
28
+
29
+ def check_size!(new_file)
30
+ size = new_file.size
31
+ expected_size_range = size_range
32
+ if expected_size_range.is_a?(::Range)
33
+ if size < expected_size_range.min
34
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.min_size_error", :min_size => ActiveSupport::NumberHelper.number_to_human_size(expected_size_range.min))
35
+ elsif size > expected_size_range.max
36
+ raise SalebotUploader::IntegrityError, I18n.translate(:"errors.messages.max_size_error", :max_size => ActiveSupport::NumberHelper.number_to_human_size(expected_size_range.max))
37
+ end
38
+ end
39
+ end
40
+
41
+ end # FileSize
42
+ end # Uploader
43
+ end # SalebotUploader
@@ -0,0 +1,44 @@
1
+ module SalebotUploader
2
+ module Uploader
3
+ module Mountable
4
+
5
+ attr_reader :model, :mounted_as
6
+
7
+ ##
8
+ # If a model is given as the first parameter, it will be stored in the
9
+ # uploader, and available through +#model+. Likewise, mounted_as stores
10
+ # the name of the column where this instance of the uploader is mounted.
11
+ # These values can then be used inside your uploader.
12
+ #
13
+ # If you do not wish to mount your uploaders with the ORM extensions in
14
+ # -more then you can override this method inside your uploader. Just be
15
+ # sure to call +super+
16
+ #
17
+ # === Parameters
18
+ #
19
+ # [model (Object)] Any kind of model object
20
+ # [mounted_as (Symbol)] The name of the column where this uploader is mounted
21
+ #
22
+ # === Examples
23
+ #
24
+ # class MyUploader < SalebotUploader::Uploader::Base
25
+ #
26
+ # def store_dir
27
+ # File.join('public', 'files', mounted_as, model.permalink)
28
+ # end
29
+ # end
30
+ #
31
+ def initialize(model=nil, mounted_as=nil)
32
+ @model = model
33
+ @mounted_as = mounted_as
34
+ end
35
+
36
+ ##
37
+ # Returns array index of given uploader within currently mounted uploaders
38
+ #
39
+ def index
40
+ model.__send__(:_mounter, mounted_as).uploaders.index(self)
41
+ end
42
+ end # Mountable
43
+ end # Uploader
44
+ end # SalebotUploader