Skip to content

Commit 8b3782c

Browse files
committed
Don't load ActiveStorage::Blob when validating the service
For tasks like `assets:precompile` that don't need ActiveStorage, we should not be loading the entire Active Storage behavior just to be able to validate the service configuration since Active Storage might be miss configured for that task.
1 parent 1914a74 commit 8b3782c

File tree

7 files changed

+82
-33
lines changed

7 files changed

+82
-33
lines changed

activestorage/app/models/active_storage/blob.rb

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -151,22 +151,6 @@ def compose(blobs, key: nil, filename:, content_type: nil, metadata: nil)
151151
combined_blob.save!
152152
end
153153
end
154-
155-
def validate_service_configuration(service_name, model_class, association_name) # :nodoc:
156-
if service_name
157-
services.fetch(service_name) do
158-
raise ArgumentError, "Cannot configure service #{service_name.inspect} for #{model_class}##{association_name}"
159-
end
160-
else
161-
validate_global_service_configuration
162-
end
163-
end
164-
165-
def validate_global_service_configuration # :nodoc:
166-
if connected? && table_exists? && Rails.configuration.active_storage.service.nil?
167-
raise RuntimeError, "Missing Active Storage service name. Specify Active Storage service name for config.active_storage.service in config/environments/#{Rails.env}.rb"
168-
end
169-
end
170154
end
171155

172156
include Analyzable

activestorage/lib/active_storage/attached/changes/create_one.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def attachment_service_name
121121
service_name = record.attachment_reflections[name].options[:service_name]
122122
if service_name.is_a?(Proc)
123123
service_name = service_name.call(record)
124-
ActiveStorage::Blob.validate_service_configuration(service_name, record.class, name)
124+
Attached::Model.validate_service_configuration(service_name, record.class, name)
125125
end
126126
service_name
127127
end

activestorage/lib/active_storage/attached/model.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ module Attached::Model
106106
# <tt>active_storage_attachments.record_type</tt> polymorphic type column of
107107
# the corresponding rows.
108108
def has_one_attached(name, dependent: :purge_later, service: nil, strict_loading: false)
109-
ActiveStorage::Blob.validate_service_configuration(service, self, name) unless service.is_a?(Proc)
109+
Attached::Model.validate_service_configuration(service, self, name) unless service.is_a?(Proc)
110110

111111
generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
112112
# frozen_string_literal: true
@@ -208,7 +208,7 @@ def #{name}=(attachable)
208208
# <tt>active_storage_attachments.record_type</tt> polymorphic type column of
209209
# the corresponding rows.
210210
def has_many_attached(name, dependent: :purge_later, service: nil, strict_loading: false)
211-
ActiveStorage::Blob.validate_service_configuration(service, self, name) unless service.is_a?(Proc)
211+
Attached::Model.validate_service_configuration(service, self, name) unless service.is_a?(Proc)
212212

213213
generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
214214
# frozen_string_literal: true
@@ -259,6 +259,25 @@ def #{name}=(attachables)
259259
end
260260
end
261261

262+
class << self
263+
def validate_service_configuration(service_name, model_class, association_name) # :nodoc:
264+
if service_name
265+
ActiveStorage::Blob.services.fetch(service_name) do
266+
raise ArgumentError, "Cannot configure service #{service_name.inspect} for #{model_class}##{association_name}"
267+
end
268+
else
269+
validate_global_service_configuration(model_class)
270+
end
271+
end
272+
273+
private
274+
def validate_global_service_configuration(model_class)
275+
if model_class.connected? && ActiveStorage::Blob.table_exists? && Rails.configuration.active_storage.service.nil?
276+
raise RuntimeError, "Missing Active Storage service name. Specify Active Storage service name for config.active_storage.service in config/environments/#{Rails.env}.rb"
277+
end
278+
end
279+
end
280+
262281
def attachment_changes # :nodoc:
263282
@attachment_changes ||= {}
264283
end
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# frozen_string_literal: true
2+
3+
require "isolation/abstract_unit"
4+
require "rack/test"
5+
require "rails-dom-testing"
6+
7+
module ApplicationTests
8+
class ValidatingServiceTest < ActiveSupport::TestCase
9+
include ActiveSupport::Testing::Isolation
10+
include Rack::Test::Methods
11+
include Rails::Dom::Testing::Assertions
12+
13+
self.file_fixture_path = "#{RAILS_FRAMEWORK_ROOT}/activestorage/test/fixtures/files"
14+
15+
def setup
16+
build_app
17+
end
18+
19+
def teardown
20+
teardown_app
21+
end
22+
23+
def test_boot_application_with_model_using_active_storage_should_not_load_active_storage_blob
24+
rails "active_storage:install"
25+
26+
rails "generate", "model", "user", "name:string", "avatar:attachment"
27+
rails "db:migrate"
28+
29+
app_file "config/routes.rb", <<~RUBY
30+
Rails.application.routes.draw do
31+
_ = User
32+
resources :users, only: [:show, :create]
33+
Rails.configuration.ok_to_proceed = true
34+
end
35+
RUBY
36+
37+
app_file "config/initializers/active_storage.rb", <<~RUBY
38+
Rails.configuration.ok_to_proceed = false
39+
40+
ActiveSupport.on_load(:active_storage_blob) do
41+
raise "ActiveStorage::Blob was loaded" unless Rails.configuration.ok_to_proceed
42+
end
43+
RUBY
44+
45+
assert_nothing_raised do
46+
with_env "RAILS_ENV" => "production" do
47+
rails ["environment", "--trace"]
48+
end
49+
end
50+
end
51+
end
52+
end

railties/test/application/assets_test.rb

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@ def precompile!(env = nil)
2626
end
2727
end
2828

29-
def with_env(env)
30-
env.each { |k, v| ENV[k.to_s] = v }
31-
yield
32-
ensure
33-
env.each_key { |k| ENV.delete k.to_s }
34-
end
35-
3629
def clean_assets!
3730
quietly do
3831
rails ["assets:clobber"]

railties/test/application/sprockets_assets_test.rb

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,6 @@ def run_app_update
5656
end
5757
end
5858

59-
def with_env(env)
60-
env.each { |k, v| ENV[k.to_s] = v }
61-
yield
62-
ensure
63-
env.each_key { |k| ENV.delete k.to_s }
64-
end
65-
6659
def clean_assets!
6760
quietly do
6861
rails ["assets:clobber"]

railties/test/isolation/abstract_unit.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,14 @@ class ActiveSupport::TestCase
595595
include TestHelpers::Reload
596596
include ActiveSupport::Testing::Stream
597597
include ActiveSupport::Testing::MethodCallAssertions
598+
599+
private
600+
def with_env(env)
601+
env.each { |k, v| ENV[k.to_s] = v }
602+
yield
603+
ensure
604+
env.each_key { |k| ENV.delete k.to_s }
605+
end
598606
end
599607

600608
# Create a scope and build a fixture rails app

0 commit comments

Comments
 (0)