Class: Upload
Overview
== Schema Information
Table name: uploads
Database name: primary
id :integer not null, primary key
asset :jsonb
attachment_mime_type :string
attachment_name :string
attachment_processing :boolean
attachment_size :integer
attachment_uid :string
category :string(255)
document_date :date
expiration_date :date
note :text
position :integer
resource_type :string(255)
template :string
thumbnail_asset :jsonb
type :string(30)
created_at :datetime
updated_at :datetime
resource_id :integer
Indexes
idx_resource_type_category (resource_type,category) WHERE (resource_id IS NULL)
idx_resource_type_category_resource_id (resource_type,category,resource_id)
index_uploads_on_category (category)
index_uploads_on_resource_type_and_resource_id (resource_type,resource_id)
index_uploads_on_type (type) WHERE (type IS NOT NULL)
Defined Under Namespace
Classes: CurrentPaths
Constant Summary
collapse
- MODEL_TO_CATEGORIES =
.each_with_object({}) {|cat, hsh| hsh[cat] = cat.to_s.humanize.titleize }.freeze
{
activity: %i[activity_attachment msrp_quote_pdf_transmission organization_quote_pdf_transmission room_layout],
call_record: %i[call_record],
certification: %i[agreement liability_insurance],
check: %i[check],
credit_memo: %i[credit_memo_pdf statement_of_account_pdf],
contact: %i[liability_insurance contract],
customer: %i[liability_insurance contract],
delivery: %i[all_intl_forms_pdf all_labels_pdf manually_generated_combined_pdf manual_ship_label pick_slip_pdf serial_numbers_pdf ship_bol_pdf ship_ci_pdf electronic_ship_ci_pdf split_pick_slip_pdf],
employee: %i[certificate contract resume form],
item: %i[usmca_certificate other_certificate],
invoice: %i[invoice_pdf statement_of_account_pdf],
mail_activity: %i[all_labels_pdf],
manifest: %i[manifest_pdf],
speedee_manifest: %i[summary_pdf manifest_csv],
opportunity: %i[installation_plan_cad installation_plan_image room_layout room_layout_image],
order: %i[custom_order_agreement custom_packing_slip_pdf early_ship_label installation_plan_pdf invalid_pick_slip_pdf manual_ship_label manual_smart_preset_form master_carton_label other pick_slip_pdf purchase_order ship_bol_pdf],
purchase_order: %i[purchase_order],
quote: %i[copy_of_plans_pdf msrp_quote_pdf organization_quote_pdf],
rma: %i[letter_ship_label_pdf photo rma_return_instructions_pdf],
room_configuration: %i[design_guideline electrical_plan_pdf installation_plan_cad installation_plan_image installation_plan_pdf installation_heated_area other photo room_layout room_layout_image warranty_card warranty_card_pdf
heat_loss_customer_form heat_loss_report multizone_plan multizone_plan_pdf],
service_job: %i[room_layout tstat_job_result],
shipment: %i[container_label letter_ship_label_pdf manual_ship_label ship_bol_pdf ship_label_image ship_label_pdf],
statement_of_account: %i[statement_of_account_pdf],
store: %i[super_pick_slip],
supplier: %i[price_list contract],
edi_communication_log: %i[custom_packing_slip_pdf feed_document_result_xml feed_document_result_json feed_document_result_gzip],
exported_catalog_item_packet: %i[exported_packet],
catalog_item: %i[amalytix_snapshot],
video: %i[audio_extraction captions],
assistant_conversation: %i[assistant_attachment],
tax_exemption: %i[tax_exemption]
}.freeze
- UNCLASSIFIED_CATEGORIES =
%i[accounting_documents all_postage_labels_path_pdf article_pdf fedex_manifest google_local_inventory_feed misc preview_organization_quote_pdf price_list_pdf reviews_io_product_feed super_invoice super_pick_slip super_pick_slip_pdf super_serial_number_label_pdf super_soa
agreement_pdf order_review archive declaration_of_steel_aluminimum_copper].freeze
- EXCLUDE_CATEGORIES_FOR_MANUAL_UPLOAD =
we don't want people accidentally manually uploading the wrong category when these are only generated by HW
%i[all_postage_labels_path_pdf article_pdf preview_organization_quote_pdf price_list_pdf super_pick_slip_pdf super_serial_number_label_pdf super_soa agreement_pdf electrical_plan_pdf installation_plan_pdf multizone_plan_pdf].freeze
- CATEGORIES =
(MODEL_TO_CATEGORIES.values.flatten + UNCLASSIFIED_CATEGORIES).uniq
- IMAGE_EXTENSIONS =
Marcel::EXTENSIONS.select { |_, mime_type| mime_type.start_with?('image/') }.keys.freeze
- RESOURCES_WITH_UPLOADS_COUNT =
Counter cache for uploads_count on polymorphic resources
Only increment for resource types that have an uploads_count column
%w[Activity Customer Contact Employee Order Quote Rma Shipment Supplier].freeze
Models::Auditable::ALWAYS_IGNORED
Instance Attribute Summary collapse
#creator, #updater
Has and belongs to many
collapse
Class Method Summary
collapse
-
.all_categories_for_select ⇒ Object
-
.custom_ship_labels ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are custom ship labels.
-
.has_document_date?(resource_type) ⇒ Boolean
-
.has_role_restrictions?(resource_type) ⇒ Boolean
-
.in_category ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are in category.
-
.invalid ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are invalid.
-
.literatures ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are literatures.
-
.most_recent_first ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are most recent first.
-
.options_for_categories_select(class_name, user: nil, include_other: true, exclude: []) ⇒ Object
-
.sorted_by_position ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are sorted by position.
-
.temp_location(filename) ⇒ Object
-
.uploadify(path, category, resource = nil, filename = nil, _do_not_delete = false, expiration_date = nil) ⇒ Object
-
.uploadify_from_data(file_name:, data:, category:, resource: nil) ⇒ Object
-
.uploadify_from_url(file_name:, url:, category:, resource: nil, expiration_date: nil, headers: nil) ⇒ Object
-
.valid ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are valid.
Instance Method Summary
collapse
#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
#publish_event
Instance Attribute Details
#attachment ⇒ Object
132
|
# File 'app/models/upload.rb', line 132
validates :attachment, presence: true
|
#import ⇒ Object
Returns the value of attribute import.
123
124
125
|
# File 'app/models/upload.rb', line 123
def import
@import
end
|
#local_file_path ⇒ Object
Returns the value of attribute local_file_path.
123
124
125
|
# File 'app/models/upload.rb', line 123
def local_file_path
@local_file_path
end
|
#should_destroy ⇒ Object
Returns the value of attribute should_destroy.
123
124
125
|
# File 'app/models/upload.rb', line 123
def should_destroy
@should_destroy
end
|
#template ⇒ Object
138
|
# File 'app/models/upload.rb', line 138
validates :template, presence: true, if: proc { |u| u.category == 'installation_plan_image' }
|
Class Method Details
.all_categories_for_select ⇒ Object
171
172
173
|
# File 'app/models/upload.rb', line 171
def self.all_categories_for_select
CATEGORIES.sort.map { |c| [c.to_s.humanize.titleize, c.to_s] }
end
|
.custom_ship_labels ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are custom ship labels. Active Record Scope
145
|
# File 'app/models/upload.rb', line 145
scope :custom_ship_labels, -> { where(category: %w[master_carton_label manual_ship_label]) }
|
.has_document_date?(resource_type) ⇒ Boolean
544
545
546
|
# File 'app/models/upload.rb', line 544
def self.has_document_date?(resource_type)
%w[StatementOfAccount CreditMemo Invoice].include?(resource_type)
end
|
.has_role_restrictions?(resource_type) ⇒ Boolean
536
537
538
|
# File 'app/models/upload.rb', line 536
def self.has_role_restrictions?(resource_type)
resource_type == 'Employee'
end
|
.in_category ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are in category. Active Record Scope
142
|
# File 'app/models/upload.rb', line 142
scope :in_category, ->(cat) { where(category: cat) }
|
.invalid ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are invalid. Active Record Scope
141
|
# File 'app/models/upload.rb', line 141
scope :invalid, -> { where("category LIKE 'invalid_%'") }
|
.literatures ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are literatures. Active Record Scope
146
|
# File 'app/models/upload.rb', line 146
scope :literatures, -> { where(type: 'Literature').joins(:publication) }
|
.most_recent_first ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are most recent first. Active Record Scope
143
|
# File 'app/models/upload.rb', line 143
scope :most_recent_first, -> { reorder('uploads.created_at DESC') }
|
.options_for_categories_select(class_name, user: nil, include_other: true, exclude: []) ⇒ Object
329
330
331
332
333
334
335
336
337
338
339
340
341
|
# File 'app/models/upload.rb', line 329
def self.options_for_categories_select(class_name, user: nil, include_other: true, exclude: [])
categories = []
if class_name.present?
symbolized_class_name = class_name if class_name.is_a?(Symbol)
symbolized_class_name ||= class_name.tableize.singularize.to_sym
new_categories = MODEL_TO_CATEGORIES[symbolized_class_name]
categories += new_categories if new_categories.present?
end
categories += [:other] if include_other
categories.reject! { |cat| cat.in?(exclude) }
categories.reject! { |cat| cat.in?(EXCLUDE_CATEGORIES_FOR_MANUAL_UPLOAD) }
categories.uniq.map { |cat| [cat.to_s.humanize.titleize.gsub('Custom', 'This is public and always enclosed: * Custom'), cat] }.sort_by { |cat_arr| cat_arr.last == :purchase_order ? '0' : cat_arr.first }
end
|
.sorted_by_position ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are sorted by position. Active Record Scope
144
|
# File 'app/models/upload.rb', line 144
scope :sorted_by_position, -> { reorder('uploads.position, uploads.created_at DESC') }
|
.temp_location(filename) ⇒ Object
323
324
325
326
327
|
# File 'app/models/upload.rb', line 323
def self.temp_location(filename)
tmp_dir = Rails.application.config.x.temp_storage_path
FileUtils.mkdir(tmp_dir) unless File.directory?(tmp_dir)
tmp_dir.join(filename)
end
|
.uploadify(path, category, resource = nil, filename = nil, _do_not_delete = false, expiration_date = nil) ⇒ Object
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
|
# File 'app/models/upload.rb', line 282
def self.uploadify(path, category, resource = nil, filename = nil, _do_not_delete = false, expiration_date = nil)
raise ArgumentError, "Upload path is nil (category: #{category}, resource: #{resource&.class&.name} ##{resource&.id})" if path.nil?
if URI(path.to_s).host.present?
uploadify_from_url(file_name: filename, url: path, category:, resource:, expiration_date:)
elsif File.exist?(path)
upload = new(category:, resource:, expiration_date:)
upload.attachment_name ||= filename
upload.attachment = File.new(path)
upload.save!
upload.set_local_file_path(path)
upload
else
msg = "File is missing at #{path}, category: #{category}, resource: #{resource&.class&.name} #{resource&.id}"
raise StandardError.new(msg)
end
end
|
.uploadify_from_data(file_name:, data:, category:, resource: nil) ⇒ Object
301
302
303
304
305
306
307
308
309
310
|
# File 'app/models/upload.rb', line 301
def self.uploadify_from_data(file_name:, data:, category:, resource: nil)
file_name = ActiveStorage::Filename.new(file_name).sanitized
file_path = temp_location(file_name)
File.open(file_path, 'wb') do |file|
file.write data
file.flush
file.fsync
end
uploadify(file_path, category, resource, file_name)
end
|
.uploadify_from_url(file_name:, url:, category:, resource: nil, expiration_date: nil, headers: nil) ⇒ Object
312
313
314
315
316
317
318
319
320
321
|
# File 'app/models/upload.rb', line 312
def self.uploadify_from_url(file_name:, url:, category:, resource: nil, expiration_date: nil, headers: nil)
require 'down'
file_path = temp_location(file_name)
= .stringify_keys if .present?
||= {}
Retryable.retryable(tries: 3, sleep: lambda { |n| 4**n }, on: Retryable::TIMEOUT_CLASSES) do |_attempt_number, _exception|
Down.download(url, headers:, destination: file_path) { |client| client.timeout(read: 60) }
end
uploadify(file_path, category, resource, file_name)
end
|
.valid ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are valid. Active Record Scope
140
|
# File 'app/models/upload.rb', line 140
scope :valid, -> { where("category NOT LIKE 'invalid_%'") }
|
Instance Method Details
#active_download_token(expires_at = nil) ⇒ Object
179
180
181
182
183
|
# File 'app/models/upload.rb', line 179
def active_download_token(expires_at = nil)
dt = download_tokens.where('expires_at IS NULL or expires_at > ?', Time.current).order(Arel.sql('expires_at IS NOT NULL, expires_at DESC')).first
dt ||= create_new_download_token(expires_at)
dt.token
end
|
#articles ⇒ ActiveRecord::Relation<Article>
101
|
# File 'app/models/upload.rb', line 101
has_and_belongs_to_many :articles
|
#attachment_ext ⇒ Object
409
410
411
|
# File 'app/models/upload.rb', line 409
def attachment_ext
File.extname(attachment_name).downcase.delete_prefix('.') if attachment_name.present?
end
|
#browser_previewable? ⇒ Boolean
True for file types modern browsers can render natively (PDFs and images).
Used by the show action to decide whether to serve inline or force download.
423
424
425
|
# File 'app/models/upload.rb', line 423
def browser_previewable?
is_pdf? || is_image?
end
|
#cad_category? ⇒ Boolean
532
533
534
|
# File 'app/models/upload.rb', line 532
def cad_category?
category.in?(%w[room_layout_cad installation_plan_cad tracer_solution_cad])
end
|
#clone_with_file(new_resource = nil) ⇒ Object
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
|
# File 'app/models/upload.rb', line 263
def clone_with_file(new_resource = nil)
new_upload = nil
return unless attachment.present?
begin
new_upload = Upload.new(category:,
resource: new_resource,
template:,
note:)
new_upload.attachment_url = presigned_url(expires_in: 10.minutes)
new_upload.attachment_name = attachment_name
new_upload.attachment_mime_type = mime_type
rescue StandardError => e
Rails.logger.error "File could not be found for #{id}, #{e}"
new_upload = nil
end
new_upload
end
|
#communications ⇒ ActiveRecord::Relation<Communication>
100
|
# File 'app/models/upload.rb', line 100
has_and_belongs_to_many :communications
|
#create_new_download_token(expires_at = nil) ⇒ Object
175
176
177
|
# File 'app/models/upload.rb', line 175
def create_new_download_token(expires_at = nil)
download_tokens.create(expires_at:)
end
|
#deletable? ⇒ Boolean
366
367
368
369
370
371
372
|
# File 'app/models/upload.rb', line 366
def deletable?
if resource_type == 'RoomConfiguration'
!resource.complete?
else
false
end
end
|
#determine_orientation ⇒ Object
209
210
211
212
213
214
215
216
|
# File 'app/models/upload.rb', line 209
def determine_orientation
case template
when /landscape/
'Landscape'
else
'Portrait'
end
end
|
#determine_page_size ⇒ Object
194
195
196
197
198
199
200
201
202
203
|
# File 'app/models/upload.rb', line 194
def determine_page_size
case template
when /tabloid/
'Tabloid'
when /plotter/
'Plotter'
else
'Letter'
end
end
|
#download_tokens ⇒ ActiveRecord::Relation<DownloadToken>
98
|
# File 'app/models/upload.rb', line 98
has_many :download_tokens, inverse_of: :upload
|
#file_exists? ⇒ Boolean
356
357
358
359
360
361
362
363
364
|
# File 'app/models/upload.rb', line 356
def file_exists?
return false if attachment.nil?
signed_url = presigned_url(expires_in: 60.minutes)
response = HTTP.('Range' => 'bytes=0-0').get(signed_url)
response.status.success?
rescue HTTP::Error, Dragonfly::Job::Fetch::NotFound
false
end
|
#file_name_for_download ⇒ Object
205
206
207
|
# File 'app/models/upload.rb', line 205
def file_name_for_download
attachment_name end
|
#get_local_file_path ⇒ Object
Returns the local file path but only if the file still exists on disk.
Checks the instance attr first, then falls back to the process-level cache
so that freshly loaded instances of the same record can reuse temp files.
555
556
557
558
559
560
561
562
563
564
565
|
# File 'app/models/upload.rb', line 555
def get_local_file_path
path = local_file_path || (id && CurrentPaths[id])
if path.present? && File.exist?(path.to_s)
self.local_file_path = path
path
else
self.local_file_path = nil
CurrentPaths.delete(id) if id
nil
end
end
|
#has_document_date? ⇒ Boolean
548
549
550
|
# File 'app/models/upload.rb', line 548
def has_document_date?
self.class.has_document_date?(resource_type)
end
|
#has_role_restrictions? ⇒ Boolean
540
541
542
|
# File 'app/models/upload.rb', line 540
def has_role_restrictions?
self.class.has_role_restrictions?(resource_type)
end
|
#has_thumbnail? ⇒ Boolean
427
428
429
|
# File 'app/models/upload.rb', line 427
def has_thumbnail?
is_image_or_pdf?
end
|
#image_attachment(dimensions) ⇒ Object
431
432
433
434
435
436
437
|
# File 'app/models/upload.rb', line 431
def image_attachment(dimensions)
if is_image?
attachment.thumb(dimensions)
elsif is_pdf? pdf_thumbnail_attachment(dimensions)
end
end
|
#image_category? ⇒ Boolean
528
529
530
|
# File 'app/models/upload.rb', line 528
def image_category?
category.in?(%w[installation_plan_image tracer_solution_image])
end
|
#image_url(dimensions) ⇒ Object
439
440
441
|
# File 'app/models/upload.rb', line 439
def image_url(dimensions)
image_attachment(dimensions)&.url
end
|
#is_audio? ⇒ Boolean
393
394
395
|
# File 'app/models/upload.rb', line 393
def is_audio?
mime_type&.start_with?('audio/')
end
|
#is_image? ⇒ Boolean
401
402
403
|
# File 'app/models/upload.rb', line 401
def is_image?
mime_type&.start_with?('image/') || (undefined_mime_type? && IMAGE_EXTENSIONS.include?(attachment_ext))
end
|
#is_image_or_pdf? ⇒ Boolean
405
406
407
|
# File 'app/models/upload.rb', line 405
def is_image_or_pdf?
is_image? || is_pdf?
end
|
#is_mp3? ⇒ Boolean
388
389
390
391
|
# File 'app/models/upload.rb', line 388
def is_mp3?
(mime_type =~ %r{^audio/(?:mp3|mpeg|mpeg3|mpg|x-mp3|x-mpeg|x-mpeg3|x-mpegaudio|x-mpg)$}).present? ||
(undefined_mime_type? && attachment_ext == 'mp3')
end
|
#is_pdf? ⇒ Boolean
417
418
419
|
# File 'app/models/upload.rb', line 417
def is_pdf?
mime_type == 'application/pdf' || (undefined_mime_type? && attachment_ext == 'pdf')
end
|
#is_video? ⇒ Boolean
397
398
399
|
# File 'app/models/upload.rb', line 397
def is_video?
mime_type&.start_with?('video/')
end
|
#is_wav? ⇒ Boolean
383
384
385
386
|
# File 'app/models/upload.rb', line 383
def is_wav?
['audio/wav', 'audio/x-wav'].include?(mime_type) ||
(undefined_mime_type? && attachment_ext == 'wav')
end
|
#items ⇒ ActiveRecord::Relation<Item>
103
|
# File 'app/models/upload.rb', line 103
has_and_belongs_to_many :items
|
#mime_type ⇒ Object
374
375
376
377
378
379
380
381
|
# File 'app/models/upload.rb', line 374
def mime_type
return attachment_mime_type if attachment_mime_type.present?
attachment_mime_type
end
|
#mime_type_symbol ⇒ Object
512
513
514
515
516
|
# File 'app/models/upload.rb', line 512
def mime_type_symbol
attachment.ext.to_sym
rescue StandardError
nil
end
|
#ok_to_delete? ⇒ Boolean
518
519
520
521
522
|
# File 'app/models/upload.rb', line 518
def ok_to_delete?
!Item.exists?(literature_id: id) && resource.nil?
end
|
#options_for_categories_select(user: nil, include_other: true, exclude: []) ⇒ Object
349
350
351
352
353
354
|
# File 'app/models/upload.rb', line 349
def options_for_categories_select(user: nil, include_other: true, exclude: [])
class_name_to_use = resource&.class&.name
class_name_to_use ||= :item if items.present?
self.class.options_for_categories_select(class_name_to_use, user:, include_other:, exclude:)
end
|
#pdf_category? ⇒ Boolean
524
525
526
|
# File 'app/models/upload.rb', line 524
def pdf_category?
category.in?(%w[custom_packing_slip_pdf purchase_order])
end
|
#pdf_thumbnail_attachment(dimensions = '600x600>', density: 150) ⇒ Object
443
444
445
446
447
448
449
450
|
# File 'app/models/upload.rb', line 443
def pdf_thumbnail_attachment(dimensions = '600x600>', density: 150)
return unless is_pdf?
attachment.thumb(dimensions, format: :avif, input_options: { page: 0, dpi: density })
end
|
#pdf_thumbnail_url(dimensions = '600x600>', density: 400) ⇒ Object
452
453
454
455
456
|
# File 'app/models/upload.rb', line 452
def pdf_thumbnail_url(dimensions = '600x600>', density: 400)
return unless is_pdf?
pdf_thumbnail_attachment(dimensions, density:).url
end
|
#presigned_url(expires_in: 1.day, download: false, file_name: nil) ⇒ Object
Generate a presigned URL for the attachment locally without S3 network calls.
Uses Dragonfly's datastore.url_for which is purely local AWS Sig V4 computation.
Use this for preview/download links where you need a signed URL quickly.
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
|
# File 'app/models/upload.rb', line 473
def presigned_url(expires_in: 1.day, download: false, file_name: nil)
return nil unless attachment_uid.present? && attachment.present?
query_params = {}
if download || file_name.present?
safe_filename = (file_name || attachment_name).to_s.parameterize(separator: '_')
safe_filename = "#{safe_filename}#{File.extname(attachment_name)}" unless safe_filename.include?('.')
disposition = download ? 'attachment' : 'inline'
query_params['response-content-disposition'] = "#{disposition}; filename=\"#{safe_filename}\""
end
attachment.app.datastore.url_for(
attachment_uid,
scheme: 'https',
expires: expires_in.from_now.to_i,
query: query_params.presence
)
end
|
#publication ⇒ Item
85
|
# File 'app/models/upload.rb', line 85
has_one :publication, class_name: 'Item', inverse_of: :literature, foreign_key: :literature_id
|
#recipient_party_id ⇒ Object
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
|
# File 'app/models/upload.rb', line 493
def recipient_party_id
p = begin
resource.customer_id
rescue StandardError
nil
end
p ||= begin
resource.party_id
rescue StandardError
nil
end
p ||= begin
upload.resource.supplier_id
rescue StandardError
nil
end
p
end
|
#resource ⇒ Resource
84
|
# File 'app/models/upload.rb', line 84
belongs_to :resource, polymorphic: true, optional: true
|
#resource_combo ⇒ Object
251
252
253
|
# File 'app/models/upload.rb', line 251
def resource_combo
"#{resource_type}|#{resource_id}" if resource
end
|
#resource_combo=(combo_val) ⇒ Object
255
256
257
258
259
260
261
|
# File 'app/models/upload.rb', line 255
def resource_combo=(combo_val)
return unless combo_val.present?
values = combo_val.split('|')
self.resource_type = values[0]
self.resource_id = values[1]
end
|
#roles ⇒ ActiveRecord::Relation<Role>
102
|
# File 'app/models/upload.rb', line 102
has_and_belongs_to_many :roles
|
#scope_condition ⇒ Object
Uploads should only be sorted based on the presence of resource id of category
otherwise if those are null then the whole upload table gets a shuffle. big
performance hit and deadlocks
:resource_id, :category
154
155
156
157
158
159
160
161
162
163
164
165
|
# File 'app/models/upload.rb', line 154
def scope_condition
if resource_type && resource_id
cnds = {
resource_type:,
resource_id:
}
cnds[:category] = category if category.present?
cnds
else
{ id: -1 }
end
end
|
#set_local_file_path(file_path) ⇒ Object
Ensures our local file path is stored in the temp storage directory (for
sendfile header acceleration) and registers it in the request-scoped cache
so other instances of the same record can find it without hitting S3.
570
571
572
573
574
575
576
577
578
579
|
# File 'app/models/upload.rb', line 570
def set_local_file_path(file_path)
if File.dirname(file_path.to_s) == Rails.application.config.x.temp_storage_path.to_s
self.local_file_path = file_path
else
self.local_file_path = Rails.application.config.x.temp_storage_path.join(File.basename(file_path))
FileUtils.cp(file_path, local_file_path.to_s)
end
CurrentPaths[id] = local_file_path.to_s if id.present?
local_file_path
end
|
#template_options_for_select ⇒ Object
343
344
345
346
347
|
# File 'app/models/upload.rb', line 343
def template_options_for_select
return [] unless resource.respond_to?(:template_options_for_select)
resource.template_options_for_select
end
|
#thumbnail_2x_url(dimensions: '184x122>') ⇒ Object
464
465
466
467
468
|
# File 'app/models/upload.rb', line 464
def thumbnail_2x_url(dimensions: '184x122>')
return unless has_thumbnail?
image_attachment(dimensions)&.url
end
|
#thumbnail_url(dimensions: '92x61>') ⇒ Object
458
459
460
461
462
|
# File 'app/models/upload.rb', line 458
def thumbnail_url(dimensions: '92x61>')
return unless has_thumbnail?
image_attachment(dimensions)&.url
end
|
#title ⇒ Object
189
190
191
192
|
# File 'app/models/upload.rb', line 189
def title
category.humanize.titleize.to_s
end
|
#to_file(file_path: nil, file_name: nil) ⇒ Object
Downloads the file using the Down library to a temporary place
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
|
# File 'app/models/upload.rb', line 219
def to_file(file_path: nil, file_name: nil)
if get_local_file_path
Rails.logger.info "to_file getting upload #{id} from local path: #{get_local_file_path}"
return get_local_file_path unless file_path.present? && file_path.to_s != get_local_file_path
FileUtils.cp get_local_file_path, file_path
file_path
else
remote_url = presigned_url(expires_in: 15.minutes)
Rails.logger.info "to_file getting upload #{id} from remote path #{remote_url}"
remote_file_name = attachment_name.presence || URI.parse(url).path
ext = begin
File.extname(remote_file_name)
rescue StandardError
nil
end
file_name ||= "tmp_#{id}_#{Time.current.strftime('%Y-%m-%d-%H%M%S')}#{ext}"
file_path ||= Rails.application.config.x.temp_storage_path.join(file_name)
Retryable.retryable(tries: 3, sleep: lambda { |n| 4**n }, on: Retryable::TIMEOUT_CLASSES) do |attempt_number, exception|
ErrorReporting.error(exception, message: "Exception on download attempt #{attempt_number} for #{remote_url}") if exception
Down::Http.download(remote_url, destination: file_path) { |client| client.timeout(read: 30) }
end
set_local_file_path(file_path) end
file_path.to_s
end
|
#to_s ⇒ Object
185
186
187
|
# File 'app/models/upload.rb', line 185
def to_s
attachment_name || "Upload id #{id}"
end
|
#undefined_mime_type? ⇒ Boolean
413
414
415
|
# File 'app/models/upload.rb', line 413
def undefined_mime_type?
mime_type.blank? || mime_type == 'application/octet-stream'
end
|