better_record 0.15.2 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38d1f355a28bcc6fa75e43137e4f6d2096c78b85de3420733cf201826424e22d
4
- data.tar.gz: d5da519726817d407cc67a027041dc0c258daf715f6c8675de934cda2c3b626b
3
+ metadata.gz: 669acb9b867dcb30b92fbe9d4d147f97c60862aedebd1a9a5f9319577f262b17
4
+ data.tar.gz: fea7a77007c6279d2c0ad4b9845f22579b9ff608e54e49f306d36da4d68198f4
5
5
  SHA512:
6
- metadata.gz: 2cdb3aeac811064a91c3450942a5e5f0776e539aba2300a14c2ec7f2883caaf985d745e44a0dfaa5761ed794a0ba37322e2583c5d014435c5e5364852799c223
7
- data.tar.gz: 7e965a6f43b3fb45b47ab026d682bf00294ec8b417077183189d85c39f965d247eb6a83d90e6d3a0e59c2194e4aa938a1c1d7a748262962a64fef211be494892
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 :"new_#{avatar_name}?", :boolean
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
- after_save :"cache_current_#{avatar_name}", if: :"new_#{avatar_name}?"
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 |file, **options|
48
- __send__(avatar_name).attach(file, **options)
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
- @copy_later = true
64
- ResizeBlobImageJob.perform_later(
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
- return true if @copy_later
87
- puts "\n\nCOPYING AVATAR\n\n"
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 = self.find_by(id: self.id).__send__(avatar_name)
93
- r.purge if r.attached?
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
- purge(to_attachment) if to_attachment.attached?
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
- tmp = Tempfile.new
115
- tmp.binmode
116
- tmp.write(from_attachment.download)
117
- tmp.flush
118
- tmp.rewind
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
- r = self.class.find_by(id: self.id)
121
- from_attachment = r.__send__ from
122
- to_attachment = r.__send__ to
167
+ r = reloaded_record
168
+ from_attachment = r.__send__ from
169
+ to_attachment = r.__send__ to
123
170
 
124
- to_attachment.attach(io: tmp, filename: from_attachment.filename, content_type: from_attachment.content_type)
125
- tmp.close
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BetterRecord
4
- VERSION = '0.15.2'
4
+ VERSION = '0.16.0'
5
5
  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.15.2
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