Module: ActiveStorage::AwsRecord

Defined in:
lib/active_storage/aws_record.rb,
lib/active_storage/aws_record/blob.rb,
lib/active_storage/aws_record/item.rb,
lib/active_storage/aws_record/owner.rb,
lib/active_storage/aws_record/schema.rb,
lib/active_storage/aws_record/tables.rb,
lib/active_storage/aws_record/railtie.rb,
lib/active_storage/aws_record/version.rb,
lib/active_storage/aws_record/relation.rb,
lib/active_storage/aws_record/attachable.rb,
lib/active_storage/aws_record/attachment.rb,
lib/active_storage/aws_record/persistence.rb,
lib/active_storage/aws_record/transaction.rb,
lib/active_storage/aws_record/configuration.rb,
lib/active_storage/aws_record/variant_record.rb

Overview

Active Storage metadata backend backed by Amazon DynamoDB through the aws-record gem. Blob bytes flow through a normal Active Storage Service (Disk/S3); only blob/attachment/variant-record metadata lives in DynamoDB, in a single application-provided table (Single Table Design). See PLAN.md / README.md for the full design.

Defined Under Namespace

Modules: Attachable, Item, Owner, Persistence, Tables Classes: Attachment, Blob, Configuration, ConfigurationError, Railtie, Relation, Schema, Transaction, TransactionTooLarge, VariantRecord

Constant Summary collapse

VERSION =
'0.1.0'

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.configConfiguration (readonly)

Returns the memoized gem configuration.

Returns:



42
43
44
# File 'lib/active_storage/aws_record.rb', line 42

def config
  @config
end

.schemaSchema? (readonly)

Returns the resolved table layout (set by install!).

Returns:



45
46
47
# File 'lib/active_storage/aws_record.rb', line 45

def schema
  @schema
end

Class Method Details

.configure {|@config| ... } ⇒ Object

Yields #config for block-style configuration.

Yields:



48
49
50
# File 'lib/active_storage/aws_record.rb', line 48

def configure
  yield @config
end

.dynamodb_clientAws::DynamoDB::Client

The shared Aws::DynamoDB::Client every model uses. Built lazily but mutex-guarded so concurrent fibers cannot race two clients into existence.

Returns:

  • (Aws::DynamoDB::Client)


56
57
58
59
60
# File 'lib/active_storage/aws_record.rb', line 56

def dynamodb_client
  @client_mutex.synchronize do
    @dynamodb_client ||= @config.client || Aws::DynamoDB::Client.new(@config.client_options)
  end
end

.dynamodb_client=(client) ⇒ Object

Inject a client (tests / Railtie) and rewire the models to it.



63
64
65
66
67
68
69
# File 'lib/active_storage/aws_record.rb', line 63

def dynamodb_client=(client)
  @client_mutex.synchronize { @dynamodb_client = client }
  [Blob, Attachment, VariantRecord].each do |model|
    model.configure_client(client: client) if model.respond_to?(:configure_client)
  end
  client
end

.install!Object

Discover the table layout, declare the key attributes on the three models (now that their DB names are known), point them at the shared client, and set the table name. Idempotent; safe to call at every boot.



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/active_storage/aws_record.rb', line 101

def install!
  client = dynamodb_client
  Tables.ensure! if @config.manage_table
  @client_mutex.synchronize { @schema ||= Schema.discover(client, @config) }

  [Blob, Attachment, VariantRecord].each do |model|
    model.set_table_name(@config.table_name)
    define_key_attributes!(model)
    model.configure_client(client: client)
  end
end

.install_attachments!Object

Declare has_one_attached on the gem’s owner entities. Must run after Active Storage class indirection so the generic (non-AR) builder is used. Idempotent.



116
117
118
119
120
121
122
123
# File 'lib/active_storage/aws_record.rb', line 116

def install_attachments!
  unless Blob.respond_to?(:reflect_on_attachment) && Blob.reflect_on_attachment(:preview_image)
    Blob.has_one_attached :preview_image
  end
  unless VariantRecord.respond_to?(:reflect_on_attachment) && VariantRecord.reflect_on_attachment(:image)
    VariantRecord.has_one_attached :image
  end
end

.key(*parts) ⇒ String

Build a #-separated composite key, validating every segment is present (a blank segment would silently corrupt the key space). This is the gem’s lightweight stand-in for an app-specific compose_key.

Parameters:

  • parts (Array<#to_s>)

Returns:

  • (String)


85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/active_storage/aws_record.rb', line 85

def key(*parts)
  separator = @config.separator
  parts.each do |part|
    raise ArgumentError, "key segment cannot be blank (parts: #{parts.inspect})" if part.nil? || part.to_s.empty?

    if part.to_s.include?(separator)
      raise ArgumentError, "key segment #{part.inspect} may not contain the separator #{separator.inspect} " \
        "(parts: #{parts.inspect})"
    end
  end
  parts.join(separator)
end

.reset!Object

Drop the memoized client/schema (tests, and the Railtie before re-boot).



72
73
74
75
76
77
# File 'lib/active_storage/aws_record.rb', line 72

def reset!
  @client_mutex.synchronize do
    @dynamodb_client = nil
    @schema = nil
  end
end