lib/active_storage/attached/model.rb in activestorage-6.0.6.1 vs lib/active_storage/attached/model.rb in activestorage-6.1.0.rc1
- old
+ new
@@ -1,16 +1,18 @@
# frozen_string_literal: true
+require "active_support/core_ext/object/try"
+
module ActiveStorage
# Provides the class-level DSL for declaring an Active Record model's attachments.
module Attached::Model
extend ActiveSupport::Concern
class_methods do
# Specifies the relation between a single attachment and the model.
#
- # class User < ActiveRecord::Base
+ # class User < ApplicationRecord
# has_one_attached :avatar
# end
#
# There is no column defined on the model side, Active Storage takes
# care of the mapping between your records and the attachment.
@@ -28,12 +30,23 @@
# The system has been designed to having you go through the ActiveStorage::Attached::One
# proxy that provides the dynamic proxy to the associations and factory methods, like +attach+.
#
# If the +:dependent+ option isn't set, the attachment will be purged
# (i.e. destroyed) whenever the record is destroyed.
- def has_one_attached(name, dependent: :purge_later)
+ #
+ # If you need the attachment to use a service which differs from the globally configured one,
+ # pass the +:service+ option. For instance:
+ #
+ # class User < ActiveRecord::Base
+ # has_one_attached :avatar, service: :s3
+ # end
+ #
+ def has_one_attached(name, dependent: :purge_later, service: nil)
+ validate_service_configuration(name, service)
+
generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
+ # frozen_string_literal: true
def #{name}
@active_storage_attached ||= {}
@active_storage_attached[:#{name}] ||= ActiveStorage::Attached::One.new("#{name}", self)
end
@@ -54,20 +67,23 @@
after_save { attachment_changes[name.to_s]&.save }
after_commit(on: %i[ create update ]) { attachment_changes.delete(name.to_s).try(:upload) }
- ActiveRecord::Reflection.add_attachment_reflection(
- self,
+ reflection = ActiveRecord::Reflection.create(
+ :has_one_attached,
name,
- ActiveRecord::Reflection.create(:has_one_attached, name, nil, { dependent: dependent }, self)
+ nil,
+ { dependent: dependent, service_name: service },
+ self
)
+ ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
end
# Specifies the relation between multiple attachments and the model.
#
- # class Gallery < ActiveRecord::Base
+ # class Gallery < ApplicationRecord
# has_many_attached :photos
# end
#
# There are no columns defined on the model side, Active Storage takes
# care of the mapping between your records and the attachments.
@@ -85,12 +101,23 @@
# The system has been designed to having you go through the ActiveStorage::Attached::Many
# proxy that provides the dynamic proxy to the associations and factory methods, like +#attach+.
#
# If the +:dependent+ option isn't set, all the attachments will be purged
# (i.e. destroyed) whenever the record is destroyed.
- def has_many_attached(name, dependent: :purge_later)
+ #
+ # If you need the attachment to use a service which differs from the globally configured one,
+ # pass the +:service+ option. For instance:
+ #
+ # class Gallery < ActiveRecord::Base
+ # has_many_attached :photos, service: :s3
+ # end
+ #
+ def has_many_attached(name, dependent: :purge_later, service: nil)
+ validate_service_configuration(name, service)
+
generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
+ # frozen_string_literal: true
def #{name}
@active_storage_attached ||= {}
@active_storage_attached[:#{name}] ||= ActiveStorage::Attached::Many.new("#{name}", self)
end
@@ -128,15 +155,27 @@
after_save { attachment_changes[name.to_s]&.save }
after_commit(on: %i[ create update ]) { attachment_changes.delete(name.to_s).try(:upload) }
- ActiveRecord::Reflection.add_attachment_reflection(
- self,
+ reflection = ActiveRecord::Reflection.create(
+ :has_many_attached,
name,
- ActiveRecord::Reflection.create(:has_many_attached, name, nil, { dependent: dependent }, self)
+ nil,
+ { dependent: dependent, service_name: service },
+ self
)
+ ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
end
+
+ private
+ def validate_service_configuration(association_name, service)
+ if service.present?
+ ActiveStorage::Blob.services.fetch(service) do
+ raise ArgumentError, "Cannot configure service :#{service} for #{name}##{association_name}"
+ end
+ end
+ end
end
def attachment_changes #:nodoc:
@attachment_changes ||= {}
end