better_record 0.15.2 → 0.16.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/app/jobs/active_storage/purge_job.rb +13 -0
- data/app/models/better_record/attachment_validation.rb +36 -0
- data/app/models/better_record/model_concerns/has_validated_avatar.rb +80 -28
- data/db/migrate/20181228204403_create_better_record_attachment_validations.rb +15 -0
- data/lib/better_record/version.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 669acb9b867dcb30b92fbe9d4d147f97c60862aedebd1a9a5f9319577f262b17
|
4
|
+
data.tar.gz: fea7a77007c6279d2c0ad4b9845f22579b9ff608e54e49f306d36da4d68198f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 283448eb2be733d810ffdb8bfcfcdb1ec0471983729da9529e4fe836711cf50ed065a7180eed2f49360218d55541288aef7c02975b7871b37286699d739d407b
|
7
|
+
data.tar.gz: 2c8c02a86f16fa393a0168dadf80438892c26a2c224511eba68a1bb573d82bc968817136d0ccea31d87b8db47dd39ad7ac70f31362da15f2e896800bbeedd2a0
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Provides asynchronous purging of ActiveStorage::Blob records via ActiveStorage::Blob#purge_later.
|
4
|
+
class ActiveStorage::PurgeJob < ActiveStorage::BaseJob
|
5
|
+
discard_on ActiveRecord::RecordNotFound
|
6
|
+
|
7
|
+
def perform(blob)
|
8
|
+
begin
|
9
|
+
blob&.purge
|
10
|
+
rescue
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BetterRecord
|
4
|
+
class AttachmentValidation < ApplicationRecord
|
5
|
+
# == Constants ============================================================
|
6
|
+
|
7
|
+
# == Attributes ===========================================================
|
8
|
+
|
9
|
+
# == Extensions ===========================================================
|
10
|
+
|
11
|
+
# == Relationships ========================================================
|
12
|
+
belongs_to :attachment,
|
13
|
+
class_name: 'ActiveStorage::Attachment',
|
14
|
+
inverse_of: :validations
|
15
|
+
|
16
|
+
ActiveStorage::Attachment.has_many :validations,
|
17
|
+
class_name: 'BetterRecord::AttachmentValidation',
|
18
|
+
foreign_key: :attachment_id,
|
19
|
+
inverse_of: :attachment,
|
20
|
+
dependent: :destroy
|
21
|
+
# == Validations ==========================================================
|
22
|
+
|
23
|
+
# == Scopes ===============================================================
|
24
|
+
|
25
|
+
# == Callbacks ============================================================
|
26
|
+
|
27
|
+
# == Boolean Class Methods ================================================
|
28
|
+
|
29
|
+
# == Class Methods ========================================================
|
30
|
+
|
31
|
+
# == Boolean Methods ======================================================
|
32
|
+
|
33
|
+
# == Instance Methods =====================================================
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -16,12 +16,13 @@ module BetterRecord
|
|
16
16
|
min_image_size: nil,
|
17
17
|
max_image_size: 500.kilobytes,
|
18
18
|
shrink_large_image: false,
|
19
|
+
shrink_wait_time: 1.minute,
|
19
20
|
**opts
|
20
21
|
)
|
21
22
|
# == Constants ============================================================
|
22
23
|
|
23
24
|
# == Attributes ===========================================================
|
24
|
-
attribute :"
|
25
|
+
attribute :"shrinking_#{avatar_name}", :boolean, default: false
|
25
26
|
|
26
27
|
# == Extensions ===========================================================
|
27
28
|
|
@@ -30,25 +31,49 @@ module BetterRecord
|
|
30
31
|
has_one_attached avatar_name
|
31
32
|
|
32
33
|
# == Validations ==========================================================
|
33
|
-
validate avatar_name, image_validator
|
34
|
+
validate avatar_name, :"check_#{image_validator}"
|
34
35
|
|
35
36
|
# == Scopes ===============================================================
|
36
37
|
|
37
38
|
# == Callbacks ============================================================
|
38
|
-
|
39
|
+
after_commit :"check_#{image_validator}", if: :"#{avatar_name}_attached?", on: %i[ create update ]
|
39
40
|
|
40
41
|
# == Boolean Class Methods ================================================
|
41
42
|
|
42
43
|
# == Class Methods ========================================================
|
43
44
|
|
44
45
|
# == Boolean Methods ======================================================
|
46
|
+
define_method :"#{avatar_name}_attached?" do
|
47
|
+
__send__(avatar_name).attached?
|
48
|
+
end
|
49
|
+
|
50
|
+
define_method :"#{avatar_name}_validation_ran?" do |rld=false|
|
51
|
+
!!__send__(:"#{avatar_name}_validation_record", !!rld)&.ran
|
52
|
+
end
|
45
53
|
|
46
54
|
# == Instance Methods =====================================================
|
47
|
-
define_method :"attach_#{avatar_name}" do
|
48
|
-
__send__(avatar_name).attach(
|
55
|
+
define_method :"attach_#{avatar_name}" do |*args, **options|
|
56
|
+
__send__(avatar_name).attach(*args, **options)
|
49
57
|
__send__ image_validator
|
50
58
|
end
|
51
59
|
|
60
|
+
define_method :"create_#{avatar_name}_validation" do |ran=false|
|
61
|
+
begin
|
62
|
+
AttachmentValidation.create!(name: image_validator, attachment_id: __send__(avatar_name).id, ran: ran)
|
63
|
+
rescue
|
64
|
+
__send__(:"#{avatar_name}_validation_record").update(ran: true) if $!.is_a?(PG::UniqueViolation) && ran && !__send__(:"#{avatar_name}_validation_record").ran
|
65
|
+
end
|
66
|
+
__send__(:"#{avatar_name}_validation_record")
|
67
|
+
end
|
68
|
+
|
69
|
+
define_method :"#{avatar_name}_validation_record" do |rld=false|
|
70
|
+
(!rld && instance_variable_get(:"@#{avatar_name}_record")) ||
|
71
|
+
instance_variable_set(
|
72
|
+
:"@#{avatar_name}_record",
|
73
|
+
AttachmentValidation.find_by(attachment_id: __send__(avatar_name).id, name: image_validator)
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
52
77
|
define_method :valid_image_format do
|
53
78
|
unless __send__(avatar_name).blob.content_type.start_with? 'image/'
|
54
79
|
errors.add(avatar_name, 'is not an image file')
|
@@ -60,14 +85,19 @@ module BetterRecord
|
|
60
85
|
define_method :valid_image_size do
|
61
86
|
if max_image_size && __send__(avatar_name).blob.byte_size > max_image_size
|
62
87
|
if shrink_large_image.present?
|
63
|
-
|
64
|
-
|
88
|
+
puts "\nSHRINKING\n"
|
89
|
+
self.__send__ :"shrinking_#{avatar_name}=", true
|
90
|
+
(
|
91
|
+
shrink_wait_time ?
|
92
|
+
ResizeBlobImageJob.set(wait: shrink_wait_time) :
|
93
|
+
ResizeBlobImageJob
|
94
|
+
).perform_later(
|
65
95
|
model: self.class.to_s,
|
66
96
|
query: {id: self.id},
|
67
97
|
attachment: avatar_name.to_s,
|
68
|
-
backup_action: image_validator.to_s,
|
69
98
|
options: shrink_large_image
|
70
99
|
)
|
100
|
+
true
|
71
101
|
else
|
72
102
|
errors.add(avatar_name, "is too large, maximum #{ActiveSupport::NumberHelper.number_to_human_size(max_image_size)}")
|
73
103
|
return false
|
@@ -81,27 +111,33 @@ module BetterRecord
|
|
81
111
|
|
82
112
|
define_method :valid_image do
|
83
113
|
return true unless __send__(avatar_name).attached?
|
114
|
+
__send__(:"create_#{avatar_name}_validation", true)
|
84
115
|
|
85
116
|
if valid_image_format && valid_image_size
|
86
|
-
|
87
|
-
|
88
|
-
result = self.class.find_by(id: self.id).__send__(:"cache_current_#{avatar_name}")
|
89
|
-
puts "\n\nDONE COPYING AVATAR: #{result}\n\n"
|
90
|
-
result
|
117
|
+
self.__send__(:"shrinking_#{avatar_name}") ||
|
118
|
+
reloaded_record.__send__(:"cache_current_#{avatar_name}")
|
91
119
|
else
|
92
|
-
r =
|
93
|
-
|
120
|
+
r = reloaded_record.__send__(avatar_name)
|
121
|
+
begin
|
122
|
+
r.purge_later if r.attached?
|
123
|
+
rescue Exception
|
124
|
+
end
|
94
125
|
__send__(:"load_last_#{avatar_name}") if __send__(:"last_#{avatar_name}").attached?
|
95
126
|
false
|
96
127
|
end
|
97
128
|
end
|
98
129
|
|
130
|
+
define_method :"check_#{image_validator}" do |*args|
|
131
|
+
return true unless __send__(avatar_name).attached?
|
132
|
+
__send__(image_validator) unless __send__(:"#{avatar_name}_validation_ran?", true)
|
133
|
+
end
|
134
|
+
|
99
135
|
define_method :"cache_current_#{avatar_name}" do
|
100
|
-
__send__ :"copy_#{avatar_name}"
|
136
|
+
reloaded_record.__send__ :"copy_#{avatar_name}"
|
101
137
|
end
|
102
138
|
|
103
139
|
define_method :"load_last_#{avatar_name}" do
|
104
|
-
__send__ :"copy_#{avatar_name}", :"last_#{avatar_name}", avatar_name
|
140
|
+
reloaded_record.__send__ :"copy_#{avatar_name}", :"last_#{avatar_name}", avatar_name
|
105
141
|
end
|
106
142
|
|
107
143
|
define_method :"copy_#{avatar_name}" do |from = avatar_name, to = :"last_#{avatar_name}"|
|
@@ -109,23 +145,39 @@ module BetterRecord
|
|
109
145
|
from_attachment = __send__ from
|
110
146
|
to_attachment = __send__ to
|
111
147
|
|
112
|
-
|
148
|
+
if to_attachment.attached?
|
149
|
+
begin
|
150
|
+
atch = ActiveStorage::Attachment.find_by(to_attachment.id)
|
151
|
+
atch&.purge_later
|
152
|
+
rescue Exception
|
153
|
+
begin
|
154
|
+
ActiveStorage::Attachment.find_by(to_attachment.id).destroy
|
155
|
+
rescue Exception
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
113
159
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
160
|
+
if from_attachment.attached?
|
161
|
+
tmp = Tempfile.new
|
162
|
+
tmp.binmode
|
163
|
+
tmp.write(from_attachment.download)
|
164
|
+
tmp.flush
|
165
|
+
tmp.rewind
|
119
166
|
|
120
|
-
|
121
|
-
|
122
|
-
|
167
|
+
r = reloaded_record
|
168
|
+
from_attachment = r.__send__ from
|
169
|
+
to_attachment = r.__send__ to
|
123
170
|
|
124
|
-
|
125
|
-
|
171
|
+
to_attachment.attach(io: tmp, filename: from_attachment.filename, content_type: from_attachment.content_type)
|
172
|
+
tmp.close
|
173
|
+
end
|
126
174
|
true
|
127
175
|
end
|
128
176
|
|
177
|
+
define_method :reloaded_record do
|
178
|
+
self.class.find_by(id: self.id)
|
179
|
+
end
|
180
|
+
|
129
181
|
end
|
130
182
|
end
|
131
183
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateBetterRecordAttachmentValidations < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :better_record_attachment_validations do |t|
|
4
|
+
t.string :name, null: false
|
5
|
+
t.references :attachment, null: false
|
6
|
+
t.boolean :ran, null: false, default: false
|
7
|
+
|
8
|
+
t.index [ :attachment_id, :name ], name: "index_attachment_validations_uniqueness", unique: true
|
9
|
+
|
10
|
+
t.timestamps default: -> { 'NOW()' }
|
11
|
+
end
|
12
|
+
|
13
|
+
audit_table :better_record_attachment_validations
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: better_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sampson Crowley
|
@@ -234,9 +234,11 @@ files:
|
|
234
234
|
- app/controllers/better_record/table_sizes_controller.rb
|
235
235
|
- app/helpers/better_record/application_helper.rb
|
236
236
|
- app/helpers/better_record/table_sizes_helper.rb
|
237
|
+
- app/jobs/active_storage/purge_job.rb
|
237
238
|
- app/jobs/better_record/application_job.rb
|
238
239
|
- app/jobs/better_record/resize_blob_image_job.rb
|
239
240
|
- app/mailers/better_record/application_mailer.rb
|
241
|
+
- app/models/better_record/attachment_validation.rb
|
240
242
|
- app/models/better_record/base.rb
|
241
243
|
- app/models/better_record/current.rb
|
242
244
|
- app/models/better_record/logged_action.rb
|
@@ -262,6 +264,7 @@ files:
|
|
262
264
|
- db/migrate/20180518042050_create_better_record_db_functions.rb
|
263
265
|
- db/migrate/20180518042060_create_better_record_custom_types.rb
|
264
266
|
- db/migrate/20180518042070_create_better_record_table_sizes.rb
|
267
|
+
- db/migrate/20181228204403_create_better_record_attachment_validations.rb
|
265
268
|
- db/postgres-audit-trigger.psql
|
266
269
|
- lib/better_record.rb
|
267
270
|
- lib/better_record/batches.rb
|