mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Add attachments
This commit is contained in:
parent
97aa328bb1
commit
aaf8415188
9 changed files with 132 additions and 25 deletions
17
README.md
17
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 \
|
||||
|
|
27
lib/active_vault/attachment.rb
Normal file
27
lib/active_vault/attachment.rb
Normal file
|
@ -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
|
30
lib/active_vault/attachments.rb
Normal file
30
lib/active_vault/attachments.rb
Normal file
|
@ -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
|
|
@ -1,15 +1,28 @@
|
|||
class ActiveVault::CreateBlobs < ActiveRecord::Migration[5.1]
|
||||
class ActiveVault::CreateTables < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
create_table :active_vault_blobs do |t|
|
||||
t.string :key
|
||||
t.string :filename
|
||||
t.string :content_type
|
||||
t.text :metadata
|
||||
create_table :active_vault_blobs do |t|
|
||||
t.integer :byte_size
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
27
test/attachments_test.rb
Normal file
27
test/attachments_test.rb
Normal file
|
@ -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
|
7
test/database/create_users_migration.rb
Normal file
7
test/database/create_users_migration.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class ActiveVault::CreateUsers < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
create_table :users do |t|
|
||||
t.string :name
|
||||
end
|
||||
end
|
||||
end
|
|
@ -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)
|
||||
|
|
|
@ -18,3 +18,11 @@ class ActiveSupport::TestCase
|
|||
ActiveVault::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
require "active_vault/attachments"
|
||||
ActiveRecord::Base.send :extend, ActiveVault::Attachments
|
||||
|
||||
require "global_id"
|
||||
GlobalID.app = "ActiveVaultExampleApp"
|
||||
ActiveRecord::Base.send :include, GlobalID::Identification
|
||||
|
|
Loading…
Reference in a new issue