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],
rma_item: %i[photo not_returned_photo],
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
Constants included
from Schedulable
Schedulable::SIMPLE_FORM_OPTIONS
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, 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
config
#after_commit
#publish_event
Instance Attribute Details
#attachment ⇒ Object
137
|
# File 'app/models/upload.rb', line 137
validates :attachment, presence: true
|
#import ⇒ Object
Returns the value of attribute import.
128
129
130
|
# File 'app/models/upload.rb', line 128
def import
@import
end
|
#local_file_path ⇒ Object
Returns the value of attribute local_file_path.
128
129
130
|
# File 'app/models/upload.rb', line 128
def local_file_path
@local_file_path
end
|
#should_destroy ⇒ Object
Returns the value of attribute should_destroy.
128
129
130
|
# File 'app/models/upload.rb', line 128
def should_destroy
@should_destroy
end
|
#template ⇒ Object
143
|
# File 'app/models/upload.rb', line 143
validates :template, presence: true, if: proc { |u| u.category == 'installation_plan_image' }
|
Class Method Details
.all_categories_for_select ⇒ Object
176
177
178
|
# File 'app/models/upload.rb', line 176
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
150
|
# File 'app/models/upload.rb', line 150
scope :custom_ship_labels, -> { where(category: %w[master_carton_label manual_ship_label]) }
|
.has_document_date?(resource_type) ⇒ Boolean
549
550
551
|
# File 'app/models/upload.rb', line 549
def self.has_document_date?(resource_type)
%w[StatementOfAccount CreditMemo Invoice].include?(resource_type)
end
|
.has_role_restrictions?(resource_type) ⇒ Boolean
541
542
543
|
# File 'app/models/upload.rb', line 541
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
147
|
# File 'app/models/upload.rb', line 147
scope :in_category, ->(cat) { where(category: cat) }
|
.invalid ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are invalid. Active Record Scope
146
|
# File 'app/models/upload.rb', line 146
scope :invalid, -> { where("category LIKE 'invalid_%'") }
|
.literatures ⇒ ActiveRecord::Relation<Upload>
A relation of Uploads that are literatures. Active Record Scope
151
|
# File 'app/models/upload.rb', line 151
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
148
|
# File 'app/models/upload.rb', line 148
scope :most_recent_first, -> { reorder('uploads.created_at DESC') }
|
.options_for_categories_select(class_name, include_other: true, exclude: []) ⇒ Object
334
335
336
337
338
339
340
341
342
343
344
345
346
|
# File 'app/models/upload.rb', line 334
def self.options_for_categories_select(class_name, 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
149
|
# File 'app/models/upload.rb', line 149
scope :sorted_by_position, -> { reorder('uploads.position, uploads.created_at DESC') }
|
.temp_location(filename) ⇒ Object
328
329
330
331
332
|
# File 'app/models/upload.rb', line 328
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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
|
# File 'app/models/upload.rb', line 287
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, msg
end
end
|
.uploadify_from_data(file_name:, data:, category:, resource: nil) ⇒ Object
306
307
308
309
310
311
312
313
314
315
|
# File 'app/models/upload.rb', line 306
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
317
318
319
320
321
322
323
324
325
326
|
# File 'app/models/upload.rb', line 317
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: ->(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
145
|
# File 'app/models/upload.rb', line 145
scope :valid, -> { where("category NOT LIKE 'invalid_%'") }
|
Instance Method Details
#active_download_token(expires_at = nil) ⇒ Object
184
185
186
187
188
|
# File 'app/models/upload.rb', line 184
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>
106
|
# File 'app/models/upload.rb', line 106
has_and_belongs_to_many :articles
|
#attachment_ext ⇒ Object
414
415
416
|
# File 'app/models/upload.rb', line 414
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.
428
429
430
|
# File 'app/models/upload.rb', line 428
def browser_previewable?
is_pdf? || is_image?
end
|
#cad_category? ⇒ Boolean
537
538
539
|
# File 'app/models/upload.rb', line 537
def cad_category?
category.in?(%w[room_layout_cad installation_plan_cad tracer_solution_cad])
end
|
#clone_with_file(new_resource = nil) ⇒ Object
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
|
# File 'app/models/upload.rb', line 268
def clone_with_file(new_resource = nil)
new_upload = nil
return if attachment.blank?
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>
105
|
# File 'app/models/upload.rb', line 105
has_and_belongs_to_many :communications
|
#create_new_download_token(expires_at = nil) ⇒ Object
180
181
182
|
# File 'app/models/upload.rb', line 180
def create_new_download_token(expires_at = nil)
download_tokens.create(expires_at:)
end
|
#deletable? ⇒ Boolean
371
372
373
374
375
376
377
|
# File 'app/models/upload.rb', line 371
def deletable?
if resource_type == 'RoomConfiguration'
!resource.complete?
else
false
end
end
|
#determine_orientation ⇒ Object
214
215
216
217
218
219
220
221
|
# File 'app/models/upload.rb', line 214
def determine_orientation
case template
when /landscape/
'Landscape'
else
'Portrait'
end
end
|
#determine_page_size ⇒ Object
199
200
201
202
203
204
205
206
207
208
|
# File 'app/models/upload.rb', line 199
def determine_page_size
case template
when /tabloid/
'Tabloid'
when /plotter/
'Plotter'
else
'Letter'
end
end
|
#download_tokens ⇒ ActiveRecord::Relation<DownloadToken>
103
|
# File 'app/models/upload.rb', line 103
has_many :download_tokens, inverse_of: :upload
|
#file_exists? ⇒ Boolean
361
362
363
364
365
366
367
368
369
|
# File 'app/models/upload.rb', line 361
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
210
211
212
|
# File 'app/models/upload.rb', line 210
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.
560
561
562
563
564
565
566
567
568
569
570
|
# File 'app/models/upload.rb', line 560
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
553
554
555
|
# File 'app/models/upload.rb', line 553
def has_document_date?
self.class.has_document_date?(resource_type)
end
|
#has_role_restrictions? ⇒ Boolean
545
546
547
|
# File 'app/models/upload.rb', line 545
def has_role_restrictions?
self.class.has_role_restrictions?(resource_type)
end
|
#has_thumbnail? ⇒ Boolean
432
433
434
|
# File 'app/models/upload.rb', line 432
def has_thumbnail?
is_image_or_pdf?
end
|
#image_attachment(dimensions) ⇒ Object
436
437
438
439
440
441
442
|
# File 'app/models/upload.rb', line 436
def image_attachment(dimensions)
if is_image?
attachment.thumb(dimensions)
elsif is_pdf? pdf_thumbnail_attachment(dimensions)
end
end
|
#image_category? ⇒ Boolean
533
534
535
|
# File 'app/models/upload.rb', line 533
def image_category?
category.in?(%w[installation_plan_image tracer_solution_image])
end
|
#image_url(dimensions) ⇒ Object
444
445
446
|
# File 'app/models/upload.rb', line 444
def image_url(dimensions)
image_attachment(dimensions)&.url
end
|
#is_audio? ⇒ Boolean
398
399
400
|
# File 'app/models/upload.rb', line 398
def is_audio?
mime_type&.start_with?('audio/')
end
|
#is_image? ⇒ Boolean
406
407
408
|
# File 'app/models/upload.rb', line 406
def is_image?
mime_type&.start_with?('image/') || (undefined_mime_type? && IMAGE_EXTENSIONS.include?(attachment_ext))
end
|
#is_image_or_pdf? ⇒ Boolean
410
411
412
|
# File 'app/models/upload.rb', line 410
def is_image_or_pdf?
is_image? || is_pdf?
end
|
#is_mp3? ⇒ Boolean
393
394
395
396
|
# File 'app/models/upload.rb', line 393
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
422
423
424
|
# File 'app/models/upload.rb', line 422
def is_pdf?
mime_type == 'application/pdf' || (undefined_mime_type? && attachment_ext == 'pdf')
end
|
#is_video? ⇒ Boolean
402
403
404
|
# File 'app/models/upload.rb', line 402
def is_video?
mime_type&.start_with?('video/')
end
|
#is_wav? ⇒ Boolean
388
389
390
391
|
# File 'app/models/upload.rb', line 388
def is_wav?
['audio/wav', 'audio/x-wav'].include?(mime_type) ||
(undefined_mime_type? && attachment_ext == 'wav')
end
|
#items ⇒ ActiveRecord::Relation<Item>
108
|
# File 'app/models/upload.rb', line 108
has_and_belongs_to_many :items
|
#mime_type ⇒ Object
379
380
381
382
383
384
385
386
|
# File 'app/models/upload.rb', line 379
def mime_type
return attachment_mime_type if attachment_mime_type.present?
attachment_mime_type
end
|
#mime_type_symbol ⇒ Object
517
518
519
520
521
|
# File 'app/models/upload.rb', line 517
def mime_type_symbol
attachment.ext.to_sym
rescue StandardError
nil
end
|
#ok_to_delete? ⇒ Boolean
523
524
525
526
527
|
# File 'app/models/upload.rb', line 523
def ok_to_delete?
!Item.exists?(literature_id: id) && resource.nil?
end
|
#options_for_categories_select(include_other: true, exclude: []) ⇒ Object
354
355
356
357
358
359
|
# File 'app/models/upload.rb', line 354
def options_for_categories_select(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, include_other:, exclude:)
end
|
#pdf_category? ⇒ Boolean
529
530
531
|
# File 'app/models/upload.rb', line 529
def pdf_category?
category.in?(%w[custom_packing_slip_pdf purchase_order])
end
|
#pdf_thumbnail_attachment(dimensions = '600x600>', density: 150) ⇒ Object
448
449
450
451
452
453
454
455
|
# File 'app/models/upload.rb', line 448
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
457
458
459
460
461
|
# File 'app/models/upload.rb', line 457
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.
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
|
# File 'app/models/upload.rb', line 478
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
90
|
# File 'app/models/upload.rb', line 90
has_one :publication, class_name: 'Item', inverse_of: :literature, foreign_key: :literature_id
|
#recipient_party_id ⇒ Object
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
|
# File 'app/models/upload.rb', line 498
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
89
|
# File 'app/models/upload.rb', line 89
belongs_to :resource, polymorphic: true, optional: true
|
#resource_combo ⇒ Object
256
257
258
|
# File 'app/models/upload.rb', line 256
def resource_combo
"#{resource_type}|#{resource_id}" if resource
end
|
#resource_combo=(combo_val) ⇒ Object
260
261
262
263
264
265
266
|
# File 'app/models/upload.rb', line 260
def resource_combo=(combo_val)
return if combo_val.blank?
values = combo_val.split('|')
self.resource_type = values[0]
self.resource_id = values[1]
end
|
#roles ⇒ ActiveRecord::Relation<Role>
107
|
# File 'app/models/upload.rb', line 107
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
159
160
161
162
163
164
165
166
167
168
169
170
|
# File 'app/models/upload.rb', line 159
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.
575
576
577
578
579
580
581
582
583
584
|
# File 'app/models/upload.rb', line 575
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
348
349
350
351
352
|
# File 'app/models/upload.rb', line 348
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
469
470
471
472
473
|
# File 'app/models/upload.rb', line 469
def thumbnail_2x_url(dimensions: '184x122>')
return unless has_thumbnail?
image_attachment(dimensions)&.url
end
|
#thumbnail_url(dimensions: '92x61>') ⇒ Object
463
464
465
466
467
|
# File 'app/models/upload.rb', line 463
def thumbnail_url(dimensions: '92x61>')
return unless has_thumbnail?
image_attachment(dimensions)&.url
end
|
#title ⇒ Object
194
195
196
197
|
# File 'app/models/upload.rb', line 194
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
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
250
251
252
253
254
|
# File 'app/models/upload.rb', line 224
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: ->(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
190
191
192
|
# File 'app/models/upload.rb', line 190
def to_s
attachment_name || "Upload id #{id}"
end
|
#undefined_mime_type? ⇒ Boolean
418
419
420
|
# File 'app/models/upload.rb', line 418
def undefined_mime_type?
mime_type.blank? || mime_type == 'application/octet-stream'
end
|