Module: Shrine::Plugins::KithePersistedDerivatives::AttacherMethods
- Defined in:
- lib/shrine/plugins/kithe_persisted_derivatives.rb
Instance Method Summary collapse
-
#add_persisted_derivatives(local_files, **options) ⇒ Object
Like the shrine ‘add_derivatives` method, but also persists the derivatives (saves to db), in a realiably concurrency-safe way.
-
#create_persisted_derivatives(*args, storage: nil, allow_other_changes: false, **options) ⇒ Object
Like the shrine ‘create_derivatives` method, but persists the created derivatives to the database in a concurrency-safe way.
-
#remove_persisted_derivatives(*paths, **options) ⇒ Object
Kind of like built-in Shrine #remove_derivatives, but also takes care of persisting AND deleting the removed derivative file from storage – all in concurrency-safe way, including not making sure to overwrite any unrelated derivatives someone else was adding.
Instance Method Details
#add_persisted_derivatives(local_files, **options) ⇒ Object
Like the shrine ‘add_derivatives` method, but also persists the derivatives (saves to db), in a realiably concurrency-safe way.
For ruby 3 compatibility, make sure you supply local_files as a hash literal with curly braces:
attacher.add_persisted_derivatives({ derivative_name1: io_obj1, deriv2: io2 })
Generally can take any options that shrine ‘add_derivatives` can take, including custom `storage` or `metadata` arguments.
Like shrine add_derivatives, it will assume the files passed in are temporary, and delete them for you. If you want to disable this behavior:
attacher.add_persisted_derivatives({key: io}, delete: false)
In some cases the derivatives can’t be persisted because the underlying database has changed such that they would not be applicable. In those cases ‘false` will be return value, otherwise returns the new derivatives just as shrine `add_derivatives`
Because the concurrent-safe persistence method will save the associated model – and save without ActiveRecord validation – it is not safe to add_persisted_derivatives on a model with other unsaved changes. The method will by default refuse to do so, throwing a TypeError. If you’d like to force it, pass ‘allow_other_changes: true` as an argument.
Also takes care of deleting any replaced derivative files, that are no longer referenced by the model. Shrine by default does not do this: github.com/shrinerb/shrine/issues/468
All deletions are inline. In general this could be a fairly expensive operation, it can be wise to do it in a bg job.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/shrine/plugins/kithe_persisted_derivatives.rb', line 59 def add_persisted_derivatives(local_files, **) other_changes_allowed = !!.delete(:allow_other_changes) if record && !other_changes_allowed && record.changed? raise TypeError.new("Can't safely add_persisted_derivatives on model with unsaved changes. Pass `allow_other_changes: true` to force.") end existing_derivative_files = nil # upload to storage new_derivatives = upload_derivatives(local_files, **) begin atomic_persist do |reloaded_attacher| # record so we can delete any replaced ones... existing_derivative_files = map_derivative(reloaded_attacher.derivatives).collect { |path, file| file } # make sure we don't override derivatives created in other jobs, by # first using the current up-to-date derivatives from db, # then merging our changes in on top. set_derivatives(reloaded_attacher.derivatives) merge_derivatives(new_derivatives) end rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound => e # underlying file has changed or model has been deleted, inappropriate # to add the derivatives, we can just silently drop them, but clean # up after ourselves. delete_derivatives(local_files) unless [:delete] == false delete_derivatives(new_derivatives) return false rescue StandardError => e # unexpected error, clean up our files and re-raise delete_derivatives(local_files) unless [:delete] == false delete_derivatives(new_derivatives) raise e end # Take care of deleting from storage any derivatives that were replaced. current_derivative_files = map_derivative(derivatives).collect { |path, file| file } replaced_files = existing_derivative_files - current_derivative_files delete_derivatives(replaced_files) new_derivatives end |
#create_persisted_derivatives(*args, storage: nil, allow_other_changes: false, **options) ⇒ Object
Like the shrine ‘create_derivatives` method, but persists the created derivatives to the database in a concurrency-safe way.
Can take all options that shrine ‘create_derivatives` can take, including custom processors, custom storage key, and arbitrary custom processor arguments.
asset.file_attacher.create_persisted_derivatives
asset.file_attacher.create_persisted_derivatives(storage: :custom_key)
asset.file_attacher.create_persisted_derivatives(:kithe_derivatives)
asset.file_attacher.create_persisted_derivatives(:kithe_derivatives, some_arg: "value")
asset.file_attacher.create_persisted_derivatives(:kithe_derivatives, alternate_source_file)
Also has an ‘allow_other_changes` argument, see #add_persisted_derivatives.
117 118 119 120 121 122 |
# File 'lib/shrine/plugins/kithe_persisted_derivatives.rb', line 117 def create_persisted_derivatives(*args, storage: nil, allow_other_changes: false, **) return false unless file local_files = process_derivatives(*args, **) add_persisted_derivatives(local_files, storage: storage, allow_other_changes: allow_other_changes) end |
#remove_persisted_derivatives(*paths, **options) ⇒ Object
Kind of like built-in Shrine #remove_derivatives, but also takes care of persisting AND deleting the removed derivative file from storage – all in concurrency-safe way, including not making sure to overwrite any unrelated derivatives someone else was adding.
Can take the same sorts of path arguments as Shrine derivative #remove_derivatives
asset.file_attacher.remove_persisted_derivatives(:small_thumb)
asset.file_attacher.remove_persisted_derivatives(:small_thumb, :large_thumb)
asset.file_attacher.remove_persisted_derivatives(:small_thumb, :large_thumb, allow_other_changes: true)
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/shrine/plugins/kithe_persisted_derivatives.rb', line 134 def remove_persisted_derivatives(*paths, **) return if paths.empty? # Shrine does weird things if we pass in Strings, let's save ourselves # the terrible debugging on that mistake, and noramlize to symbols paths = paths.collect(&:to_sym) other_changes_allowed = !!.delete(:allow_other_changes) if record && !other_changes_allowed && record.changed? raise TypeError.new("Can't safely add_persisted_derivatives on model with unsaved changes. Pass `allow_other_changes: true` to force.") end removed_derivatives = nil atomic_persist do |reloaded_attacher| set_derivatives(reloaded_attacher.derivatives) removed_derivatives = remove_derivatives(*paths, delete: false) end if removed_derivatives map_derivative(removed_derivatives) do |_, derivative| derivative.delete if derivative end end removed_derivatives rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound # original was already deleted or changed, the derivatives wer'e trying to delete. # It should be fine to do nothing, the process that deleted or changed # the model should already have deleted all these derivatives. # But we'll return false as a signel. return false end |