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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +83 -218
  4. data/Rakefile +1 -14
  5. data/lib/attachs.rb +98 -31
  6. data/lib/attachs/attachment.rb +301 -72
  7. data/lib/attachs/builder.rb +78 -0
  8. data/lib/attachs/collection.rb +84 -0
  9. data/lib/attachs/concern.rb +47 -0
  10. data/lib/attachs/configuration.rb +11 -0
  11. data/lib/attachs/console.rb +40 -0
  12. data/lib/attachs/extensions/active_record/base.rb +24 -0
  13. data/lib/attachs/extensions/active_record/validations/attachment_content_type_validator.rb +37 -0
  14. data/lib/attachs/extensions/active_record/validations/attachment_presence_validator.rb +27 -0
  15. data/lib/attachs/extensions/active_record/validations/attachment_size_validator.rb +55 -0
  16. data/lib/attachs/extensions/active_record/validations/attachment_validator.rb +24 -0
  17. data/lib/attachs/interpolations.rb +27 -0
  18. data/lib/attachs/jobs/base.rb +14 -0
  19. data/lib/attachs/jobs/delete_job.rb +15 -0
  20. data/lib/attachs/jobs/update_job.rb +11 -0
  21. data/lib/attachs/locales/en.yml +2 -6
  22. data/lib/attachs/locales/es.yml +2 -6
  23. data/lib/attachs/processors/base.rb +4 -14
  24. data/lib/attachs/processors/image.rb +45 -0
  25. data/lib/attachs/railtie.rb +7 -27
  26. data/lib/attachs/storages/base.rb +10 -59
  27. data/lib/attachs/storages/s3.rb +68 -63
  28. data/lib/attachs/version.rb +1 -1
  29. data/lib/generators/attachs/install/install_generator.rb +15 -0
  30. data/lib/generators/attachs/install/templates/initializer.rb +7 -0
  31. data/lib/generators/attachs/upload/templates/migration.rb +11 -0
  32. data/lib/generators/attachs/upload/templates/model.rb +19 -0
  33. data/lib/generators/attachs/upload/upload_generator.rb +24 -0
  34. data/lib/tasks/attachs.rake +12 -26
  35. data/test/attachment_test.rb +175 -12
  36. data/test/collection_test.rb +52 -0
  37. data/test/concern_test.rb +10 -0
  38. data/test/dummy/Rakefile +1 -2
  39. data/test/dummy/app/assets/javascripts/application.js +2 -2
  40. data/test/dummy/app/assets/stylesheets/application.css +6 -4
  41. data/test/dummy/app/models/product.rb +16 -0
  42. data/test/dummy/app/models/shop.rb +14 -0
  43. data/test/dummy/app/models/upload.rb +19 -0
  44. data/test/dummy/app/views/layouts/application.html.erb +9 -11
  45. data/test/dummy/bin/bundle +1 -0
  46. data/test/dummy/bin/rails +2 -1
  47. data/test/dummy/bin/rake +1 -0
  48. data/test/dummy/bin/setup +30 -0
  49. data/test/dummy/config.ru +1 -1
  50. data/test/dummy/config/application.rb +3 -2
  51. data/test/dummy/config/boot.rb +1 -1
  52. data/test/dummy/config/database.yml +4 -22
  53. data/test/dummy/config/database.yml.travis +3 -0
  54. data/test/dummy/config/environment.rb +1 -1
  55. data/test/dummy/config/environments/development.rb +15 -3
  56. data/test/dummy/config/environments/production.rb +21 -26
  57. data/test/dummy/config/environments/test.rb +10 -12
  58. data/test/dummy/config/initializers/assets.rb +11 -0
  59. data/test/dummy/config/initializers/attachs.rb +7 -21
  60. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  61. data/test/dummy/config/initializers/mime_types.rb +1 -2
  62. data/test/dummy/config/initializers/session_store.rb +1 -1
  63. data/test/dummy/config/routes.rb +54 -0
  64. data/test/dummy/config/secrets.yml +24 -0
  65. data/test/dummy/db/migrate/20161024234003_create_shops.rb +11 -0
  66. data/test/dummy/db/migrate/20161024234029_create_products.rb +12 -0
  67. data/test/dummy/db/migrate/20161031135453_create_uploads.rb +11 -0
  68. data/test/dummy/db/schema.rb +27 -16
  69. data/test/dummy/log/development.log +61 -0
  70. data/test/dummy/log/test.log +5873 -0
  71. data/test/dummy/public/404.html +58 -55
  72. data/test/dummy/public/422.html +58 -55
  73. data/test/dummy/public/500.html +57 -54
  74. data/test/fixtures/big_file.txt +50 -0
  75. data/test/fixtures/big_image.jpg +0 -0
  76. data/test/fixtures/file.txt +1 -0
  77. data/test/fixtures/image.jpg +0 -0
  78. data/test/{dummy/test/fixtures/file.txt → fixtures/small_file.txt} +0 -0
  79. data/test/fixtures/small_image.jpg +0 -0
  80. data/test/generator_test.rb +14 -6
  81. data/test/helper_test.rb +28 -0
  82. data/test/query_test.rb +26 -0
  83. data/test/support/storage_helper.rb +65 -0
  84. data/test/task_test.rb +69 -0
  85. data/test/test_helper.rb +6 -45
  86. data/test/upload_test.rb +27 -0
  87. data/test/validator_test.rb +160 -0
  88. metadata +114 -68
  89. data/lib/attachs/active_record/base.rb +0 -103
  90. data/lib/attachs/active_record/connection_adapters.rb +0 -40
  91. data/lib/attachs/active_record/migration.rb +0 -17
  92. data/lib/attachs/active_record/validators.rb +0 -7
  93. data/lib/attachs/active_record/validators/attachment_content_type_validator.rb +0 -30
  94. data/lib/attachs/active_record/validators/attachment_presence_validator.rb +0 -22
  95. data/lib/attachs/active_record/validators/attachment_size_validator.rb +0 -47
  96. data/lib/attachs/processors/thumbnail.rb +0 -69
  97. data/lib/attachs/storages/local.rb +0 -95
  98. data/lib/attachs/types/base.rb +0 -22
  99. data/lib/attachs/types/default.rb +0 -29
  100. data/lib/attachs/types/regular.rb +0 -21
  101. data/lib/generators/attachs/install_generator.rb +0 -13
  102. data/lib/generators/attachs/templates/attachs.rb +0 -2
  103. data/test/dummy/README.rdoc +0 -28
  104. data/test/dummy/app/models/medium.rb +0 -5
  105. data/test/dummy/app/models/picture.rb +0 -2
  106. data/test/dummy/config/initializers/secret_token.rb +0 -13
  107. data/test/dummy/config/s3.yml +0 -15
  108. data/test/dummy/db/migrate/20140808012639_create_media.rb +0 -11
  109. data/test/dummy/test/fixtures/image.gif +0 -0
  110. data/test/local_storage_test.rb +0 -72
  111. data/test/migration_test.rb +0 -65
  112. data/test/processor_test.rb +0 -49
  113. data/test/s3_storage_tes.rb +0 -66
  114. data/test/tasks_test.rb +0 -57
  115. data/test/validators_test.rb +0 -100
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3945fa2265a2f9ddfe93516b5476fa84688811f1
4
- data.tar.gz: 2e50c546d315e7c33fbfe139b9f9c971d48b62ae
3
+ metadata.gz: af92d781bacb0959c5de57b14471a72591c85071
4
+ data.tar.gz: cd0da9ce6108a4029cacfab38f284d6ee7a655ab
5
5
  SHA512:
6
- metadata.gz: 3bfa61b0d19c30e29b47d0f8532ed3507918f6344f49743e4f0348320b93fc74d66c4cc977c32f06715932b8cc8b6ed6025e0334d8d6ba57ab4530fd631a0239
7
- data.tar.gz: 6ebd136c2d1373b8c7afa4feab958f91e8a5329758eef3cda01453c48c1ec0150b577f5a412e3e7a7dc3e47aa717a4ce1e2fec48d3a42b3b984dee21306809c2
6
+ metadata.gz: 97c0b6d55ca5fb851f150f319f0df8e04b2dfb30e4162251aa23d7cf8d0fdd2a6624781368207a4a794eb339b1e795b06635fdb8fc44d0d7b8e529309ca86157
7
+ data.tar.gz: 93844d464cfc4f11389e7b7d96ae7d61d9670bc376ae52b9b9690b771ee7feb21108d337962540d58454ef9e0d3b602e3e9f586b3792c8e403f7467c9662b640
@@ -1,4 +1,4 @@
1
- Copyright 2015 Mathías Montossi
1
+ Copyright 2016 Mathías Montossi
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -5,7 +5,18 @@
5
5
 
6
6
  # Attachs
7
7
 
8
- Minimalistic toolkit to attach files to records.
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
- NOTE: ImageMagick is needed.
23
-
24
- ## Configuration
25
-
26
- Generate the configuration file:
33
+ To install GraphicsMagick you can use homebrew:
27
34
  ```
28
- rails g attachs:install
35
+ $ brew install graphicsmagick
29
36
  ```
30
37
 
31
- The defaults values are:
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
- To customize the path to some model:
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
- NOTE: Look into lib/attachs/storages/base.rb to find a list of the system interpolations.
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.styles = {
90
- small: '120x120!', # forces the exact size
91
- medium: '240x240#', # resizes and crops to fill the desire space
92
- big: '360x360' # resizes to contain the imagen in the desire space
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
- Then reference them in your model:
98
- ```ruby
99
- class User < ActiveRecord::Base
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
- To set styles for all attachments:
105
- ```ruby
106
- Attachs.configure do |config|
107
- config.global_styles = [:big]
108
- end
109
- ```
59
+ ## Usage
110
60
 
111
- ## Convert
61
+ ### Definitions
112
62
 
113
- To define global convert options:
63
+ Add the columns to your tables:
114
64
  ```ruby
115
- Attachs.configure do |config|
116
- config.global_convert_options = '-quality 75 -strip'
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
- To set convert options to some styles only:
73
+ Define the attachments in your models:
121
74
  ```ruby
122
- Attachs.configure do |config|
123
- config.convert_options = {
124
- medium: '-trim'
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
- ## Security
130
-
131
- To make the attachment private:
132
- ```ruby
133
- class User < ActiveRecord::Base
134
- has_attached_file :avatar, private: true
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: Private attachments will be saved into /private folder.
97
+ NOTE: The out of the box interpolations are: filename, basename, extension, attribute, content_type, size.
139
98
 
140
- ## Validations
99
+ ### Validations
141
100
 
142
101
  To validate the presence of the attachment:
143
102
  ```ruby
144
103
  class User < ActiveRecord::Base
145
- has_attached_file :avatar
146
- validates_attachment_presence_of :avatar
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
- has_attached_file :avatar
154
- validates_attachment_size_of :avatar, in: 1..5.megabytes
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
- has_attached_file :avatar
162
- validates_attachment_content_type_of :avatar, with: /\Aimage/
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
- ## I18n
125
+ NOTE: Look into lib/attachs/locales yamls to known the keys.
169
126
 
170
- To translate the messages the keys are:
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 @user do |f| %>
187
- <%= f.file_field :avatar %>
131
+ <%= form_for @shop do |f| %>
132
+ <%= f.file_field :logo %>
188
133
  <% end %>
189
134
  ```
190
135
 
191
- ## Urls
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
- <%= image_tag user.avatar.url(:small) %>
201
- ```
202
-
203
- The defauft url is used when there is no upload:
204
- ```ruby
205
- class User < ActiveRecord::Base
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
- To disable cachebuster in a model:
227
- ```ruby
228
- class User < ActiveRecord::Base
229
- has_attached_file :avatar, cachebuster: false
230
- end
231
- ```
146
+ ### Urls
232
147
 
233
- To disable cachebuster for some url:
148
+ The url method points to the original file:
234
149
  ```erb
235
- <%= image_tag user.avatar.url(cachebuster: false) %>
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
- ## Processors
259
-
260
- To create a custom processor:
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
- To change the processors in the model:
276
- ```ruby
277
- class User < ActiveRecord::Base
278
- has_attached_file :avatar, processors: [:custom_thumbnail]
279
- end
280
- ```
158
+ ### Tasks
281
159
 
282
- To change the default processors:
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
- ## Tasks
299
-
300
- To refresh all the styles of some attachment:
165
+ To fix missing styles:
301
166
  ```
302
- bundle exec rake attachs:refresh:all class=user attachment=avatar
167
+ $ bundle exec rake attachs:fix_missings
303
168
  ```
304
169
 
305
- To refresh missing styles of some attachment:
170
+ To remove orphan files:
306
171
  ```
307
- bundle exec rake attachs:refresh:missing class=user attachment=avatar
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
@@ -1,45 +1,112 @@
1
- require 'open3'
2
- require 'attachs/attachment'
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/thumbnail'
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/types/base'
9
- require 'attachs/types/default'
10
- require 'attachs/types/regular'
11
- require 'attachs/active_record/base'
12
- require 'attachs/active_record/connection_adapters'
13
- require 'attachs/active_record/migration'
14
- require 'attachs/active_record/validators'
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 config
25
- end
26
-
27
- def config
28
- @config ||= begin
29
- ActiveSupport::OrderedOptions.new.tap do |config|
30
- config.s3 = { ssl: false }
31
- config.base_url = ''
32
- config.styles = {}
33
- config.cachebuster = true
34
- config.interpolations = {}
35
- config.convert_options = {}
36
- config.global_styles = []
37
- config.global_convert_options= ''
38
- config.default_storage = :local
39
- config.default_processors = [:thumbnail]
40
- config.default_path = '/:timestamp-:filename'
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