attachs 0.3.2 → 0.3.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6376bae7f409923ee076e8f0b4eba342e0b107b4
4
- data.tar.gz: c9cf65c444e4e9538ee0d99fdd7a77a5b26a6f04
3
+ metadata.gz: d4b7e169e9f30ad2bf78cb7f234ff71814200ad6
4
+ data.tar.gz: b8a1b2b599f222bf759809834c9e492389629ef0
5
5
  SHA512:
6
- metadata.gz: e34990d1ba9a0f1dbb33300c3bea569d1ecde6645368f7f3f269d2e2742c6d9b0ea2e288910f03d28373cfa86a82705ca6281168b4cf7c311f2290a917f2cbe6
7
- data.tar.gz: 57f8213edd2ddbafd31ea2257a7fb9c64ad833a06cdf99259156bc3ed6bd64d8f5a067f339d88c94c6b85da2e090b9b4b53db717a3cb2a4a183afa5ff0af45cd
6
+ metadata.gz: 2ab3ab663652618fbe9bf500def726a1f101bbb695d7a7bd6ba30b57963fe1b4d2f6b3892d974764b850c53c5f9b0c08b6903acdd782a6e8ad3e258372a27c02
7
+ data.tar.gz: 45bf708582744d4c012e5b739f921a3c1fc72e4ec2824516dbf9dfa0be08d185956e952f7159f9f25755ca977a343534e3854567be38a598ab8ffaf50e68eb20
data/README.rdoc CHANGED
@@ -18,7 +18,7 @@ ImageMagick must be install, you can install it with homebrew:
18
18
  = Usage
19
19
 
20
20
  Mount the engine at the end of you routes.rb (only if you are using local storage):
21
- mount Attachs:Engine: '/' # Will be use to generate on the fly missing image presets
21
+ mount Attachs::Engine => '/' # Will be use to generate on the fly missing image presets
22
22
 
23
23
  Add the column to your table (just a string):
24
24
  create_table :models do |t|
@@ -35,6 +35,8 @@ If you need a image:
35
35
  has_attached_image :attr, presets: [:small, :big], default: 'assets/image.jpg'
36
36
  end
37
37
 
38
+ (If you want your attachment to be private add private: true to the parameters)
39
+
38
40
  Define presets in your application.rb
39
41
  config.attachs.presets = {
40
42
  big: { method: :fit, width: 1024, height: 768 }, # Fit will scale the image until it fit in the space without cropping
@@ -73,6 +75,10 @@ If your file it's optional:
73
75
 
74
76
  = FAQ
75
77
 
78
+ == Where my private files are stored?
79
+
80
+ In a folder named "private" in the root directory of your app.
81
+
76
82
  == How can I use a cdn with this plugin?
77
83
 
78
84
  Define a base url in your application.rb:
@@ -3,20 +3,6 @@ module Attachs
3
3
  module Base
4
4
  extend ActiveSupport::Concern
5
5
 
6
- included do
7
- singleton_class.class_eval do
8
- [:file, :image].each do |type|
9
- name = :"has_attached_#{type}"
10
- define_method name do |*args|
11
- options = args.extract_options!
12
- options[:type] = type
13
- define_attachment *args.append(options)
14
- end
15
- alias_method :"attached_#{type}", name
16
- end
17
- end
18
- end
19
-
20
6
  protected
21
7
 
22
8
  attr_reader :stored_attachments, :deleted_attachments
@@ -24,6 +10,22 @@ module Attachs
24
10
  def attachments
25
11
  @attachments ||= {}
26
12
  end
13
+
14
+ def add_attachment(attr, value, options)
15
+ attachment = build_attachment_instance(value, options)
16
+ attachments[attr] = attachment
17
+ write_attribute attr, attachment.filename
18
+ end
19
+
20
+ def get_attachment(attr, options)
21
+ return attachments[attr] if attachments.has_key? attr
22
+ return nil unless read_attribute(attr) or options.has_key? :default
23
+ attachments[attr] = build_attachment_instance(read_attribute(attr), options)
24
+ end
25
+
26
+ def remove_attachment(attr)
27
+ write_attribute attr, nil
28
+ end
27
29
 
28
30
  def build_attachment_instance(source, options)
29
31
  klass = options.has_key?(:type) ? options[:type].to_s.classify : 'File'
@@ -59,7 +61,7 @@ module Attachs
59
61
  end
60
62
 
61
63
  def delete_attachments
62
- iterate_attachments { |a| a.delete }
64
+ iterate_attachments { |a| a.delete }
63
65
  end
64
66
 
65
67
  def remove_stored_attachments
@@ -72,6 +74,16 @@ module Attachs
72
74
 
73
75
  module ClassMethods
74
76
 
77
+ [:file, :image].each do |type|
78
+ name = :"has_attached_#{type}"
79
+ define_method name do |*args|
80
+ options = args.extract_options!
81
+ options[:type] = type
82
+ define_attachment *args.map(&:to_sym).append(options)
83
+ end
84
+ alias_method :"attached_#{type}", name
85
+ end
86
+
75
87
  attr_reader :attachments
76
88
 
77
89
  def inherited(subclass)
@@ -89,9 +101,9 @@ module Attachs
89
101
  options = args.extract_options!
90
102
  make_attachable unless attachable?
91
103
  args.each do |attr|
92
- define_attachable_attribute_methods attr.to_sym, options
93
- define_default_validations attr.to_sym, options
94
- attachments[attr.to_sym] = options
104
+ define_attachment_attribute_methods attr, options
105
+ define_attachment_default_validations attr, options
106
+ attachments[attr] = options
95
107
  end
96
108
  end
97
109
 
@@ -103,41 +115,24 @@ module Attachs
103
115
  @attachments = {}
104
116
  end
105
117
 
106
- def define_default_validations(attr, options)
107
- default_validations = Rails.application.config.attachs.default_validations[options[:type]]
108
- validates attr, default_validations.dup if default_validations.present?
109
- end
110
-
111
- def define_attachable_attribute_methods(attr, options)
112
- ['set','get'].each { |method| send "define_attachable_attribute_method_#{method}", attr, options }
113
- end
114
-
115
- def define_attachable_attribute_method_set(attr, options)
118
+ def define_attachment_attribute_methods(attr, options)
116
119
  define_method "#{attr}=" do |value|
117
- if value.is_a? ActionDispatch::Http::UploadedFile or value.is_a? Rack::Test::UploadedFile or (value.is_a? String and value =~ /^[a-zA-Z0-9_-]+\.[a-zA-z]+$/)
118
- attachment = build_attachment_instance(value, options)
119
- attachments[attr] = attachment
120
- write_attribute attr, attachment.filename
121
- end
120
+ add_attachment attr, value, options if value.is_a? ActionDispatch::Http::UploadedFile or value.is_a? Rack::Test::UploadedFile
122
121
  end
122
+ define_method attr do
123
+ get_attachment attr, options
124
+ end
123
125
  define_method "delete_#{attr}=" do |value|
124
- if attribute_present? attr and value == '1'
125
- send "#{attr}_will_change!"
126
- attachments[attr] = nil
127
- attributes[attr.to_s] = nil
128
- end
126
+ remove_attachment attr if value == '1'
129
127
  instance_variable_set :"@delete_#{attr}", value
130
128
  end
131
- end
132
-
133
- def define_attachable_attribute_method_get(attr, options)
134
- define_method attr do
135
- return attachments[attr] if attachments.has_key? attr
136
- return nil unless super() or options.has_key? :default
137
- attachments[attr] = build_attachment_instance(super(), options)
138
- end
139
129
  attr_reader :"delete_#{attr}"
140
130
  end
131
+
132
+ def define_attachment_default_validations(attr, options)
133
+ default_validations = Rails.application.config.attachs.default_validations[options[:type]]
134
+ validates attr, default_validations.dup if default_validations.present?
135
+ end
141
136
 
142
137
  end
143
138
  end
@@ -2,8 +2,9 @@ module Attachs
2
2
  module Storages
3
3
  class Local
4
4
 
5
- def initialize(default)
5
+ def initialize(default, private)
6
6
  @tmp = (Rails.env.test? and !default)
7
+ @private = private
7
8
  end
8
9
 
9
10
  def exists?(path)
@@ -19,7 +20,7 @@ module Attachs
19
20
  end
20
21
 
21
22
  def url(path)
22
- ::File.join Rails.application.config.attachs.base_url, path
23
+ ::File.join Rails.application.config.attachs.base_url, path unless private?
23
24
  end
24
25
 
25
26
  def store(upload, path)
@@ -47,8 +48,12 @@ module Attachs
47
48
  @tmp == true
48
49
  end
49
50
 
51
+ def private?
52
+ @private == true
53
+ end
54
+
50
55
  def base_path
51
- Rails.root.join tmp? ? 'tmp' : 'public'
56
+ Rails.root.join tmp? ? 'tmp' : private? ? 'private' : 'public'
52
57
  end
53
58
 
54
59
  def create_dir(path)
@@ -4,7 +4,7 @@ module Attachs
4
4
 
5
5
  cattr_accessor :config
6
6
 
7
- def initialize(default)
7
+ def initialize(default, private)
8
8
  if (Rails.env.test? and !default)
9
9
  env = 'test'
10
10
  elsif default
@@ -12,9 +12,9 @@ module Attachs
12
12
  else
13
13
  env = Rails.env
14
14
  end
15
- config = self.class.config[env]
16
- AWS.config access_key_id: config['access_key_id'], secret_access_key: config['secret_access_key']
17
- @bucket = AWS::S3.new.buckets[config['bucket']]
15
+ AWS.config access_key_id: config[env]['access_key_id'], secret_access_key: config[env]['secret_access_key']
16
+ @bucket = AWS::S3.new.buckets[config[env]['bucket']]
17
+ @private = private
18
18
  end
19
19
 
20
20
  def exists?(path)
@@ -26,12 +26,11 @@ module Attachs
26
26
  end
27
27
 
28
28
  def url(path)
29
- base_url = Rails.application.config.attachs.base_url
30
29
  base_url.present? ? ::File.join(base_url, path) : object(path).public_url(secure: false)
31
30
  end
32
31
 
33
32
  def store(upload, path)
34
- bucket.objects.create(path, Pathname.new(upload.path)).acl = :public_read
33
+ bucket.objects.create(path, Pathname.new(upload.path)).acl = private? ? :private : :public_read
35
34
  end
36
35
 
37
36
  def delete(path)
@@ -43,7 +42,7 @@ module Attachs
43
42
  if upload.present?
44
43
  cache[source] = upload.path
45
44
  else
46
- remote = create_tmp_file
45
+ remote = create_tmp
47
46
  remote.binmode
48
47
  object(source).read { |chunk| remote.write(chunk) }
49
48
  remote.close
@@ -51,7 +50,7 @@ module Attachs
51
50
  cache[source] = remote.path
52
51
  end
53
52
  end
54
- tmp = create_tmp_file
53
+ tmp = create_tmp
55
54
  yield Attachs::Magick::Image.new(cache[source], tmp.path)
56
55
  store tmp, output
57
56
  end
@@ -59,9 +58,21 @@ module Attachs
59
58
  protected
60
59
 
61
60
  attr_reader :bucket
61
+
62
+ def config
63
+ self.class.config
64
+ end
65
+
66
+ def base_url
67
+ Rails.application.config.attachs.base_url
68
+ end
69
+
70
+ def private?
71
+ @private
72
+ end
62
73
 
63
- def create_tmp_file
64
- Tempfile.new('s3')
74
+ def create_tmp
75
+ Tempfile.new 's3'
65
76
  end
66
77
 
67
78
  def cache
@@ -3,6 +3,8 @@ module Attachs
3
3
  class File
4
4
 
5
5
  def initialize(source, options={})
6
+ @options = options
7
+ @deleted = false
6
8
  if source.is_a? ActionDispatch::Http::UploadedFile or source.is_a? Rack::Test::UploadedFile
7
9
  @upload = source
8
10
  @stored = false
@@ -21,8 +23,10 @@ module Attachs
21
23
  @default = true
22
24
  @storage = build_storage
23
25
  end
24
- @deleted = false
25
- @options = options
26
+ end
27
+
28
+ def private?
29
+ @options and @options[:private] == true
26
30
  end
27
31
 
28
32
  def default?
@@ -68,17 +72,17 @@ module Attachs
68
72
  end
69
73
 
70
74
  def realpath(*args)
71
- return nil if deleted? or Rails.application.config.attachs.storage == :s3
75
+ return nil if deleted? or storage_type == :s3
72
76
  (stored? ? storage.realpath(path(*args)) : upload.path).to_s
73
77
  end
74
78
 
75
79
  def url(*args)
76
- return nil if deleted? or not stored?
80
+ return nil if deleted? or !stored?
77
81
  storage.url(path(*args)).to_s
78
82
  end
79
83
 
80
84
  def store
81
- if not stored? and upload?
85
+ if !stored? and upload?
82
86
  @storage = build_storage
83
87
  storage.store upload, destination_path
84
88
  yield if block_given?
@@ -88,7 +92,7 @@ module Attachs
88
92
  end
89
93
 
90
94
  def delete
91
- if not default? and stored? and exists?
95
+ if !default? and stored? and exists?
92
96
  storage.delete path
93
97
  yield if block_given?
94
98
  @storage = build_storage(:local) if upload?
@@ -101,9 +105,13 @@ module Attachs
101
105
 
102
106
  attr_reader :upload, :storage, :options
103
107
 
108
+ def storage_type
109
+ Rails.application.config.attachs.storage
110
+ end
111
+
104
112
  def build_storage(type=nil)
105
- type ||= Rails.application.config.attachs.storage
106
- Attachs::Storages.const_get(type.to_s.classify).new default?
113
+ klass = (type || storage_type).to_s.classify
114
+ Attachs::Storages.const_get(klass).new default?, private?
107
115
  end
108
116
 
109
117
  def upload?
@@ -3,7 +3,7 @@ module Attachs
3
3
  class Image < File
4
4
 
5
5
  def presets
6
- Rails.application.config.attachs.default_presets | (options[:presets] || [])
6
+ default_presets | parse_array_setting(options[:presets])
7
7
  end
8
8
 
9
9
  def store
@@ -11,26 +11,44 @@ module Attachs
11
11
  end
12
12
 
13
13
  def delete
14
- super { presets.each { |name| storage.delete path(name) if exists?(name) } if presets.any? }
14
+ super { presets.each { |name| delete_preset name } if presets.any? }
15
15
  end
16
16
 
17
17
  def generate_preset(name)
18
- storage.magick destination_path, destination_path(name), upload do |image|
19
- settings = Rails.application.config.attachs.presets[name]
20
- if settings.respond_to? :call
21
- settings.call image
22
- else
23
- image.send "resize_to_#{settings[:method] || 'fill'}", settings[:width], settings[:height]
18
+ if settings = Rails.application.config.attachs.presets[name]
19
+ storage.magick destination_path, destination_path(name), upload do |image|
20
+ if settings.respond_to? :call
21
+ settings.call image
22
+ else
23
+ image.send "resize_to_#{settings[:method] || 'fill'}", settings[:width], settings[:height]
24
+ end
24
25
  end
25
26
  end
26
27
  end
27
28
 
28
29
  def delete_preset(name)
29
- storage.delete path(name)
30
+ storage.delete path(name) if exists?(name)
30
31
  end
31
32
 
32
33
  protected
33
34
 
35
+ def parse_array_setting(value)
36
+ case value
37
+ when Symbol
38
+ [value]
39
+ when String
40
+ [value.to_sym]
41
+ when Array
42
+ value
43
+ else
44
+ []
45
+ end
46
+ end
47
+
48
+ def default_presets
49
+ parse_array_setting Rails.application.config.attachs.default_presets
50
+ end
51
+
34
52
  def store_path(*args)
35
53
  ::File.join 'images', (args[0] ? args[0].to_s.gsub('_', '-') : 'original')
36
54
  end
@@ -1,9 +1,9 @@
1
1
  class AttachmentContentTypeValidator < Attachs::Validators::Base
2
2
 
3
3
  def validate_each(record, attribute, value)
4
- if value.present? and not value.default?
5
- unless options[:in].include? value.extname.from(1)
6
- add_error record, attribute, 'errors.messages.attachment_content_type', types: options[:in].to_sentence
4
+ if value.present? and !value.default?
5
+ if options[:in].exclude? value.extname.from(1)
6
+ add_error record, attribute, 'attachment_content_type', types: options[:in].to_sentence
7
7
  end
8
8
  end
9
9
  end
@@ -1,8 +1,8 @@
1
1
  class AttachmentPresenceValidator < Attachs::Validators::Base
2
2
 
3
3
  def validate_each(record, attribute, value)
4
- unless value.present? and value.exists? and not value.default?
5
- add_error record, attribute, 'errors.messages.attachment_presence'
4
+ unless value.present? and value.exists? and !value.default?
5
+ add_error record, attribute, 'attachment_presence'
6
6
  end
7
7
  end
8
8
 
@@ -2,9 +2,9 @@ class AttachmentSizeValidator < Attachs::Validators::Base
2
2
  include ActionView::Helpers::NumberHelper
3
3
 
4
4
  def validate_each(record, attribute, value)
5
- if value.present? and not value.default?
5
+ if value.present? and !value.default?
6
6
  if options.has_key? :in
7
- unless options[:in].include? value.size
7
+ if options[:in].exclude? value.size
8
8
  add_error record, attribute, 'attachment_size_in', min: number_to_human_size(options[:in].begin), max: number_to_human_size(options[:in].end)
9
9
  end
10
10
  else
@@ -18,10 +18,4 @@ class AttachmentSizeValidator < Attachs::Validators::Base
18
18
  end
19
19
  end
20
20
 
21
- protected
22
-
23
- def add_error(record, attribute, type, options)
24
- super(record, attribute, "errors.messages.#{type}", options)
25
- end
26
-
27
21
  end