-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add mongoid support for mount_uploadcare_file and mount_uploadcare_fi…
…le_group methods.
- Loading branch information
1 parent
eb27313
commit 5ab4236
Showing
9 changed files
with
400 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'mongoid' | ||
require 'active_support/concern' | ||
require 'uploadcare/rails/services/id_extractor' | ||
require 'uploadcare/rails/jobs/delete_file_job' | ||
require 'uploadcare/rails/jobs/store_file_job' | ||
require 'uploadcare/rails/objects/file' | ||
|
||
module Uploadcare | ||
module Rails | ||
module Mongoid | ||
# A module containing Mongoid extension. Allows using uploadcare file methods in Mongoid models | ||
module MountUploadcareFile | ||
extend ActiveSupport::Concern | ||
|
||
def build_uploadcare_file(attribute) | ||
cdn_url = read_attribute(attribute).to_s | ||
return if cdn_url.empty? | ||
|
||
uuid = IdExtractor.call(cdn_url) | ||
cache_key = File.build_cache_key(cdn_url) | ||
default_attributes = { cdn_url: cdn_url, uuid: uuid.presence } | ||
file_attributes = ::Rails.cache.read(cache_key).presence || default_attributes | ||
Uploadcare::Rails::File.new(file_attributes) | ||
end | ||
|
||
class_methods do | ||
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity | ||
def mount_uploadcare_file(attribute) | ||
define_method attribute do | ||
build_uploadcare_file(attribute) | ||
end | ||
|
||
define_method "uploadcare_store_#{attribute}!" do |store_job = StoreFileJob| | ||
file_uuid = public_send(attribute)&.uuid | ||
return unless file_uuid | ||
return store_job.perform_later(file_uuid) if Uploadcare::Rails.configuration.store_files_async | ||
|
||
Uploadcare::FileApi.store_file(file_uuid) | ||
end | ||
|
||
define_method "uploadcare_delete_#{attribute}!" do |delete_job = DeleteFileJob| | ||
file_uuid = public_send(attribute)&.uuid | ||
return unless file_uuid | ||
return delete_job.perform_later(file_uuid) if Uploadcare::Rails.configuration.delete_files_async | ||
|
||
Uploadcare::FileApi.delete_file(file_uuid) | ||
end | ||
|
||
unless Uploadcare::Rails.configuration.do_not_store | ||
set_callback(:save, :after, :"uploadcare_store_#{attribute}!", if: :"#{attribute}_changed?") | ||
end | ||
|
||
return unless Uploadcare::Rails.configuration.delete_files_after_destroy | ||
|
||
set_callback(:destroy, :after, :"uploadcare_delete_#{attribute}!") | ||
end | ||
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
Mongoid::Document.include Uploadcare::Rails::Mongoid::MountUploadcareFile |
61 changes: 61 additions & 0 deletions
61
lib/uploadcare/rails/mongoid/mount_uploadcare_file_group.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'mongoid' | ||
require 'active_support/concern' | ||
require 'uploadcare/rails/services/id_extractor' | ||
require 'uploadcare/rails/services/files_count_extractor' | ||
require 'uploadcare/rails/jobs/store_group_job' | ||
require 'uploadcare/rails/objects/group' | ||
|
||
module Uploadcare | ||
module Rails | ||
module Mongoid | ||
# A module containing Mongoid extension. Allows to use uploadcare group methods in Rails models | ||
module MountUploadcareFileGroup | ||
extend ActiveSupport::Concern | ||
|
||
GROUP_ID_REGEX = /\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b~\d+/.freeze | ||
|
||
def build_uploadcare_file_group(attribute) | ||
cdn_url = read_attribute(attribute).to_s | ||
return if cdn_url.empty? | ||
|
||
group_id = IdExtractor.call(cdn_url, GROUP_ID_REGEX).presence | ||
cache_key = Group.build_cache_key(cdn_url) | ||
files_count = FilesCountExtractor.call(group_id) | ||
default_attributes = { cdn_url: cdn_url, id: group_id, files_count: files_count } | ||
file_attributes = ::Rails.cache.read(cache_key).presence || default_attributes | ||
Uploadcare::Rails::Group.new(file_attributes) | ||
end | ||
|
||
class_methods do | ||
# rubocop:disable Metrics/MethodLength | ||
def mount_uploadcare_file_group(attribute) | ||
define_singleton_method "has_uploadcare_file_group_for_#{attribute}?" do | ||
true | ||
end | ||
|
||
define_method attribute do | ||
build_uploadcare_file_group attribute | ||
end | ||
|
||
define_method "uploadcare_store_#{attribute}!" do |store_job = StoreGroupJob| | ||
group_id = public_send(attribute)&.id | ||
return unless group_id | ||
return store_job.perform_later(group_id) if Uploadcare::Rails.configuration.store_files_async | ||
|
||
Uploadcare::GroupApi.store_group(group_id) | ||
end | ||
|
||
return if Uploadcare::Rails.configuration.do_not_store | ||
|
||
set_callback :save, :after, :"uploadcare_store_#{attribute}!" | ||
end | ||
# rubocop:enable Metrics/MethodLength | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
Mongoid::Document.include Uploadcare::Rails::Mongoid::MountUploadcareFileGroup |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
spec/uploadcare/rails/mongoid/mount_uploadcare_file_group_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
require 'uploadcare/rails/mongoid/mount_uploadcare_file_group' | ||
|
||
describe Uploadcare::Rails::Mongoid::MountUploadcareFileGroup do | ||
before do | ||
allow(Rails).to receive(:cache).and_return(double(read: nil, write: nil)) | ||
allow(Uploadcare::Rails).to receive(:configuration).and_return( | ||
OpenStruct.new( | ||
store_files_async: false, | ||
delete_files_async: false, | ||
do_not_store: false, | ||
delete_files_after_destroy: false, | ||
cache_files: false, | ||
cache_namespace: 'uploadcare' | ||
) | ||
) | ||
|
||
stub_const 'TestModel', Class.new | ||
TestModel.class_eval do | ||
include Mongoid::Document | ||
include Uploadcare::Rails::Mongoid::MountUploadcareFileGroup | ||
extend ActiveModel::Callbacks | ||
|
||
field :cdn_url, type: String | ||
|
||
define_model_callbacks :save, only: :after | ||
|
||
mount_uploadcare_file_group :cdn_url | ||
end | ||
end | ||
|
||
let(:cdn_url) { 'https://api.uploadcare.com/groups/e6c3fb25-0653-454c-9c8e-7e91902bb044~2/' } | ||
let(:model) { TestModel.new(cdn_url: cdn_url) } | ||
let(:files_count) { 2 } | ||
let(:file_attributes) { { cdn_url: cdn_url, id: group_id, files_count: files_count } } | ||
let(:group_id) { 'e6c3fb25-0653-454c-9c8e-7e91902bb044~2' } | ||
|
||
describe '#build_uploadcare_file_group' do | ||
let(:subject) { model.build_uploadcare_file_group(:cdn_url) } | ||
|
||
context 'when cdn_url is empty' do | ||
it 'returns nil' do | ||
model.cdn_url = '' | ||
expect(subject).to be_nil | ||
end | ||
end | ||
|
||
context 'when cdn_url is not empty' do | ||
it 'returns a new Uploadcare::Rails::Group object' do | ||
expect(subject).to be_a(Uploadcare::Rails::Group) | ||
end | ||
|
||
it 'sets the correct attributes on the Uploadcare::Rails::Group object' do | ||
expect(subject.cdn_url).to eq(cdn_url) | ||
expect(subject.id).to eq(group_id) | ||
expect(subject.files_count.to_i).to eq(files_count) | ||
end | ||
end | ||
end | ||
|
||
describe 'Singleton .has_uploadcare_file_group_for_cdn_url?' do | ||
it 'returns true' do | ||
expect(TestModel.has_uploadcare_file_group_for_cdn_url?).to be(true) | ||
end | ||
end | ||
|
||
describe '.mount_uploadcare_file_group' do | ||
let(:attribute) { :cdn_url } | ||
|
||
it 'defines a getter method for the specified attribute' do | ||
expect(model).to respond_to(attribute) | ||
end | ||
|
||
it 'defines a method to store the file group asynchronously' do | ||
expect(model).to respond_to("uploadcare_store_#{attribute}!") | ||
end | ||
|
||
context 'when the file group is present' do | ||
it 'stores the file group synchronously if not configured for async storage' do | ||
Uploadcare::Rails.configuration.store_files_async = false | ||
expect(Uploadcare::GroupApi).to receive(:store_group).with(group_id) | ||
model.send("uploadcare_store_#{attribute}!") | ||
end | ||
|
||
it 'performs the store job asynchronously if configured' do | ||
Uploadcare::Rails.configuration.store_files_async = true | ||
expect(Uploadcare::Rails::StoreGroupJob).to receive(:perform_later).with(group_id) | ||
model.send("uploadcare_store_#{attribute}!") | ||
end | ||
end | ||
|
||
context 'when do_not_store configuration is true' do | ||
it 'does not define the after_save callback' do | ||
Uploadcare::Rails.configuration.do_not_store = true | ||
expect(TestModel).not_to receive(:after_save) | ||
TestModel.mount_uploadcare_file_group(:attribute) | ||
end | ||
end | ||
|
||
context 'when do_not_store configuration is false' do | ||
it 'defines the after_save callback' do | ||
Uploadcare::Rails.configuration.do_not_store = false | ||
expect(TestModel).to receive(:set_callback).with(:save, :after, :uploadcare_store_cdn_url!) | ||
TestModel.mount_uploadcare_file_group(attribute) | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.