Skip to content

Commit

Permalink
Merge pull request #15 from robin850/documentation
Browse files Browse the repository at this point in the history
Add some documentation
  • Loading branch information
dhh committed Jul 8, 2017
2 parents 800e957 + 27f87b6 commit 97bd958
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 5 deletions.
26 changes: 24 additions & 2 deletions lib/active_storage/attached/macros.rb
@@ -1,7 +1,18 @@
module ActiveStorage::Attached::Macros
# Specifies the relation between a single attachment and the model.
#
# class User < ActiveRecord::Base
# 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.
#
# 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)
define_method(name) do
instance_variable_get("@active_storage_attached_#{name}") ||
instance_variable_get("@active_storage_attached_#{name}") ||
instance_variable_set("@active_storage_attached_#{name}", ActiveStorage::Attached::One.new(name, self))
end

Expand All @@ -10,9 +21,20 @@ def has_one_attached(name, dependent: :purge_later)
end
end

# Specifies the relation between multiple attachments and the model.
#
# class Gallery < ActiveRecord::Base
# 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.
#
# 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)
define_method(name) do
instance_variable_get("@active_storage_attached_#{name}") ||
instance_variable_get("@active_storage_attached_#{name}") ||
instance_variable_set("@active_storage_attached_#{name}", ActiveStorage::Attached::Many.new(name, self))
end

Expand Down
17 changes: 17 additions & 0 deletions lib/active_storage/attached/many.rb
@@ -1,27 +1,44 @@
# Representation of multiple attachments to a model.
class ActiveStorage::Attached::Many < ActiveStorage::Attached
delegate_missing_to :attachments

# Returns all the associated attachment records.
#
# You don't have to call this method to access the attachments' methods as
# they are all available at the model level.
def attachments
@attachments ||= ActiveStorage::Attachment.where(record_gid: record.to_gid.to_s, name: name)
end

# Associates one or several attachments with the current record, saving
# them to the database.
def attach(*attachables)
@attachments = attachments | Array(attachables).flatten.collect do |attachable|
ActiveStorage::Attachment.create!(record_gid: record.to_gid.to_s, name: name, blob: create_blob_from(attachable))
end
end

# Checks the presence of attachments.
#
# class Gallery < ActiveRecord::Base
# has_many_attached :photos
# end
#
# Gallery.new.photos.attached? # => false
def attached?
attachments.any?
end

# Directly purges each associated attachment (i.e. destroys the blobs and
# attachments and deletes the files on the service).
def purge
if attached?
attachments.each(&:purge)
@attachments = nil
end
end

# Purges each associated attachment through the queuing system.
def purge_later
if attached?
attachments.each(&:purge_later)
Expand Down
17 changes: 17 additions & 0 deletions lib/active_storage/attached/one.rb
@@ -1,25 +1,42 @@
# Representation of a single attachment to a model.
class ActiveStorage::Attached::One < ActiveStorage::Attached
delegate_missing_to :attachment

# Returns the associated attachment record.
#
# You don't have to call this method to access the attachment's methods as
# they are all available at the model level.
def attachment
@attachment ||= ActiveStorage::Attachment.find_by(record_gid: record.to_gid.to_s, name: name)
end

# Associates a given attachment with the current record, saving it to the
# database.
def attach(attachable)
@attachment = ActiveStorage::Attachment.create!(record_gid: record.to_gid.to_s, name: name, blob: create_blob_from(attachable))
end

# Checks the presence of the attachment.
#
# class User < ActiveRecord::Base
# has_one_attached :avatar
# end
#
# User.new.avatar.attached? # => false
def attached?
attachment.present?
end

# Directly purges the attachment (i.e. destroys the blob and
# attachment and deletes the file on the service).
def purge
if attached?
attachment.purge
@attachment = nil
end
end

# Purges the attachment through the queuing system.
def purge_later
if attached?
attachment.purge_later
Expand Down
12 changes: 11 additions & 1 deletion lib/active_storage/disk_controller.rb
Expand Up @@ -4,11 +4,21 @@

require "active_support/core_ext/object/inclusion"

# This controller is a wrapper around local file downloading. It allows you to
# make abstraction of the URL generation logic and to serve files with expiry
# if you are using the +Disk+ service.
#
# By default, mounting the Active Storage engine inside your application will
# define a +/rails/blobs/:encoded_key+ route that will reference this controller's
# +show+ action and will be used to serve local files.
#
# A URL for an attachment can be generated through its +#url+ method, that
# will use the aforementioned route.
class ActiveStorage::DiskController < ActionController::Base
def show
if key = decode_verified_key
blob = ActiveStorage::Blob.find_by!(key: key)

if stale?(etag: blob.checksum)
send_data blob.download, filename: blob.filename, type: blob.content_type, disposition: disposition_param
end
Expand Down
2 changes: 1 addition & 1 deletion lib/active_storage/migration.rb
@@ -1,4 +1,4 @@
class ActiveStorageCreateTables < ActiveRecord::Migration[5.1]
class ActiveStorageCreateTables < ActiveRecord::Migration[5.1] # :nodoc:
def change
create_table :active_storage_blobs do |t|
t.string :key
Expand Down
31 changes: 30 additions & 1 deletion lib/active_storage/service.rb
@@ -1,4 +1,34 @@
# Abstract class serving as an interface for concrete services.
#
# The available services are:
#
# * +Disk+, to manage attachments saved directly on the hard drive.
# * +GCS+, to manage attachments through Google Cloud Storage.
# * +S3+, to manage attachments through Amazon S3.
# * +Mirror+, to be able to use several services to manage attachments.
#
# Inside a Rails application, you can set-up your services through the
# generated <tt>config/storage_services.yml</tt> file and reference one
# of the aforementioned constant under the +service+ key. For example:
#
# local:
# service: Disk
# root: <%= Rails.root.join("storage") %>
#
# You can checkout the service's constructor to know which keys are required.
#
# Then, in your application's configuration, you can specify the service to
# use like this:
#
# config.active_storage.service = :local
#
# If you are using Active Storage outside of a Ruby on Rails application, you
# can configure the service to use like this:
#
# ActiveStorage::Blob.service = ActiveStorage::Service.configure(
# :Disk,
# root: Pathname("/foo/bar/storage")
# )
class ActiveStorage::Service
class ActiveStorage::IntegrityError < StandardError; end

Expand All @@ -11,7 +41,6 @@ def self.configure(service, **options)
end
end


def upload(key, io, checksum: nil)
raise NotImplementedError
end
Expand Down

0 comments on commit 97bd958

Please sign in to comment.