aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md17
-rw-r--r--lib/active_vault/attachment.rb27
-rw-r--r--lib/active_vault/attachments.rb30
-rw-r--r--lib/active_vault/migration.rb27
-rw-r--r--lib/active_vault/railtie.rb8
-rw-r--r--test/attachments_test.rb27
-rw-r--r--test/database/create_users_migration.rb7
-rw-r--r--test/database/setup.rb4
-rw-r--r--test/test_helper.rb10
9 files changed, 132 insertions, 25 deletions
diff --git a/README.md b/README.md
index 5160acda56..a72c79948f 100644
--- a/README.md
+++ b/README.md
@@ -6,26 +6,11 @@
```ruby
class Person < ApplicationRecord
- has_one :avatar
-end
-
-class Avatar < ApplicationRecord
- belongs_to :person
- belongs_to :image, class_name: 'ActiveVault::Blob'
-
- has_file :image
+ has_file :avatar
end
avatar.image.url(expires_in: 5.minutes)
-
-class ActiveVault::DownloadsController < ActionController::Base
- def show
- head :ok, ActiveVault::Blob.locate(params[:id]).download_headers
- end
-end
-
-
class AvatarsController < ApplicationController
def create
# @avatar = Avatar.create \
diff --git a/lib/active_vault/attachment.rb b/lib/active_vault/attachment.rb
new file mode 100644
index 0000000000..eb108e9cbb
--- /dev/null
+++ b/lib/active_vault/attachment.rb
@@ -0,0 +1,27 @@
+require "active_vault/blob"
+require "global_id"
+require "active_support/core_ext/module/delegation"
+
+# Schema: id, record_gid, blob_id, created_at
+class ActiveVault::Attachment < ActiveRecord::Base
+ self.table_name = "active_vault_attachments"
+
+ belongs_to :blob, class_name: "ActiveVault::Blob"
+
+ delegate_missing_to :blob
+
+ def record
+ @record ||= GlobalID::Locator.locate(record_gid)
+ end
+
+ def record=(record)
+ @record = record
+ self.record_gid = record&.to_gid
+ end
+
+ def purge
+ blob.purge
+ destroy
+ record.public_send "#{name}=", nil
+ end
+end
diff --git a/lib/active_vault/attachments.rb b/lib/active_vault/attachments.rb
new file mode 100644
index 0000000000..c66c142650
--- /dev/null
+++ b/lib/active_vault/attachments.rb
@@ -0,0 +1,30 @@
+require "active_vault/attachment"
+require "action_dispatch/http/upload"
+
+module ActiveVault::Attachments
+ def has_file(name)
+ define_method(name) do
+ (@active_vault_attachments ||= {})[name] ||=
+ ActiveVault::Attachment.find_by(record_gid: to_gid.to_s, name: name)&.tap { |a| a.record = self }
+ end
+
+ define_method(:"#{name}=") do |attachable|
+ case attachable
+ when ActiveVault::Blob
+ blob = attachable
+ when ActionDispatch::Http::UploadedFile
+ blob = ActiveVault::Blob.create_after_upload! \
+ io: attachable.open,
+ filename: attachable.original_filename,
+ content_type: attachable.content_type
+ when Hash
+ blob = ActiveVault::Blob.create_after_upload!(attachable)
+ when NilClass
+ blob = nil
+ end
+
+ (@active_vault_attachments ||= {})[name] = blob ?
+ ActiveVault::Attachment.create!(record_gid: to_gid.to_s, name: name, blob: blob)&.tap { |a| a.record = self } : nil
+ end
+ end
+end
diff --git a/lib/active_vault/migration.rb b/lib/active_vault/migration.rb
index b3c66428ce..985d26d1b9 100644
--- a/lib/active_vault/migration.rb
+++ b/lib/active_vault/migration.rb
@@ -1,15 +1,28 @@
-class ActiveVault::CreateBlobs < ActiveRecord::Migration[5.1]
+class ActiveVault::CreateTables < ActiveRecord::Migration[5.1]
def change
- t.string :key
- t.string :filename
- t.string :content_type
- t.text :metadata
create_table :active_vault_blobs do |t|
+ t.string :key
+ t.string :filename
+ t.string :content_type
+ t.text :metadata
t.integer :byte_size
- t.string :checksum
- t.time :created_at
+ t.string :checksum
+ t.time :created_at
t.index [ :key ], unique: true
end
+
+ create_table :active_vault_attachments do |t|
+ t.string :name
+ t.string :record_gid
+ t.integer :blob_id
+
+ t.time :created_at
+
+ t.index :record_gid
+ t.index :blob_id
+ t.index [ :record_gid, :name ]
+ t.index [ :record_gid, :blob_id ], unique: true
+ end
end
end
diff --git a/lib/active_vault/railtie.rb b/lib/active_vault/railtie.rb
index c254f4c77c..f1c5740aa5 100644
--- a/lib/active_vault/railtie.rb
+++ b/lib/active_vault/railtie.rb
@@ -15,5 +15,13 @@ module ActiveVault
end
end
end
+
+ initializer "action_file.attachments" do
+ require "active_vault/attachments"
+
+ ActiveSupport.on_load(:active_record) do
+ extend ActiveVault::Attachments
+ end
+ end
end
end
diff --git a/test/attachments_test.rb b/test/attachments_test.rb
new file mode 100644
index 0000000000..970804b68f
--- /dev/null
+++ b/test/attachments_test.rb
@@ -0,0 +1,27 @@
+require "test_helper"
+require "database/setup"
+require "active_vault/blob"
+
+# ActiveRecord::Base.logger = Logger.new(STDOUT)
+
+class User < ActiveRecord::Base
+ has_file :avatar
+end
+
+class ActiveVault::AttachmentsTest < ActiveSupport::TestCase
+ setup { @user = User.create!(name: "DHH") }
+
+ test "create attachment from existing blob" do
+ @user.avatar = create_blob filename: "funky.jpg"
+ assert_equal "funky.jpg", @user.avatar.filename.to_s
+ end
+
+ test "purge attached blob" do
+ @user.avatar = create_blob filename: "funky.jpg"
+ avatar_key = @user.avatar.key
+
+ @user.avatar.purge
+ assert_nil @user.avatar
+ assert_not ActiveVault::Blob.site.exist?(avatar_key)
+ end
+end
diff --git a/test/database/create_users_migration.rb b/test/database/create_users_migration.rb
new file mode 100644
index 0000000000..38dcdc129b
--- /dev/null
+++ b/test/database/create_users_migration.rb
@@ -0,0 +1,7 @@
+class ActiveVault::CreateUsers < ActiveRecord::Migration[5.1]
+ def change
+ create_table :users do |t|
+ t.string :name
+ end
+ end
+end
diff --git a/test/database/setup.rb b/test/database/setup.rb
index bc6e8b9ec1..7373d72237 100644
--- a/test/database/setup.rb
+++ b/test/database/setup.rb
@@ -1,4 +1,6 @@
require "active_vault/migration"
+require_relative "create_users_migration"
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
-ActiveVault::CreateBlobs.migrate(:up)
+ActiveVault::CreateTables.migrate(:up)
+ActiveVault::CreateUsers.migrate(:up)
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 96ef58b73f..29bd31e62f 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -17,4 +17,12 @@ class ActiveSupport::TestCase
def create_blob(data: "Hello world!", filename: "hello.txt", content_type: "text/plain")
ActiveVault::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type
end
-end \ No newline at end of file
+end
+
+
+require "active_vault/attachments"
+ActiveRecord::Base.send :extend, ActiveVault::Attachments
+
+require "global_id"
+GlobalID.app = "ActiveVaultExampleApp"
+ActiveRecord::Base.send :include, GlobalID::Identification