attachs 0.4.5 → 4.0.0.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 +83 -218
- data/Rakefile +1 -14
- data/lib/attachs.rb +98 -31
- data/lib/attachs/attachment.rb +301 -72
- data/lib/attachs/builder.rb +78 -0
- data/lib/attachs/collection.rb +84 -0
- data/lib/attachs/concern.rb +47 -0
- data/lib/attachs/configuration.rb +11 -0
- data/lib/attachs/console.rb +40 -0
- data/lib/attachs/extensions/active_record/base.rb +24 -0
- data/lib/attachs/extensions/active_record/validations/attachment_content_type_validator.rb +37 -0
- data/lib/attachs/extensions/active_record/validations/attachment_presence_validator.rb +27 -0
- data/lib/attachs/extensions/active_record/validations/attachment_size_validator.rb +55 -0
- data/lib/attachs/extensions/active_record/validations/attachment_validator.rb +24 -0
- data/lib/attachs/interpolations.rb +27 -0
- data/lib/attachs/jobs/base.rb +14 -0
- data/lib/attachs/jobs/delete_job.rb +15 -0
- data/lib/attachs/jobs/update_job.rb +11 -0
- data/lib/attachs/locales/en.yml +2 -6
- data/lib/attachs/locales/es.yml +2 -6
- data/lib/attachs/processors/base.rb +4 -14
- data/lib/attachs/processors/image.rb +45 -0
- data/lib/attachs/railtie.rb +7 -27
- data/lib/attachs/storages/base.rb +10 -59
- data/lib/attachs/storages/s3.rb +68 -63
- data/lib/attachs/version.rb +1 -1
- data/lib/generators/attachs/install/install_generator.rb +15 -0
- data/lib/generators/attachs/install/templates/initializer.rb +7 -0
- data/lib/generators/attachs/upload/templates/migration.rb +11 -0
- data/lib/generators/attachs/upload/templates/model.rb +19 -0
- data/lib/generators/attachs/upload/upload_generator.rb +24 -0
- data/lib/tasks/attachs.rake +12 -26
- data/test/attachment_test.rb +175 -12
- data/test/collection_test.rb +52 -0
- data/test/concern_test.rb +10 -0
- data/test/dummy/Rakefile +1 -2
- data/test/dummy/app/assets/javascripts/application.js +2 -2
- data/test/dummy/app/assets/stylesheets/application.css +6 -4
- data/test/dummy/app/models/product.rb +16 -0
- data/test/dummy/app/models/shop.rb +14 -0
- data/test/dummy/app/models/upload.rb +19 -0
- data/test/dummy/app/views/layouts/application.html.erb +9 -11
- data/test/dummy/bin/bundle +1 -0
- data/test/dummy/bin/rails +2 -1
- data/test/dummy/bin/rake +1 -0
- data/test/dummy/bin/setup +30 -0
- data/test/dummy/config.ru +1 -1
- data/test/dummy/config/application.rb +3 -2
- data/test/dummy/config/boot.rb +1 -1
- data/test/dummy/config/database.yml +4 -22
- data/test/dummy/config/database.yml.travis +3 -0
- data/test/dummy/config/environment.rb +1 -1
- data/test/dummy/config/environments/development.rb +15 -3
- data/test/dummy/config/environments/production.rb +21 -26
- data/test/dummy/config/environments/test.rb +10 -12
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/attachs.rb +7 -21
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/mime_types.rb +1 -2
- data/test/dummy/config/initializers/session_store.rb +1 -1
- data/test/dummy/config/routes.rb +54 -0
- data/test/dummy/config/secrets.yml +24 -0
- data/test/dummy/db/migrate/20161024234003_create_shops.rb +11 -0
- data/test/dummy/db/migrate/20161024234029_create_products.rb +12 -0
- data/test/dummy/db/migrate/20161031135453_create_uploads.rb +11 -0
- data/test/dummy/db/schema.rb +27 -16
- data/test/dummy/log/development.log +61 -0
- data/test/dummy/log/test.log +5873 -0
- data/test/dummy/public/404.html +58 -55
- data/test/dummy/public/422.html +58 -55
- data/test/dummy/public/500.html +57 -54
- data/test/fixtures/big_file.txt +50 -0
- data/test/fixtures/big_image.jpg +0 -0
- data/test/fixtures/file.txt +1 -0
- data/test/fixtures/image.jpg +0 -0
- data/test/{dummy/test/fixtures/file.txt → fixtures/small_file.txt} +0 -0
- data/test/fixtures/small_image.jpg +0 -0
- data/test/generator_test.rb +14 -6
- data/test/helper_test.rb +28 -0
- data/test/query_test.rb +26 -0
- data/test/support/storage_helper.rb +65 -0
- data/test/task_test.rb +69 -0
- data/test/test_helper.rb +6 -45
- data/test/upload_test.rb +27 -0
- data/test/validator_test.rb +160 -0
- metadata +114 -68
- data/lib/attachs/active_record/base.rb +0 -103
- data/lib/attachs/active_record/connection_adapters.rb +0 -40
- data/lib/attachs/active_record/migration.rb +0 -17
- data/lib/attachs/active_record/validators.rb +0 -7
- data/lib/attachs/active_record/validators/attachment_content_type_validator.rb +0 -30
- data/lib/attachs/active_record/validators/attachment_presence_validator.rb +0 -22
- data/lib/attachs/active_record/validators/attachment_size_validator.rb +0 -47
- data/lib/attachs/processors/thumbnail.rb +0 -69
- data/lib/attachs/storages/local.rb +0 -95
- data/lib/attachs/types/base.rb +0 -22
- data/lib/attachs/types/default.rb +0 -29
- data/lib/attachs/types/regular.rb +0 -21
- data/lib/generators/attachs/install_generator.rb +0 -13
- data/lib/generators/attachs/templates/attachs.rb +0 -2
- data/test/dummy/README.rdoc +0 -28
- data/test/dummy/app/models/medium.rb +0 -5
- data/test/dummy/app/models/picture.rb +0 -2
- data/test/dummy/config/initializers/secret_token.rb +0 -13
- data/test/dummy/config/s3.yml +0 -15
- data/test/dummy/db/migrate/20140808012639_create_media.rb +0 -11
- data/test/dummy/test/fixtures/image.gif +0 -0
- data/test/local_storage_test.rb +0 -72
- data/test/migration_test.rb +0 -65
- data/test/processor_test.rb +0 -49
- data/test/s3_storage_tes.rb +0 -66
- data/test/tasks_test.rb +0 -57
- data/test/validators_test.rb +0 -100
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af92d781bacb0959c5de57b14471a72591c85071
|
4
|
+
data.tar.gz: cd0da9ce6108a4029cacfab38f284d6ee7a655ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97c0b6d55ca5fb851f150f319f0df8e04b2dfb30e4162251aa23d7cf8d0fdd2a6624781368207a4a794eb339b1e795b06635fdb8fc44d0d7b8e529309ca86157
|
7
|
+
data.tar.gz: 93844d464cfc4f11389e7b7d96ae7d61d9670bc376ae52b9b9690b771ee7feb21108d337962540d58454ef9e0d3b602e3e9f586b3792c8e403f7467c9662b640
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -5,7 +5,18 @@
|
|
5
5
|
|
6
6
|
# Attachs
|
7
7
|
|
8
|
-
|
8
|
+
Json based attachments for records in rails.
|
9
|
+
|
10
|
+
## Why
|
11
|
+
|
12
|
+
I did this gem to:
|
13
|
+
|
14
|
+
- Save attachments into one json column.
|
15
|
+
- Handle multiple attachments without the need of a separate model.
|
16
|
+
- Have a way to delete orphan files.
|
17
|
+
- Use graphicsmagick out of the box.
|
18
|
+
- Delete and rename attachments asynchronous.
|
19
|
+
- Keep renamed files to improve seo.
|
9
20
|
|
10
21
|
## Install
|
11
22
|
|
@@ -19,292 +30,146 @@ Then bundle:
|
|
19
30
|
$ bundle
|
20
31
|
```
|
21
32
|
|
22
|
-
|
23
|
-
|
24
|
-
## Configuration
|
25
|
-
|
26
|
-
Generate the configuration file:
|
33
|
+
To install GraphicsMagick you can use homebrew:
|
27
34
|
```
|
28
|
-
|
35
|
+
$ brew install graphicsmagick
|
29
36
|
```
|
30
37
|
|
31
|
-
|
32
|
-
```ruby
|
33
|
-
Attachs.configure do |config|
|
34
|
-
config.s3 = { ssl: false }
|
35
|
-
config.base_url = ''
|
36
|
-
config.styles = {}
|
37
|
-
config.cachebuster = true
|
38
|
-
config.interpolations = {}
|
39
|
-
config.convert_options = {}
|
40
|
-
config.global_styles = []
|
41
|
-
config.global_convert_options= ''
|
42
|
-
config.default_storage = :local
|
43
|
-
config.default_processors = [:thumbnail]
|
44
|
-
config.default_path = '/:timestamp-:filename'
|
45
|
-
end
|
46
|
-
```
|
47
|
-
|
48
|
-
## Usage
|
49
|
-
|
50
|
-
Add the column to your table:
|
51
|
-
```ruby
|
52
|
-
create_table :users do |t|
|
53
|
-
t.attachment :avatar
|
54
|
-
end
|
55
|
-
```
|
56
|
-
|
57
|
-
Define the attachment in your model:
|
58
|
-
```ruby
|
59
|
-
class User < ActiveRecord::Base
|
60
|
-
has_attached_file :avatar
|
61
|
-
end
|
62
|
-
```
|
63
|
-
|
64
|
-
## Paths
|
38
|
+
## Configuration
|
65
39
|
|
66
|
-
|
67
|
-
```ruby
|
68
|
-
class User < ActiveRecord::Base
|
69
|
-
has_attached_file :avatar, path: '/:type/:timestamp/:filename'
|
70
|
-
end
|
40
|
+
Generate the configuration file:
|
71
41
|
```
|
72
|
-
|
73
|
-
To create custom interpolations:
|
74
|
-
```ruby
|
75
|
-
Attachs.configure do |config|
|
76
|
-
config.interpolations = {
|
77
|
-
category: -> (attachment) { attachment.record.category }
|
78
|
-
}
|
79
|
-
end
|
42
|
+
$ bundle exec rails g attachs:install
|
80
43
|
```
|
81
44
|
|
82
|
-
|
83
|
-
|
84
|
-
## Styles
|
85
|
-
|
86
|
-
Define the styles of the attachment:
|
45
|
+
Set the global settings:
|
87
46
|
```ruby
|
88
47
|
Attachs.configure do |config|
|
89
|
-
config.
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
}
|
94
|
-
end
|
95
|
-
```
|
48
|
+
config.convert_options = '-strip -quality 82'
|
49
|
+
config.region = 'us-east-1'
|
50
|
+
config.bucket = 'some-bucket'
|
51
|
+
config.base_url = 'https://cdn.mydomain.com'
|
96
52
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
has_attached_file :avatar, styles: [:small, :medium]
|
53
|
+
config.interpolation :name do |record|
|
54
|
+
record.name
|
55
|
+
end
|
101
56
|
end
|
102
57
|
```
|
103
58
|
|
104
|
-
|
105
|
-
```ruby
|
106
|
-
Attachs.configure do |config|
|
107
|
-
config.global_styles = [:big]
|
108
|
-
end
|
109
|
-
```
|
59
|
+
## Usage
|
110
60
|
|
111
|
-
|
61
|
+
### Definitions
|
112
62
|
|
113
|
-
|
63
|
+
Add the columns to your tables:
|
114
64
|
```ruby
|
115
|
-
|
116
|
-
|
65
|
+
class AddAttachments < ActiveRecord::Migration
|
66
|
+
def change
|
67
|
+
add_column :shops, :logo, :jsonb, default: {}
|
68
|
+
add_column :products, :pictures, :jsonb, default: []
|
69
|
+
end
|
117
70
|
end
|
118
71
|
```
|
119
72
|
|
120
|
-
|
73
|
+
Define the attachments in your models:
|
121
74
|
```ruby
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
75
|
+
class Shop < ActiveRecord::Base
|
76
|
+
has_attachment(
|
77
|
+
:logo,
|
78
|
+
path: ':id/:name.png',
|
79
|
+
default_path: 'missing.png'
|
80
|
+
)
|
126
81
|
end
|
127
|
-
```
|
128
82
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
83
|
+
class Product < ActiveRecord::Base
|
84
|
+
has_attachments(
|
85
|
+
:pictures,
|
86
|
+
path: ':id/:style.:extension',
|
87
|
+
styles: {
|
88
|
+
tiny: '25x25',
|
89
|
+
small: '150x150#',
|
90
|
+
medium: '300x300!',
|
91
|
+
large: '600x'
|
92
|
+
}
|
93
|
+
)
|
135
94
|
end
|
136
95
|
```
|
137
96
|
|
138
|
-
NOTE:
|
97
|
+
NOTE: The out of the box interpolations are: filename, basename, extension, attribute, content_type, size.
|
139
98
|
|
140
|
-
|
99
|
+
### Validations
|
141
100
|
|
142
101
|
To validate the presence of the attachment:
|
143
102
|
```ruby
|
144
103
|
class User < ActiveRecord::Base
|
145
|
-
|
146
|
-
validates_attachment_presence_of :
|
104
|
+
has_attachment :pictures
|
105
|
+
validates_attachment_presence_of :pictures
|
147
106
|
end
|
148
107
|
```
|
149
108
|
|
150
109
|
To validate the size of the attachment:
|
151
110
|
```ruby
|
152
111
|
class User < ActiveRecord::Base
|
153
|
-
|
154
|
-
validates_attachment_size_of :
|
112
|
+
has_attachment :pictures
|
113
|
+
validates_attachment_size_of :pictures, in: 1..5.megabytes
|
155
114
|
end
|
156
115
|
```
|
157
116
|
|
158
117
|
To validate the content type of the attachment:
|
159
118
|
```ruby
|
160
119
|
class User < ActiveRecord::Base
|
161
|
-
|
162
|
-
validates_attachment_content_type_of :
|
163
|
-
# Or using a list
|
164
|
-
validates_attachment_content_type_of :avatar, in: %w(image/jpg image/png)
|
120
|
+
has_attachment :pictures
|
121
|
+
validates_attachment_content_type_of :pictures, with: /\Aimage/
|
165
122
|
end
|
166
123
|
```
|
167
124
|
|
168
|
-
|
125
|
+
NOTE: Look into lib/attachs/locales yamls to known the keys.
|
169
126
|
|
170
|
-
|
171
|
-
```
|
172
|
-
errors.messages.attachment_presence
|
173
|
-
errors.messages.attachment_size_in
|
174
|
-
errors.messages.attachment_size_less_than
|
175
|
-
errors.messages.attachment_size_greater_than
|
176
|
-
errors.messages.attachment_content_type_with
|
177
|
-
errors.messages.attachment_content_type_in
|
178
|
-
```
|
179
|
-
|
180
|
-
NOTE: Look into lib/attachs/locales yamls.
|
181
|
-
|
182
|
-
## Forms
|
127
|
+
### Forms
|
183
128
|
|
184
129
|
Your forms continue to work the same:
|
185
130
|
```erb
|
186
|
-
<%= form_for @
|
187
|
-
<%= f.file_field :
|
131
|
+
<%= form_for @shop do |f| %>
|
132
|
+
<%= f.file_field :logo %>
|
188
133
|
<% end %>
|
189
134
|
```
|
190
135
|
|
191
|
-
|
192
|
-
|
193
|
-
The url method points to the original file:
|
194
|
-
```erb
|
195
|
-
<%= image_tag user.avatar.url %>
|
196
|
-
```
|
197
|
-
|
198
|
-
To point to some particular style:
|
136
|
+
You can manage collections with fields_for:
|
199
137
|
```erb
|
200
|
-
<%=
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
has_attached_file :avatar, default_url: '/missing.png'
|
207
|
-
end
|
208
|
-
```
|
209
|
-
|
210
|
-
NOTE: If storage is s3 you can pass ssl: true to force https.
|
211
|
-
|
212
|
-
## Cachebuster
|
213
|
-
|
214
|
-
All the urls end with a timestamp helper to prevent unwanted caching:
|
215
|
-
```
|
216
|
-
example.com/media/photo.jpg?1234567890
|
217
|
-
```
|
218
|
-
|
219
|
-
To disable cachebuster globally:
|
220
|
-
```ruby
|
221
|
-
Attachs.configure do |config|
|
222
|
-
config.cachebuster = false
|
223
|
-
end
|
138
|
+
<%= form_for @product do |f| %>
|
139
|
+
<%= f.fields_for :pictures do |ff| %>
|
140
|
+
<%= ff.file_field :value %>
|
141
|
+
<%= ff.number_field :position %>
|
142
|
+
<% end %>
|
143
|
+
<% end %>
|
224
144
|
```
|
225
145
|
|
226
|
-
|
227
|
-
```ruby
|
228
|
-
class User < ActiveRecord::Base
|
229
|
-
has_attached_file :avatar, cachebuster: false
|
230
|
-
end
|
231
|
-
```
|
146
|
+
### Urls
|
232
147
|
|
233
|
-
|
148
|
+
The url method points to the original file:
|
234
149
|
```erb
|
235
|
-
<%= image_tag
|
236
|
-
```
|
237
|
-
|
238
|
-
## Storage
|
239
|
-
|
240
|
-
To override the storage in the model:
|
241
|
-
```ruby
|
242
|
-
class User < ActiveRecord::Base
|
243
|
-
has_attached_file :avatar, storage: :s3
|
244
|
-
end
|
245
|
-
```
|
246
|
-
|
247
|
-
To configure the s3 credentials:
|
248
|
-
```ruby
|
249
|
-
Attachs.configure do |config|
|
250
|
-
config.s3 = {
|
251
|
-
bucket: 'xxx',
|
252
|
-
access_key_id: 'xxx',
|
253
|
-
secret_access_key: 'xxx'
|
254
|
-
}
|
255
|
-
end
|
150
|
+
<%= image_tag shop.logo.url %>
|
256
151
|
```
|
257
152
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
```ruby
|
262
|
-
class Attachs::Processors::CustomThumbnail
|
263
|
-
|
264
|
-
def initialize(attachment, source)
|
265
|
-
# Custom initialization
|
266
|
-
end
|
267
|
-
|
268
|
-
def process(style, destination)
|
269
|
-
# Custom logic
|
270
|
-
end
|
271
|
-
|
272
|
-
end
|
153
|
+
To point to some particular style:
|
154
|
+
```erb
|
155
|
+
<%= image_tag shop.logo.url(:small) %>
|
273
156
|
```
|
274
157
|
|
275
|
-
|
276
|
-
```ruby
|
277
|
-
class User < ActiveRecord::Base
|
278
|
-
has_attached_file :avatar, processors: [:custom_thumbnail]
|
279
|
-
end
|
280
|
-
```
|
158
|
+
### Tasks
|
281
159
|
|
282
|
-
To
|
283
|
-
```ruby
|
284
|
-
Attachs.configure do |config|
|
285
|
-
config.default_processors = [:custom_thumbnail]
|
286
|
-
end
|
160
|
+
To reprocess all styles:
|
287
161
|
```
|
288
|
-
|
289
|
-
## CDN
|
290
|
-
|
291
|
-
To configure a cdn:
|
292
|
-
```ruby
|
293
|
-
Attachs.configure do |config|
|
294
|
-
config.base_url = 'http://cdn.example.com'
|
295
|
-
end
|
162
|
+
$ bundle exec rake attachs:reprocess
|
296
163
|
```
|
297
164
|
|
298
|
-
|
299
|
-
|
300
|
-
To refresh all the styles of some attachment:
|
165
|
+
To fix missing styles:
|
301
166
|
```
|
302
|
-
bundle exec rake attachs:
|
167
|
+
$ bundle exec rake attachs:fix_missings
|
303
168
|
```
|
304
169
|
|
305
|
-
To
|
170
|
+
To remove orphan files:
|
306
171
|
```
|
307
|
-
bundle exec rake attachs:
|
172
|
+
$ bundle exec rake attachs:clear
|
308
173
|
```
|
309
174
|
|
310
175
|
## Credits
|
data/Rakefile
CHANGED
@@ -4,19 +4,6 @@ rescue LoadError
|
|
4
4
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
5
|
end
|
6
6
|
|
7
|
-
require 'rdoc/task'
|
8
|
-
|
9
|
-
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
-
rdoc.rdoc_dir = 'rdoc'
|
11
|
-
rdoc.title = 'Attachs'
|
12
|
-
rdoc.options << '--line-numbers'
|
13
|
-
rdoc.rdoc_files.include('README.rdoc')
|
14
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
7
|
Bundler::GemHelper.install_tasks
|
21
8
|
|
22
9
|
require 'rake/testtask'
|
@@ -26,7 +13,7 @@ Rake::TestTask.new(:test) do |t|
|
|
26
13
|
t.libs << 'test'
|
27
14
|
t.pattern = 'test/**/*_test.rb'
|
28
15
|
t.verbose = false
|
16
|
+
t.warning = false
|
29
17
|
end
|
30
18
|
|
31
|
-
|
32
19
|
task default: :test
|
data/lib/attachs.rb
CHANGED
@@ -1,45 +1,112 @@
|
|
1
|
-
require '
|
2
|
-
require 'attachs/
|
1
|
+
require 'attachs/extensions/active_record/validations/attachment_validator'
|
2
|
+
require 'attachs/extensions/active_record/validations/attachment_content_type_validator'
|
3
|
+
require 'attachs/extensions/active_record/validations/attachment_presence_validator'
|
4
|
+
require 'attachs/extensions/active_record/validations/attachment_size_validator'
|
5
|
+
require 'attachs/extensions/active_record/base'
|
6
|
+
require 'attachs/jobs/base'
|
7
|
+
require 'attachs/jobs/delete_job'
|
8
|
+
require 'attachs/jobs/update_job'
|
3
9
|
require 'attachs/processors/base'
|
4
|
-
require 'attachs/processors/
|
10
|
+
require 'attachs/processors/image'
|
5
11
|
require 'attachs/storages/base'
|
6
|
-
require 'attachs/storages/local'
|
7
12
|
require 'attachs/storages/s3'
|
8
|
-
require 'attachs/
|
9
|
-
require 'attachs/
|
10
|
-
require 'attachs/
|
11
|
-
require 'attachs/
|
12
|
-
require 'attachs/
|
13
|
-
require 'attachs/
|
14
|
-
require 'attachs/
|
15
|
-
require 'attachs/active_record/validators/attachment_content_type_validator'
|
16
|
-
require 'attachs/active_record/validators/attachment_presence_validator'
|
17
|
-
require 'attachs/active_record/validators/attachment_size_validator'
|
13
|
+
require 'attachs/attachment'
|
14
|
+
require 'attachs/builder'
|
15
|
+
require 'attachs/collection'
|
16
|
+
require 'attachs/concern'
|
17
|
+
require 'attachs/configuration'
|
18
|
+
require 'attachs/console'
|
19
|
+
require 'attachs/interpolations'
|
18
20
|
require 'attachs/railtie'
|
21
|
+
require 'attachs/version'
|
22
|
+
require 'open3'
|
19
23
|
|
20
24
|
module Attachs
|
21
25
|
class << self
|
22
26
|
|
23
27
|
def configure
|
24
|
-
yield
|
25
|
-
end
|
26
|
-
|
27
|
-
def
|
28
|
-
@
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
28
|
+
yield configuration
|
29
|
+
end
|
30
|
+
|
31
|
+
def configuration
|
32
|
+
@configuration ||= Configuration.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def storage
|
36
|
+
@storage ||= Storages::S3.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def interpolations
|
40
|
+
@interpolations ||= Interpolations.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def models
|
44
|
+
if Rails.configuration.cache_classes == false
|
45
|
+
Rails.application.eager_load!
|
46
|
+
end
|
47
|
+
ActiveRecord::Base.descendants.select do |model|
|
48
|
+
model.included_modules.include?(Attachs::Concern) && model.descendants.none?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def each
|
53
|
+
models.each do |model|
|
54
|
+
model.find_each do |record|
|
55
|
+
model.attachments.each do |attribute, options|
|
56
|
+
yield record.send(attribute)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def exists?(path)
|
63
|
+
queries = models.map do |model|
|
64
|
+
model.attachments.map do |attribute, options|
|
65
|
+
joins = []
|
66
|
+
if options[:multiple]
|
67
|
+
joins << "LEFT JOIN JSONB_ARRAY_ELEMENTS(#{model.table_name}.#{attribute}) attachments ON TRUE"
|
68
|
+
joins << "LEFT JOIN JSONB_EACH_TEXT(attachments->'paths') paths ON TRUE"
|
69
|
+
joins << "LEFT JOIN JSONB_ARRAY_ELEMENTS_TEXT(attachments->'old_paths') old_paths ON TRUE"
|
70
|
+
else
|
71
|
+
joins << "LEFT JOIN JSONB_EACH_TEXT(#{model.table_name}.#{attribute}->'paths') paths ON TRUE"
|
72
|
+
joins << "LEFT JOIN JSONB_ARRAY_ELEMENTS_TEXT(#{model.table_name}.#{attribute}->'old_paths') old_paths ON TRUE"
|
73
|
+
end
|
74
|
+
joins = joins.join(' ')
|
75
|
+
conditions = ['paths.value = :path OR old_paths.value = :path', path: path]
|
76
|
+
model.select('1 AS one').from(model.table_name).joins(joins).where(conditions).to_sql
|
41
77
|
end
|
42
78
|
end
|
79
|
+
query = queries.flatten.join(' UNION ')
|
80
|
+
ActiveRecord::Base.connection.execute(query).any?
|
81
|
+
end
|
82
|
+
|
83
|
+
def clear
|
84
|
+
storage.find_each do |path|
|
85
|
+
unless exists?(path)
|
86
|
+
Rails.logger.info "Deleting #{path}"
|
87
|
+
storage.delete path
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def reprocess
|
93
|
+
each do |attachment|
|
94
|
+
class_name = attachment.record.class.name
|
95
|
+
id = attachment.record.id
|
96
|
+
attribute = attachment.record_attribute
|
97
|
+
Rails.logger.info "Reprocessing #{class_name} ##{id} => #{attribute}"
|
98
|
+
attachment.reprocess
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def fix_missings
|
103
|
+
each do |attachment|
|
104
|
+
class_name = attachment.record.class.name
|
105
|
+
id = attachment.record.id
|
106
|
+
attribute = attachment.record_attribute
|
107
|
+
Rails.logger.info "Fix missings of #{class_name} ##{id} => #{attribute}"
|
108
|
+
attachment.fix_missings
|
109
|
+
end
|
43
110
|
end
|
44
111
|
|
45
112
|
end
|