attachs 0.3.5 → 0.4.0
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/MIT-LICENSE +1 -1
- data/README.md +254 -0
- data/Rakefile +0 -2
- data/lib/attachs.rb +37 -10
- data/lib/attachs/active_record/base.rb +58 -95
- data/lib/attachs/active_record/connection_adapters.rb +40 -0
- data/lib/attachs/active_record/migration.rb +17 -0
- data/lib/attachs/active_record/validators.rb +7 -0
- data/lib/attachs/active_record/validators/attachment_content_type_validator.rb +30 -0
- data/lib/attachs/active_record/validators/attachment_presence_validator.rb +22 -0
- data/lib/attachs/active_record/validators/attachment_size_validator.rb +39 -0
- data/lib/attachs/attachment.rb +114 -0
- data/{config → lib/attachs}/locales/en.yml +2 -1
- data/{config → lib/attachs}/locales/es.yml +2 -1
- data/lib/attachs/railtie.rb +31 -11
- data/lib/attachs/storages/base.rb +68 -0
- data/lib/attachs/storages/local.rb +61 -37
- data/lib/attachs/storages/s3.rb +66 -57
- data/lib/attachs/tools/magick.rb +52 -0
- data/lib/attachs/types/base.rb +22 -0
- data/lib/attachs/types/default.rb +21 -0
- data/lib/attachs/types/regular.rb +21 -0
- data/lib/attachs/version.rb +1 -1
- data/lib/generators/attachs/install_generator.rb +13 -0
- data/lib/generators/attachs/templates/attachs.rb +2 -0
- data/lib/tasks/attachs.rake +30 -0
- data/test/attachment_test.rb +19 -0
- data/test/dummy/app/models/medium.rb +5 -0
- data/test/dummy/app/models/picture.rb +2 -0
- data/test/dummy/config/application.rb +1 -7
- data/test/dummy/config/initializers/attachs.rb +25 -0
- data/test/dummy/config/initializers/secret_token.rb +1 -0
- data/test/dummy/config/routes.rb +0 -1
- data/test/dummy/db/migrate/20140808012639_create_media.rb +11 -0
- data/test/dummy/db/schema.rb +14 -25
- data/test/dummy/log/development.log +9 -27
- data/test/dummy/log/test.log +52130 -11207
- data/test/dummy/test/fixtures/180x150.gif +0 -0
- data/test/generator_test.rb +18 -0
- data/test/local_storage_test.rb +57 -0
- data/test/magick_tool_test.rb +42 -0
- data/test/migration_test.rb +65 -0
- data/test/s3_storage_tes.rb +56 -0
- data/test/tasks_test.rb +61 -0
- data/test/test_helper.rb +17 -17
- data/test/validators_test.rb +100 -0
- metadata +85 -120
- data/README.rdoc +0 -104
- data/app/controllers/attachs/presets_controller.rb +0 -17
- data/config/routes.rb +0 -5
- data/lib/attachs/engine.rb +0 -7
- data/lib/attachs/magick/image.rb +0 -85
- data/lib/attachs/types/file.rb +0 -131
- data/lib/attachs/types/image.rb +0 -58
- data/lib/attachs/validators/attachment_content_type_validator.rb +0 -11
- data/lib/attachs/validators/attachment_presence_validator.rb +0 -9
- data/lib/attachs/validators/attachment_size_validator.rb +0 -21
- data/lib/attachs/validators/base.rb +0 -13
- data/lib/generators/attachs/s3/config_generator.rb +0 -13
- data/lib/generators/attachs/s3/templates/s3.yml +0 -16
- data/lib/tasks/attachs_tasks.rake +0 -71
- data/test/dummy/app/models/all_attached.rb +0 -16
- data/test/dummy/app/models/file_attached.rb +0 -3
- data/test/dummy/app/models/image_attached.rb +0 -3
- data/test/dummy/app/models/private_file_attached.rb +0 -3
- data/test/dummy/app/models/private_image_attached.rb +0 -3
- data/test/dummy/db/migrate/20130820222342_create_file_attacheds.rb +0 -9
- data/test/dummy/db/migrate/20130820222355_create_image_attacheds.rb +0 -9
- data/test/dummy/db/migrate/20130820222534_create_all_attacheds.rb +0 -19
- data/test/dummy/public/uploads/files/file.txt +0 -1
- data/test/dummy/public/uploads/images/big/image.jpg +0 -0
- data/test/dummy/public/uploads/images/original/image.jpg +0 -0
- data/test/dummy/public/uploads/images/small/image.jpg +0 -0
- data/test/dummy/test/fixtures/file_big.txt +0 -1
- data/test/dummy/test/fixtures/file_empty.txt +0 -1
- data/test/dummy/test/fixtures/image.jpg +0 -0
- data/test/dummy/test/fixtures/image_big.jpg +0 -0
- data/test/dummy/test/fixtures/image_empty.jpg +0 -0
- data/test/dummy/tmp/uploads/files/13898788260004868.txt +0 -1
- data/test/local_file_record_test.rb +0 -31
- data/test/local_file_string_test.rb +0 -23
- data/test/local_file_upload_test.rb +0 -30
- data/test/local_generate_test.rb +0 -25
- data/test/local_image_record_test.rb +0 -25
- data/test/local_image_string_test.rb +0 -34
- data/test/local_image_upload_test.rb +0 -27
- data/test/local_records_test.rb +0 -52
- data/test/local_validators_test.rb +0 -71
- data/test/s3_file_record_tes.rb +0 -21
- data/test/s3_file_string_tes.rb +0 -24
- data/test/s3_file_upload_tes.rb +0 -31
- data/test/s3_image_record_tes.rb +0 -26
- data/test/s3_image_string_tes.rb +0 -31
- data/test/s3_image_upload_tes.rb +0 -28
- data/test/s3_records_tes.rb +0 -56
- data/test/s3_validators_tes.rb +0 -72
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 174763ef00e837f637a02dadcf2c6e732304c911
|
|
4
|
+
data.tar.gz: 543f20a4cfbc0097daa613ec66bf31459191c260
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5fc324cf2d3df019d8d37501e9af50eb1169d3e88b6ba11c6be97afdfd22377d3dd8391e03fb170d051f852b1116da68ce195de93d22bab1f98edf5986bee561
|
|
7
|
+
data.tar.gz: a57ec77ecc61acebed6512bce22a18c0152fc26b9f488f86daeed88f055e44b4284388644bba3ef7500eeecb7f99469e86f94435a356c627b1f77f99800f4c94
|
data/MIT-LICENSE
CHANGED
data/README.md
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
[](http://badge.fury.io/rb/attachs) [](https://codeclimate.com/github/museways/attachs) [](https://travis-ci.org/museways/attachs)
|
|
2
|
+
|
|
3
|
+
# Attachs
|
|
4
|
+
|
|
5
|
+
Minimalistic toolkit to attach files to records.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Put this line in your Gemfile:
|
|
10
|
+
```ruby
|
|
11
|
+
gem 'attachs'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Then bundle:
|
|
15
|
+
```
|
|
16
|
+
$ bundle
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
NOTE: ImageMagick is needed.
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
Generate the configuration file:
|
|
24
|
+
```
|
|
25
|
+
rails g attachs:install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The defaults values are:
|
|
29
|
+
```ruby
|
|
30
|
+
Attachs.configure do |config|
|
|
31
|
+
config.styles = {}
|
|
32
|
+
config.interpolations = {}
|
|
33
|
+
config.global_styles = []
|
|
34
|
+
config.global_convert_options= ''
|
|
35
|
+
config.convert_options = {}
|
|
36
|
+
config.default_storage = :local
|
|
37
|
+
config.default_path = '/:timestamp-:filename'
|
|
38
|
+
config.base_url = ''
|
|
39
|
+
config.s3 = { ssl: false }
|
|
40
|
+
end
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
Add the column to your table:
|
|
46
|
+
```ruby
|
|
47
|
+
create_table :users do |t|
|
|
48
|
+
t.attachment :avatar
|
|
49
|
+
end
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Define the attachment in your model:
|
|
53
|
+
```ruby
|
|
54
|
+
class User < ActiveRecord::Base
|
|
55
|
+
has_attached_file :avatar
|
|
56
|
+
end
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Paths
|
|
60
|
+
|
|
61
|
+
To customize the path to some model:
|
|
62
|
+
```ruby
|
|
63
|
+
class User < ActiveRecord::Base
|
|
64
|
+
has_attached_file :avatar, path: '/:type/:timestamp/:filename'
|
|
65
|
+
end
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
To create custom interpolations:
|
|
69
|
+
```ruby
|
|
70
|
+
Attachs.configure do |config|
|
|
71
|
+
config.interpolations = {
|
|
72
|
+
category: -> (attachment) { attachment.record.category }
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
NOTE: Look into lib/attachs/storages/base.rb to find a list of the system interpolations.
|
|
78
|
+
|
|
79
|
+
## Styles
|
|
80
|
+
|
|
81
|
+
Define the styles of the attachment:
|
|
82
|
+
```ruby
|
|
83
|
+
Attachs.configure do |config|
|
|
84
|
+
config.styles = {
|
|
85
|
+
small: '120x120!', # forces the exact size
|
|
86
|
+
medium: '240x240#', # resizes and crops to fill the desire space
|
|
87
|
+
big: '360x360' # resizes to contain the imagen in the desire space
|
|
88
|
+
}
|
|
89
|
+
end
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Then reference them in your model:
|
|
93
|
+
```ruby
|
|
94
|
+
class User < ActiveRecord::Base
|
|
95
|
+
has_attached_file :avatar, styles: [:small, :medium]
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
To set styles for all attachments:
|
|
100
|
+
```ruby
|
|
101
|
+
Attachs.configure do |config|
|
|
102
|
+
config.global_styles = [:big]
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Convert
|
|
107
|
+
|
|
108
|
+
To define global convert options:
|
|
109
|
+
```ruby
|
|
110
|
+
Attachs.configure do |config|
|
|
111
|
+
config.global_convert_options = '-quality 75 -strip'
|
|
112
|
+
end
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
To set convert options to some styles only:
|
|
116
|
+
```ruby
|
|
117
|
+
Attachs.configure do |config|
|
|
118
|
+
config.convert_options = {
|
|
119
|
+
medium: '-trim'
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Security
|
|
125
|
+
|
|
126
|
+
To make the attachment private:
|
|
127
|
+
```ruby
|
|
128
|
+
class User < ActiveRecord::Base
|
|
129
|
+
has_attached_file :avatar, private: true
|
|
130
|
+
end
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
NOTE: Private attachments will be saved into /private folder.
|
|
134
|
+
|
|
135
|
+
## Validations
|
|
136
|
+
|
|
137
|
+
To validate the presence of the attachment:
|
|
138
|
+
```ruby
|
|
139
|
+
class User < ActiveRecord::Base
|
|
140
|
+
has_attached_file :avatar
|
|
141
|
+
validates_attachment_presence_of :avatar
|
|
142
|
+
end
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
To validate the size of the attachment:
|
|
146
|
+
```ruby
|
|
147
|
+
class User < ActiveRecord::Base
|
|
148
|
+
has_attached_file :avatar
|
|
149
|
+
validates_attachment_size_of :avatar, in: 1..5.megabytes
|
|
150
|
+
end
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
To validate the content type of the attachment:
|
|
154
|
+
```ruby
|
|
155
|
+
class User < ActiveRecord::Base
|
|
156
|
+
has_attached_file :avatar
|
|
157
|
+
validates_attachment_content_type_of :avatar, with: /\Aimage/
|
|
158
|
+
# Or using a list
|
|
159
|
+
validates_attachment_content_type_of :avatar, in: %w(image/jpg image/png)
|
|
160
|
+
end
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## I18n
|
|
164
|
+
|
|
165
|
+
To translate the messages the keys are:
|
|
166
|
+
```
|
|
167
|
+
errors.messages.attachment_presence
|
|
168
|
+
errors.messages.attachment_size_in
|
|
169
|
+
errors.messages.attachment_size_less_than
|
|
170
|
+
errors.messages.attachment_size_greater_than
|
|
171
|
+
errors.messages.attachment_content_type_with
|
|
172
|
+
errors.messages.attachment_content_type_in
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
NOTE: Look into lib/attachs/locales yamls.
|
|
176
|
+
|
|
177
|
+
## Forms
|
|
178
|
+
|
|
179
|
+
Your forms continue to work the same:
|
|
180
|
+
```erb
|
|
181
|
+
<%= form_for @user do |f| %>
|
|
182
|
+
<%= f.file_field :avatar %>
|
|
183
|
+
<% end %>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Urls
|
|
187
|
+
|
|
188
|
+
The url method points to the original file:
|
|
189
|
+
```erb
|
|
190
|
+
<%= image_tag user.avatar.url %>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
To point to some particular style:
|
|
194
|
+
```erb
|
|
195
|
+
<%= image_tag user.avatar.url(:small) %>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The defauft url is used when there is no upload:
|
|
199
|
+
```ruby
|
|
200
|
+
class User < ActiveRecord::Base
|
|
201
|
+
has_attached_file :avatar, default_url: '/missing.png'
|
|
202
|
+
end
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
NOTE: If storage is s3 you can pass ssl: true to force https.
|
|
206
|
+
|
|
207
|
+
## Storage
|
|
208
|
+
|
|
209
|
+
To override the storage in the model:
|
|
210
|
+
```ruby
|
|
211
|
+
class User < ActiveRecord::Base
|
|
212
|
+
has_attached_file :avatar, storage: :s3
|
|
213
|
+
end
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
To configure the s3 credentials:
|
|
217
|
+
```ruby
|
|
218
|
+
Attachs.configure do |config|
|
|
219
|
+
config.s3 = {
|
|
220
|
+
bucket: 'xxx',
|
|
221
|
+
access_key_id: 'xxx',
|
|
222
|
+
secret_access_key: 'xxx'
|
|
223
|
+
}
|
|
224
|
+
end
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## CDN
|
|
228
|
+
|
|
229
|
+
To configure a cdn:
|
|
230
|
+
```ruby
|
|
231
|
+
Attachs.configure do |config|
|
|
232
|
+
config.base_url = 'http://cdn.example.com'
|
|
233
|
+
end
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Tasks
|
|
237
|
+
|
|
238
|
+
To refresh all the styles of some attachment:
|
|
239
|
+
```
|
|
240
|
+
bundle exec rake attachs:refresh:all CLASS=User ATTACHMENT=avatar
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
To refresh missing styles of some attachment:
|
|
244
|
+
```
|
|
245
|
+
bundle exec rake attachs:refresh:missing CLASS=User ATTACHMENT=avatar
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Credits
|
|
249
|
+
|
|
250
|
+
This gem is maintained and funded by [museways](http://museways.com).
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
|
data/Rakefile
CHANGED
data/lib/attachs.rb
CHANGED
|
@@ -1,16 +1,43 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require 'attachs/
|
|
1
|
+
require 'open3'
|
|
2
|
+
require 'attachs/attachment'
|
|
3
|
+
require 'attachs/tools/magick'
|
|
4
|
+
require 'attachs/storages/base'
|
|
3
5
|
require 'attachs/storages/local'
|
|
4
6
|
require 'attachs/storages/s3'
|
|
5
|
-
require 'attachs/types/
|
|
6
|
-
require 'attachs/types/
|
|
7
|
-
require 'attachs/
|
|
8
|
-
require 'attachs/
|
|
9
|
-
require 'attachs/
|
|
10
|
-
require 'attachs/
|
|
11
|
-
require 'attachs/
|
|
7
|
+
require 'attachs/types/base'
|
|
8
|
+
require 'attachs/types/default'
|
|
9
|
+
require 'attachs/types/regular'
|
|
10
|
+
require 'attachs/active_record/base'
|
|
11
|
+
require 'attachs/active_record/connection_adapters'
|
|
12
|
+
require 'attachs/active_record/migration'
|
|
13
|
+
require 'attachs/active_record/validators'
|
|
14
|
+
require 'attachs/active_record/validators/attachment_content_type_validator'
|
|
15
|
+
require 'attachs/active_record/validators/attachment_presence_validator'
|
|
16
|
+
require 'attachs/active_record/validators/attachment_size_validator'
|
|
12
17
|
require 'attachs/railtie'
|
|
13
|
-
require 'attachs/version'
|
|
14
18
|
|
|
15
19
|
module Attachs
|
|
20
|
+
class << self
|
|
21
|
+
|
|
22
|
+
def configure
|
|
23
|
+
yield config
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def config
|
|
27
|
+
@config ||= begin
|
|
28
|
+
ActiveSupport::OrderedOptions.new.tap do |config|
|
|
29
|
+
config.styles = {}
|
|
30
|
+
config.interpolations = {}
|
|
31
|
+
config.global_styles = []
|
|
32
|
+
config.global_convert_options= ''
|
|
33
|
+
config.convert_options = {}
|
|
34
|
+
config.default_storage = :local
|
|
35
|
+
config.default_path = '/:timestamp-:filename'
|
|
36
|
+
config.base_url = ''
|
|
37
|
+
config.s3 = { ssl: false }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
16
43
|
end
|
|
@@ -5,136 +5,99 @@ module Attachs
|
|
|
5
5
|
|
|
6
6
|
protected
|
|
7
7
|
|
|
8
|
-
attr_reader :stored_attachments, :deleted_attachments
|
|
9
|
-
|
|
10
8
|
def attachments
|
|
11
|
-
@attachments ||= {}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
attachments[attr] = attachment
|
|
17
|
-
write_attribute attr, attachment.filename
|
|
9
|
+
@attachments ||= {}.tap do |instances|
|
|
10
|
+
self.class.attachments.each do |attr, options|
|
|
11
|
+
instances[attr] = Attachs::Attachment.new(self, attr, options)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
18
14
|
end
|
|
19
15
|
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
return nil unless read_attribute(attr) or options.has_key? :default
|
|
23
|
-
attachments[attr] = build_attachment_instance(read_attribute(attr), options)
|
|
16
|
+
def queued_attachments
|
|
17
|
+
@queued_attachments ||= { process: {}, destroy: {} }
|
|
24
18
|
end
|
|
25
19
|
|
|
26
|
-
def
|
|
27
|
-
|
|
20
|
+
def queue_attachment(attr, options, value)
|
|
21
|
+
unless queued_attachments[:destroy].has_key? attr
|
|
22
|
+
queued_attachments[:destroy][attr] = attachments[attr]
|
|
23
|
+
end
|
|
24
|
+
if queued_attachments[:process].has_key? attr and value.nil?
|
|
25
|
+
attachments[attr]
|
|
26
|
+
else
|
|
27
|
+
queued_attachments[:process][attr] = Attachs::Attachment.new(self, attr, options, value)
|
|
28
|
+
end
|
|
28
29
|
end
|
|
29
30
|
|
|
30
|
-
def
|
|
31
|
-
klass = options.has_key?(:type) ? options[:type].to_s.classify : 'File'
|
|
32
|
-
Attachs::Types.const_get(klass).new source, options
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def check_changed_attachments
|
|
36
|
-
@stored_attachments = []
|
|
37
|
-
@deleted_attachments = []
|
|
31
|
+
def commit_attachments
|
|
38
32
|
self.class.attachments.each do |attr, options|
|
|
39
|
-
|
|
40
|
-
stored = attributes[attr.to_s]
|
|
41
|
-
deleted = changed_attributes[attr.to_s]
|
|
42
|
-
add_changed_attachment stored, options, :stored if stored.present?
|
|
43
|
-
add_changed_attachment deleted, options, :deleted if deleted.present?
|
|
44
|
-
end
|
|
33
|
+
send "destroy_#{attr}=", nil
|
|
45
34
|
end
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def iterate_attachments
|
|
49
|
-
self.class.attachments.each do |attr, options|
|
|
50
|
-
next unless instance = send(attr)
|
|
51
|
-
yield instance
|
|
35
|
+
queued_attachments[:destroy].each do |attr, attachment|
|
|
36
|
+
attachment.destroy
|
|
52
37
|
end
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def store_attachments
|
|
60
|
-
iterate_attachments { |a| a.store }
|
|
38
|
+
queued_attachments[:process].each do |attr, attachment|
|
|
39
|
+
attachment.process
|
|
40
|
+
end
|
|
41
|
+
queued_attachments[:destroy] = {}
|
|
42
|
+
queued_attachments[:process] = {}
|
|
61
43
|
end
|
|
62
44
|
|
|
63
|
-
def
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def remove_stored_attachments
|
|
68
|
-
stored_attachments.each { |a| a.delete }
|
|
45
|
+
def destroy_attachments
|
|
46
|
+
self.class.attachments.each do |attr, options|
|
|
47
|
+
send(attr).destroy
|
|
48
|
+
end
|
|
69
49
|
end
|
|
70
|
-
|
|
71
|
-
def remove_deleted_attachments
|
|
72
|
-
deleted_attachments.each { |a| a.delete }
|
|
73
|
-
end
|
|
74
50
|
|
|
75
51
|
module ClassMethods
|
|
76
52
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
53
|
+
def has_attached_file(*args)
|
|
54
|
+
options = args.extract_options!
|
|
55
|
+
unless attachable?
|
|
56
|
+
make_attachable
|
|
57
|
+
end
|
|
58
|
+
args.each do |attr|
|
|
59
|
+
define_attachment_methods attr, options
|
|
60
|
+
attachments[attr] = options
|
|
83
61
|
end
|
|
84
|
-
alias_method :"attached_#{type}", name
|
|
85
62
|
end
|
|
86
63
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def inherited(subclass)
|
|
90
|
-
subclass.instance_variable_set :@attachments, @attachments
|
|
91
|
-
super
|
|
64
|
+
def attachments
|
|
65
|
+
@attachments ||= {}
|
|
92
66
|
end
|
|
93
67
|
|
|
94
68
|
def attachable?
|
|
95
|
-
attachments.
|
|
69
|
+
attachments.any?
|
|
96
70
|
end
|
|
97
71
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
options = args.extract_options!
|
|
102
|
-
make_attachable unless attachable?
|
|
103
|
-
args.each do |attr|
|
|
104
|
-
define_attachment_attribute_methods attr, options
|
|
105
|
-
define_attachment_default_validations attr, options
|
|
106
|
-
attachments[attr] = options
|
|
107
|
-
end
|
|
72
|
+
def inherited(subclass)
|
|
73
|
+
subclass.instance_variable_set :@attachments, @attachments
|
|
74
|
+
super
|
|
108
75
|
end
|
|
109
76
|
|
|
77
|
+
protected
|
|
78
|
+
|
|
110
79
|
def make_attachable
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
before_destroy :delete_attachments
|
|
114
|
-
after_rollback :remove_stored_attachments
|
|
115
|
-
@attachments = {}
|
|
80
|
+
after_save :commit_attachments
|
|
81
|
+
after_destroy :destroy_attachments
|
|
116
82
|
end
|
|
117
83
|
|
|
118
|
-
def
|
|
84
|
+
def define_attachment_methods(attr, options)
|
|
119
85
|
define_method "#{attr}=" do |value|
|
|
120
|
-
|
|
86
|
+
attachments[attr] = queue_attachment(attr, options, value)
|
|
121
87
|
end
|
|
122
88
|
define_method attr do
|
|
123
|
-
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
instance_variable_set
|
|
89
|
+
attachments[attr]
|
|
90
|
+
end
|
|
91
|
+
attr_reader "destroy_#{attr}"
|
|
92
|
+
define_method "destroy_#{attr}=" do |value|
|
|
93
|
+
instance_variable_set "@destroy_#{attr}", value
|
|
94
|
+
if [1, '1', true].include?(value) and !send(attr).upload?
|
|
95
|
+
send "#{attr}=", nil
|
|
96
|
+
end
|
|
128
97
|
end
|
|
129
|
-
attr_reader :"delete_#{attr}"
|
|
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
98
|
end
|
|
136
99
|
|
|
137
|
-
end
|
|
100
|
+
end
|
|
138
101
|
end
|
|
139
102
|
end
|
|
140
103
|
end
|