effective_assets 1.11.4 → 1.12.1

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: 91867f057c8237f0c9b602989b2c75b9805c898b799c83d4de6c96e3cbca2c60
4
- data.tar.gz: 6272d43a0d8e24bd9c270a8a7f808d2804477f13057663328e3823bca416ddb0
3
+ metadata.gz: f65f48554e7a828db12f7dee36c5b88664d05d62e9cef510ce45bbd63087d01c
4
+ data.tar.gz: 110be6a9d526d749485332af287a9ed78b392dc48f0f4790f8d90764e91b7530
5
5
  SHA512:
6
- metadata.gz: 1243fc18c744665d68bad27d273e98a451eb78e1c212c62fd7aa2e095996ae2677e856f76614fdb3aefdf2f24419ef092291666891f52b0391a47ad8e3b8e5f5
7
- data.tar.gz: 5ea43c65ffcad79c5f2a16bd7266e6529bb37f71d68d23f8a7f3332bef777c543face50148888d7b1f3740b1d8392f20f74e0907cada172772492d8315425a0d
6
+ metadata.gz: '019b6aa40e1af5d85d48eea6b80b0d7a89c981412099a500908235233cfec771f11c3447f69979555a78c90f4ba808ddaf863875fdf8eb0869608dda0881dea7'
7
+ data.tar.gz: eb176c764207dca6bb761df0a08bfb3bdfd945cc493284273e6db43adc5df3410ba5826359c560133eb775816151b7113295ec2f3fa79ecd0cd4588a4661e495
@@ -0,0 +1,17 @@
1
+ module Effective
2
+ class AssetReplacerJob < ::ApplicationJob
3
+
4
+ queue_as :default
5
+
6
+ if defined?(Sidekiq)
7
+ # The retry setting works. But none of these waits seem to. Still getting exponential backoff.
8
+ sidekiq_options retry: 2, retry_in: 10, wait: 10
9
+ sidekiq_retry_in { |count, exception| 10 }
10
+ end
11
+
12
+ def perform(attachment, box)
13
+ Effective::AssetReplacer.new.replace_attachment!(attachment, box)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Effective
2
+ class SnippetReplacerJob < ::ApplicationJob
3
+
4
+ queue_as :default
5
+
6
+ if defined?(Sidekiq)
7
+ # The retry setting works. But none of these waits seem to. Still getting exponential backoff.
8
+ sidekiq_options retry: 2, retry_in: 10, wait: 10
9
+ sidekiq_retry_in { |count, exception| 10 }
10
+ end
11
+
12
+ def perform(region)
13
+ Effective::SnippetReplacer.new.replace_region!(region)
14
+ end
15
+
16
+ end
17
+ end
@@ -195,9 +195,6 @@ module Effective
195
195
  # Do Nothing
196
196
  elsif upload_file.include?(Effective::Asset.string_base_path)
197
197
  puts 'String-based Asset processing and uploading'
198
-
199
- data.cache_stored_file!
200
- data.retrieve_from_cache!(data.cache_name)
201
198
  data.recreate_versions!
202
199
  elsif upload_file.include?(Effective::Asset.s3_base_path)
203
200
  # Carrierwave must download the file, process it, then upload the generated versions to S3
@@ -0,0 +1,156 @@
1
+ # Looks at the Effective::Asset and Effective::Attachments and converts to ActiveStorage
2
+ #
3
+ # 1. Put in the has_attached_files to each model to be upgraded
4
+ # 2. Remove the acts_as_asset_box
5
+
6
+ require 'timeout'
7
+
8
+ module Effective
9
+ class AssetReplacer
10
+ include ActiveStorage::Blob::Analyzable
11
+
12
+ BATCH_SIZE = 500
13
+ TIMEOUT = 120
14
+
15
+ def replace!(skip_existing: false)
16
+ verify!
17
+
18
+ attachments = attachments_to_process().to_a
19
+
20
+ while(true)
21
+ wait_for_active_job!
22
+
23
+ puts "\nEnqueuing #{attachments.length} attachments with ids #{attachments.first.id} to #{attachments.last.id}"
24
+
25
+ attachments.each do |attachment|
26
+ asset = attachment.asset
27
+ attachable = attachment.attachable
28
+ next if asset.blank? || attachable.blank?
29
+
30
+ box = attachment.box.singularize
31
+ boxes = attachment.box
32
+
33
+ one = attachable.respond_to?(box) && attachable.send(box).kind_of?(ActiveStorage::Attached::One)
34
+ many = attachable.respond_to?(boxes) && attachable.send(boxes).kind_of?(ActiveStorage::Attached::Many)
35
+ box = (one ? box : boxes)
36
+
37
+ if skip_existing
38
+ existing = Array(attachable.send(box))
39
+
40
+ if existing.any? { |obj| obj.respond_to?(:filename) && obj.filename.to_s == asset.file_name }
41
+ puts("Skipping existing #{attachable.class.name} #{attachable.id} #{box} #{asset.file_name}.")
42
+ next
43
+ end
44
+ end
45
+
46
+ Effective::AssetReplacerJob.perform_later(attachment, box)
47
+ end
48
+
49
+ attachments = attachments_to_process().where.not(id: attachments.map(&:id))
50
+ break if attachments.to_a.blank?
51
+
52
+ GC.start
53
+ end
54
+
55
+ puts "\nAll Done. Have a great day."
56
+ true
57
+ end
58
+
59
+ # This is called on the background by the AssetReplacerJob
60
+ def replace_attachment!(attachment, box)
61
+ raise('expected an Effective::Attachment') unless attachment.kind_of?(Effective::Attachment)
62
+ puts("Processing attachment ##{attachment.id}")
63
+
64
+ asset = attachment.asset
65
+ attachable = attachment.attachable
66
+
67
+ attachable.replacing_asset = true if attachable.respond_to?(:replacing_asset=)
68
+
69
+ Timeout.timeout(TIMEOUT) do
70
+ attachable.send(box).attach(
71
+ io: URI.open(asset.url),
72
+ filename: asset.file_name,
73
+ content_type: asset.content_type.presence,
74
+ identify: (asset.content_type.blank?)
75
+ )
76
+
77
+ attachment.update_column(:replaced, true)
78
+ end
79
+
80
+ true
81
+ end
82
+
83
+ def verify!
84
+ raise('expected effective assets') unless defined?(Effective::Asset)
85
+ raise('expected active storage') unless defined?(ActiveStorage)
86
+
87
+ unless Effective::Attachment.new.respond_to?(:replaced?)
88
+ raise('please add a replaced boolean to Effective::Attachment. add_column :attachments, :replaced, :boolean')
89
+ end
90
+
91
+ (Effective::Attachment.all.pluck(:attachable_type, :box).uniq).each do |name, boxes|
92
+ next if name.blank? || boxes.blank?
93
+
94
+ box = boxes.singularize
95
+
96
+ klass = name.safe_constantize
97
+ raise("invalid class #{klass}") unless klass.present?
98
+
99
+ instance = klass.new
100
+
101
+ if instance.respond_to?(:effective_assets)
102
+ raise("please remove acts_as_asset_box() from #{klass.name}")
103
+ end
104
+
105
+ unless instance.respond_to?(box) || instance.respond_to?(boxes)
106
+ raise("expected #{klass.name} to has_one_attached :#{box} or has_many_attached :#{boxes}")
107
+ end
108
+
109
+ one = instance.respond_to?(box) && instance.send(box).kind_of?(ActiveStorage::Attached::One)
110
+ many = instance.respond_to?(boxes) && instance.send(boxes).kind_of?(ActiveStorage::Attached::Many)
111
+
112
+ unless one.present? || many.present?
113
+ raise("expected #{klass.name} to has_one_attached :#{box} or has_many_attached :#{boxes}")
114
+ end
115
+ end
116
+
117
+ puts 'All attachment classes verified.'
118
+
119
+ true
120
+ end
121
+
122
+ def reset!
123
+ Effective::Attachment.update_all(replaced: false)
124
+ end
125
+
126
+ private
127
+
128
+ def wait_for_active_job!
129
+ while(true)
130
+ if(jobs = enqueued_jobs_count) > (BATCH_SIZE / 10)
131
+ print '.'; sleep(3)
132
+ else
133
+ break
134
+ end
135
+ end
136
+ end
137
+
138
+ # The last BATCH_SIZE attachments
139
+ def attachments_to_process
140
+ Effective::Attachment.all
141
+ .includes(:asset)
142
+ .where(replaced: [nil, false])
143
+ .reorder(id: :desc)
144
+ .limit(BATCH_SIZE)
145
+ end
146
+
147
+ def enqueued_jobs_count
148
+ if Rails.application.config.active_job.queue_adapter == :sidekiq
149
+ Sidekiq::Stats.new.enqueued.to_i
150
+ else
151
+ ActiveJob::Base.queue_adapter.enqueued_jobs.count
152
+ end
153
+ end
154
+
155
+ end
156
+ end
@@ -0,0 +1,67 @@
1
+ # Replaces the [snippet_x] in all effective regions with static content
2
+
3
+ module Effective
4
+ class SnippetReplacer
5
+ include ActiveStorage::Blob::Analyzable
6
+ include ActionView::Helpers::UrlHelper
7
+ include ActionView::Helpers::AssetTagHelper
8
+
9
+ def replace!
10
+ raise('expected effective regions') unless defined?(Effective::Region)
11
+ raise('expected effective assets') unless defined?(Effective::Asset)
12
+ raise('expected active storage') unless defined?(ActiveStorage)
13
+
14
+ Effective::Region.with_snippets.find_each do |region|
15
+ Effective::SnippetReplacerJob.perform_later(region)
16
+ end
17
+
18
+ puts 'All Done. Background jobs are running. Have a great day.'
19
+ true
20
+ end
21
+
22
+ def replace_region!(region)
23
+ region.snippet_objects.each do |snippet|
24
+ print('.')
25
+
26
+ begin
27
+ case snippet.class.name
28
+ when 'Effective::Snippets::EffectiveAsset'
29
+ replace_effective_asset(region, snippet)
30
+ else
31
+ raise("unsupported snippet: #{snippet.class.name}")
32
+ end
33
+ rescue => e
34
+ puts "\nError: #{e}\n"
35
+ remove_snippet(region, snippet)
36
+ end
37
+ end
38
+
39
+ region.save!
40
+ end
41
+
42
+ def replace_effective_asset(region, snippet)
43
+ asset = snippet.asset
44
+ raise("Effective:Asset id=#{snippet.asset_id || 'none'} does not exist") unless asset.present?
45
+
46
+ blob = ActiveStorage::Blob.create_and_upload!(io: URI.open(asset.url), filename: asset.file_name)
47
+ url = Rails.application.routes.url_helpers.rails_blob_url(blob, only_path: true)
48
+
49
+ content = if asset.image?
50
+ image_tag(url, class: snippet.html_class, alt: snippet.link_title)
51
+ else
52
+ link_to(snippet.link_title, url, class: snippet.html_class, title: snippet.link_title)
53
+ end
54
+
55
+ region.content.sub!("[#{snippet.id}]", content.to_s)
56
+ region.snippets.delete(snippet.id)
57
+
58
+ true
59
+ end
60
+
61
+ def remove_snippet(region, snippet)
62
+ region.content.sub!("[#{snippet.id}]", '')
63
+ region.snippets.delete(snippet.id)
64
+ end
65
+
66
+ end
67
+ end
@@ -8,14 +8,18 @@ module EffectiveAssets
8
8
 
9
9
  # Include acts_as_addressable concern and allow any ActiveRecord object to call it
10
10
  initializer 'effective_assets.active_record' do |app|
11
- ActiveSupport.on_load :active_record do
12
- ActiveRecord::Base.extend(ActsAsAssetBox::ActiveRecord)
11
+ app.config.to_prepare do
12
+ ActiveSupport.on_load :active_record do
13
+ ActiveRecord::Base.extend(ActsAsAssetBox::ActiveRecord)
14
+ end
13
15
  end
14
16
  end
15
17
 
16
18
  initializer 'effective_assets.action_view' do |app|
17
- ActiveSupport.on_load :action_view do
18
- ActionView::Helpers::FormBuilder.send(:include, AssetBoxFormInput)
19
+ app.config.to_prepare do
20
+ ActiveSupport.on_load :action_view do
21
+ ActionView::Helpers::FormBuilder.send(:include, AssetBoxFormInput)
22
+ end
19
23
  end
20
24
  end
21
25
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveAssets
2
- VERSION = '1.11.4'.freeze
2
+ VERSION = '1.12.1'.freeze
3
3
  end
@@ -0,0 +1,5 @@
1
+ # bundle exec rake replace_effective_assets
2
+ desc 'Replaces effective_assets with ActiveStorage'
3
+ task :replace_effective_assets => :environment do
4
+ Effective::AssetReplacer.new.replace!
5
+ end
@@ -0,0 +1,5 @@
1
+ # bundle exec rake replace_effective_snippets
2
+ desc 'Replaces effective_assets snippets with ActiveStorage uploads'
3
+ task :replace_effective_snippets => :environment do
4
+ Effective::SnippetReplacer.new.replace!
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_assets
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.4
4
+ version: 1.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-10 00:00:00.000000000 Z
11
+ date: 2022-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -165,14 +165,17 @@ files:
165
165
  - app/controllers/effective/s3_uploads_controller.rb
166
166
  - app/helpers/effective_assets_helper.rb
167
167
  - app/helpers/effective_assets_s3_helper.rb
168
+ - app/jobs/effective/asset_replacer_job.rb
168
169
  - app/jobs/effective/process_with_active_job.rb
169
170
  - app/jobs/effective/process_with_sucker_punch_job.rb
171
+ - app/jobs/effective/snippet_replacer_job.rb
170
172
  - app/models/concerns/acts_as_asset_box.rb
171
173
  - app/models/effective/access_denied.rb
172
174
  - app/models/effective/asset.rb
175
+ - app/models/effective/asset_replacer.rb
173
176
  - app/models/effective/attachment.rb
174
177
  - app/models/effective/iframe_upload.rb
175
- - app/models/effective/snippets/effective_asset.rb
178
+ - app/models/effective/snippet_replacer.rb
176
179
  - app/uploaders/effective_assets_uploader.rb
177
180
  - app/uploaders/test_asset_uploader.rb
178
181
  - app/views/active_admin/effective_assets/_edit.html.haml
@@ -201,6 +204,8 @@ files:
201
204
  - lib/inputs/asset_box_input.rb
202
205
  - lib/inputs/asset_box_simple_form_input.rb
203
206
  - lib/tasks/effective_assets_tasks.rake
207
+ - lib/tasks/replace_effective_assets.rake
208
+ - lib/tasks/replace_effective_snippets.rake
204
209
  - lib/validators/asset_box_length_validator.rb
205
210
  - lib/validators/asset_box_presence_validator.rb
206
211
  homepage: https://github.com/code-and-effect/effective_assets
@@ -1,37 +0,0 @@
1
- if defined?(EffectiveRegions)
2
- module Effective
3
- module Snippets
4
- class EffectiveAsset < Snippet
5
- # attr_accessor :asset_id #, Integer
6
- # attr_accessor :html_class #, String
7
- # attr_accessor :link_title #, String
8
- # attr_accessor :private_url # , Boolean
9
-
10
- def snippet_attributes
11
- super + [:asset_id, :html_class, :link_title, :private_url]
12
- end
13
-
14
- def asset
15
- @asset ||= (Effective::Asset.where(:id => asset_id).first if asset_id)
16
- end
17
-
18
- def snippet_tag
19
- :span
20
- end
21
-
22
- def private_url
23
- super || aws_private?
24
- end
25
-
26
- def is_private?
27
- [true, 'true', '1'].include?(private_url)
28
- end
29
-
30
- def aws_private?
31
- (asset.try(:aws_acl) == EffectiveAssets::AWS_PRIVATE)
32
- end
33
-
34
- end
35
- end
36
- end
37
- end