Skip to content

Commit

Permalink
Merge pull request #3037 from sferik/active_storage
Browse files Browse the repository at this point in the history
ActiveStorage integration
  • Loading branch information
mshibuya committed Jul 7, 2018
2 parents da0584a + beeb004 commit e1ec821
Show file tree
Hide file tree
Showing 16 changed files with 213 additions and 7 deletions.
2 changes: 1 addition & 1 deletion app/views/rails_admin/main/_form_file_upload.html.haml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- file = form.object.send(field.method_name).presence
- file = field.value

.toggle{style: ('display:none;' if file && field.delete_method && form.object.send(field.delete_method) == '1')}
- if value = field.pretty_value
Expand Down
2 changes: 1 addition & 1 deletion lib/rails_admin/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def default_search_operator=(operator)

# pool of all found model names from the whole application
def models_pool
excluded = (excluded_models.collect(&:to_s) + %w(RailsAdmin::History PaperTrail::Version PaperTrail::VersionAssociation))
excluded = (excluded_models.collect(&:to_s) + %w(RailsAdmin::History PaperTrail::Version PaperTrail::VersionAssociation ActiveStorage::Attachment ActiveStorage::Blob))

(viable_models - excluded).uniq.sort
end
Expand Down
1 change: 1 addition & 0 deletions lib/rails_admin/config/fields.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,5 @@ def self.register_factory(&block)
require 'rails_admin/config/fields/factories/dragonfly'
require 'rails_admin/config/fields/factories/carrierwave'
require 'rails_admin/config/fields/factories/refile'
require 'rails_admin/config/fields/factories/active_storage'
require 'rails_admin/config/fields/factories/association'
23 changes: 23 additions & 0 deletions lib/rails_admin/config/fields/factories/active_storage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'rails_admin/config/fields'
require 'rails_admin/config/fields/types'
require 'rails_admin/config/fields/types/file_upload'

RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
if defined?(::ActiveStorage) && properties.is_a?(RailsAdmin::Adapters::ActiveRecord::Association) && (match = /\A(.+)_attachment\Z/.match properties.name) && properties.klass.to_s == 'ActiveStorage::Attachment'
name = match[1]
field = RailsAdmin::Config::Fields::Types.load(:active_storage).new(parent, name, properties)
fields << field
associations = ["#{name}_attachment".to_sym, "#{name}_blob".to_sym]
children_fields = associations.map do |child_name|
next unless child_association = parent.abstract_model.associations.detect { |p| p.name.to_sym == child_name }
child_field = fields.detect { |f| f.name == child_name } || RailsAdmin::Config::Fields.default_factory.call(parent, child_association, fields)
child_field.hide unless field == child_field
child_field.filterable(false) unless field == child_field
child_field.name
end.flatten
field.children_fields(children_fields)
true
else
false
end
end
44 changes: 44 additions & 0 deletions lib/rails_admin/config/fields/types/active_storage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require 'rails_admin/config/fields/types/file_upload'

module RailsAdmin
module Config
module Fields
module Types
class ActiveStorage < RailsAdmin::Config::Fields::Types::FileUpload
RailsAdmin::Config::Fields::Types.register(self)

register_instance_option :thumb_method do
{resize: '100x100>'}
end

register_instance_option :delete_method do
"remove_#{name}" if bindings[:object].respond_to?("remove_#{name}")
end

register_instance_option :image? do
if value
value.filename.to_s.split('.').last =~ /jpg|jpeg|png|gif|svg/i
end
end

def resource_url(thumb = false)
return nil unless value
if thumb && value.variable?
variant = value.variant(thumb)
Rails.application.routes.url_helpers.rails_blob_representation_path(
variant.blob.signed_id, variant.variation.key, variant.blob.filename, only_path: true
)
else
Rails.application.routes.url_helpers.rails_blob_path(value, only_path: true)
end
end

def value
attachment = super
attachment if attachment && attachment.attached?
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rails_admin/config/fields/types/all.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'rails_admin/config/fields/types/active_record_enum'
require 'rails_admin/config/fields/types/active_storage'
require 'rails_admin/config/fields/types/belongs_to_association'
require 'rails_admin/config/fields/types/boolean'
require 'rails_admin/config/fields/types/bson_object_id'
Expand Down
9 changes: 7 additions & 2 deletions spec/controllers/rails_admin/main_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,9 @@ class TeamWithNumberedPlayers < Team
delete_method :delete_paperclip_asset
end
field :refile_asset if defined?(Refile)
field :active_storage_asset do
delete_method :remove_active_storage_asset
end if defined?(ActiveStorage)
end
controller.params = HashWithIndifferentAccess.new(
'field_test' => {
Expand All @@ -395,7 +398,8 @@ class TeamWithNumberedPlayers < Team
'paperclip_asset' => 'test',
'delete_paperclip_asset' => 'test',
'should_not_be_here' => 'test',
}.merge(defined?(Refile) ? {'refile_asset' => 'test', 'remove_refile_asset' => 'test'} : {}),
}.merge(defined?(Refile) ? {'refile_asset' => 'test', 'remove_refile_asset' => 'test'} : {}).
merge(defined?(ActiveStorage) ? {'active_storage_asset' => 'test', 'remove_active_storage_asset' => 'test'} : {}),
)

controller.send(:sanitize_params_for!, :create, RailsAdmin.config(FieldTest), controller.params['field_test'])
Expand All @@ -408,7 +412,8 @@ class TeamWithNumberedPlayers < Team
'retained_dragonfly_asset' => 'test',
'paperclip_asset' => 'test',
'delete_paperclip_asset' => 'test',
}.merge(defined?(Refile) ? {'refile_asset' => 'test', 'remove_refile_asset' => 'test'} : {}))
}.merge(defined?(Refile) ? {'refile_asset' => 'test', 'remove_refile_asset' => 'test'} : {}).
merge(defined?(ActiveStorage) ? {'active_storage_asset' => 'test', 'remove_active_storage_asset' => 'test'} : {}))
end

it 'allows for polymorphic associations parameters' do
Expand Down
4 changes: 2 additions & 2 deletions spec/dummy_app/Gemfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
source 'https://rubygems.org'

gem 'rails', '~> 5.0.0'
gem 'rails', '~> 5.0'
gem 'rack-cache', require: 'rack/cache'

group :active_record do
Expand All @@ -23,7 +23,7 @@ group :active_record do
end

group :mongoid do
gem 'mongoid', '~> 6.0.0.beta'
gem 'mongoid', '~> 6.0'
gem 'mongoid-paperclip', '>= 0.0.8', require: 'mongoid_paperclip'
gem 'carrierwave-mongoid', '>= 0.6.3', require: 'carrierwave/mongoid'
# gem 'refile-mongoid', '>= 0.0.1', platforms: [:ruby_21, :ruby_22]
Expand Down
4 changes: 4 additions & 0 deletions spec/dummy_app/app/active_record/field_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class FieldTest < ActiveRecord::Base

attachment :refile_asset if defined?(Refile)

has_one_attached :active_storage_asset if defined?(ActiveStorage)
attr_accessor :remove_active_storage_asset
after_save { active_storage_asset.purge if remove_active_storage_asset == '1' }

if ::Rails.version >= '4.1' # enum support was added in Rails 4.1
enum string_enum_field: {S: 's', M: 'm', L: 'l'}
enum integer_enum_field: [:small, :medium, :large]
Expand Down
3 changes: 3 additions & 0 deletions spec/dummy_app/config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
rescue LoadError # rubocop:disable HandleExceptions
end

require 'active_storage/engine' if Rails.version >= '5.2.0' && CI_ORM == :active_record

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups, CI_ORM)
Expand All @@ -25,5 +27,6 @@ class Application < Rails::Application
config.active_record.raise_in_transactional_callbacks = true if Rails::VERSION::MAJOR == 4 && Rails::VERSION::MINOR == 2 && CI_ORM == :active_record
config.active_record.time_zone_aware_types = [:datetime, :time] if Rails::VERSION::MAJOR >= 5 && CI_ORM == :active_record
config.active_record.sqlite3.represent_boolean_as_integer = true if CI_ORM == :active_record && config.active_record.sqlite3.respond_to?(:represent_boolean_as_integer=)
config.active_storage.service = :local if defined?(ActiveStorage)
end
end
3 changes: 3 additions & 0 deletions spec/dummy_app/config/storage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
local:
service: Disk
root: <%= Rails.root.join('public', 'system') %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < MigrationBase
def change
create_table :active_storage_blobs do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
if t.respond_to? :bigint
t.bigint :byte_size, null: false
else
t.integer :byte_size, null: false
end
t.string :checksum, null: false
t.datetime :created_at, null: false

t.index [:key], unique: true
end

create_table :active_storage_attachments do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false
t.references :blob, null: false

t.datetime :created_at, null: false

t.index [:record_type, :record_id, :name, :blob_id], name: "index_active_storage_attachments_uniqueness", unique: true
end
end
end
14 changes: 14 additions & 0 deletions spec/rails_admin/config/fields/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,20 @@ class CommentReversed < Tableless
end
end
end

if defined?(ActiveStorage)
context 'of a ActiveStorage installation' do
it 'is _attachment and _blob fields' do
expect(RailsAdmin.config(FieldTest).fields.detect { |f| f.name == :active_storage_asset }.children_fields).to match_array [:active_storage_asset_attachment, :active_storage_asset_blob]
end

it 'is hidden, not filterable' do
fields = RailsAdmin.config(FieldTest).fields.select { |f| [:active_storage_asset_attachment, :active_storage_asset_blob].include?(f.name) }
expect(fields).to all(be_hidden)
expect(fields).not_to include(be_filterable)
end
end
end
end

describe '#form_default_value' do
Expand Down
74 changes: 74 additions & 0 deletions spec/rails_admin/config/fields/types/active_storage_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require 'spec_helper'

describe RailsAdmin::Config::Fields::Types::ActiveStorage do
it_behaves_like 'a generic field type', :string_field, :active_storage

let(:record) { FactoryGirl.create :field_test }
let(:field) do
RailsAdmin.config('FieldTest').fields.detect do |f|
f.name == :active_storage_asset
end.with(object: record)
end

describe '#image?' do
context 'when attachment is an image' do
let(:record) { FactoryGirl.create :field_test, active_storage_asset: {io: StringIO.new('dummy'), filename: "test.jpg", content_type: "image/jpeg"} }

it 'returns true' do
expect(field.image?).to be_truthy
end
end

context 'when attachment is not an image' do
let(:record) { FactoryGirl.create :field_test, active_storage_asset: {io: StringIO.new('dummy'), filename: "test.txt", content_type: "text/plain"} }

it 'returns false' do
expect(field.image?).to be_falsy
end
end
end

describe '#resource_url' do
context 'when calling with thumb = false' do
let(:record) { FactoryGirl.create :field_test, active_storage_asset: {io: StringIO.new('dummy'), filename: "test.jpg", content_type: "image/jpeg"} }

it 'returns original url' do
expect(field.resource_url).not_to match(/representations/)
end
end

context 'when attachment is an image' do
let(:record) { FactoryGirl.create :field_test, active_storage_asset: {io: StringIO.new('dummy'), filename: "test.jpg", content_type: "image/jpeg"} }

it 'returns variant\'s url' do
expect(field.resource_url(true)).to match(/representations/)
end
end

context 'when attachment is not an image' do
let(:record) { FactoryGirl.create :field_test, active_storage_asset: {io: StringIO.new('dummy'), filename: "test.txt", content_type: "text/plain"} }

it 'returns original url' do
expect(field.resource_url(true)).not_to match(/representations/)
end
end
end

describe '#value' do
context 'when attachment exists' do
let(:record) { FactoryGirl.create :field_test, active_storage_asset: {io: StringIO.new('dummy'), filename: "test.jpg", content_type: "image/jpeg"} }

it 'returns attached object' do
expect(field.value).to be_a(ActiveStorage::Attached::One)
end
end

context 'when attachment does not exist' do
let(:record) { FactoryGirl.create :field_test }

it 'returns nil' do
expect(field.value).to be_nil
end
end
end
end if defined?(ActiveStorage)
4 changes: 4 additions & 0 deletions spec/rails_admin/config/fields/types/file_upload_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@
delete_method :delete_paperclip_asset
end
field :refile_asset
field :active_storage_asset do
delete_method :remove_active_storage_asset
end if defined?(ActiveStorage)
end
end
expect(RailsAdmin.config(FieldTest).field(:carrierwave_asset).allowed_methods.collect(&:to_s)).to eq %w(carrierwave_asset remove_carrierwave_asset carrierwave_asset_cache)
expect(RailsAdmin.config(FieldTest).field(:dragonfly_asset).allowed_methods.collect(&:to_s)).to eq %w(dragonfly_asset remove_dragonfly_asset retained_dragonfly_asset)
expect(RailsAdmin.config(FieldTest).field(:paperclip_asset).allowed_methods.collect(&:to_s)).to eq %w(paperclip_asset delete_paperclip_asset)
expect(RailsAdmin.config(FieldTest).field(:refile_asset).allowed_methods.collect(&:to_s)).to eq %w(refile_asset remove_refile_asset) if defined?(Refile)
expect(RailsAdmin.config(FieldTest).field(:active_storage_asset).allowed_methods.collect(&:to_s)).to eq %w(active_storage_asset remove_active_storage_asset) if defined?(ActiveStorage)
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
SimpleCov.start do
add_filter '/spec/'
add_filter '/vendor/bundle/'
minimum_coverage(91.21)
minimum_coverage(CI_ORM == :mongoid ? 91.08 : 91.21)
end

require File.expand_path('../dummy_app/config/environment', __FILE__)
Expand Down

0 comments on commit e1ec821

Please sign in to comment.