Skip to content

Commit 146f89a

Browse files
authored
Merge pull request #168 from basecamp/flavorjones/167-exception-wrapper
`TenantSelector` middleware no longer directly renders a 404
2 parents 4d7f236 + 73bcf3e commit 146f89a

File tree

7 files changed

+18
-14
lines changed

7 files changed

+18
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Added
66

77
- `#inspect` on instances of tenanted models includes the tenant. #155, #161 @miguelmarcondesf @flavorjones
8+
- `TenantSelector` middleware no longer directly renders a 404. Instead, it configures ActionDispatch::ShowExceptions middlware and raises an appropriate exception. #167 @flavorjones
89

910

1011
## 0.2.0 / 2025-09-04

Gemfile.lock

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ PATH
104104
specs:
105105
activerecord-tenanted (0.2.0)
106106
activerecord (>= 8.1.alpha)
107-
rack-contrib (>= 2.5.0)
108107
railties (>= 8.1.alpha)
109108
zeitwerk
110109

@@ -217,8 +216,6 @@ GEM
217216
raabro (1.4.0)
218217
racc (1.8.1)
219218
rack (3.2.1)
220-
rack-contrib (2.5.0)
221-
rack (< 4)
222219
rack-session (2.1.1)
223220
base64 (>= 0.1.0)
224221
rack (>= 3.0.0)

activerecord-tenanted.gemspec

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,5 @@ Gem::Specification.new do |spec|
2929
rails_requirement = ">= 8.1.alpha"
3030
spec.add_dependency "activerecord", rails_requirement
3131
spec.add_dependency "railties", rails_requirement
32-
33-
spec.add_dependency "rack-contrib", ">= 2.5.0"
3432
spec.add_dependency "zeitwerk"
3533
end

lib/active_record/tenanted/railtie.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ class Railtie < ::Rails::Railtie
137137
end
138138
end
139139

140+
initializer "active_record_tenanted.action_dispatch", before: "action_dispatch.configure" do
141+
config.action_dispatch.rescue_responses["ActiveRecord::Tenanted::TenantDoesNotExistError"] = :not_found
142+
end
143+
140144
config.after_initialize do
141145
if defined?(Rails::Console)
142146
require "rails/commands/console/irb_console"

lib/active_record/tenanted/tenant_selector.rb

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# frozen_string_literal: true
22

3-
require "rack/contrib"
4-
53
module ActiveRecord
64
module Tenanted
75
#
@@ -34,8 +32,7 @@ def call(env)
3432
elsif tenanted_class.tenant_exist?(tenant_name)
3533
tenanted_class.with_tenant(tenant_name) { @app.call(env) }
3634
else
37-
Rails.logger.info("ActiveRecord::Tenanted::TenantSelector: Tenant not found: #{tenant_name.inspect}")
38-
Rack::NotFound.new(Rails.root.join("public/404.html")).call(env)
35+
raise ActiveRecord::Tenanted::TenantDoesNotExistError, "Tenant not found: #{tenant_name.inspect}"
3936
end
4037
end
4138

test/integration/test/testcase_test.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ class TestActionDispatchIntegrationTest < ActionDispatch::IntegrationTest
4141
end
4242
end
4343

44+
test "middleware: to a nonexistent tenant domain" do
45+
integration_session.host = "nonexistent-tenant.example.com"
46+
47+
get notes_url
48+
49+
assert_response :not_found
50+
end
51+
4452
test "middleware: creating a new tenant and requesting that domain" do
4553
note = ApplicationRecord.create_tenant("non-default-tenant") do
4654
Note.create!(title: "asdf", body: "Lorem ipsum.")

test/unit/tenant_selector_test.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,12 @@ def call(env)
4141
describe "when nonexistent tenant is resolved" do
4242
let(:resolver) { ->(request) { "does-not-exist" } }
4343

44-
test "returns 404" do
44+
test "raises TenantDoesNotExistError" do
45+
# Note that in production, this exception is handled by the ShowExceptions middleware, which
46+
# will raise a 404. That behavior is covered by integration tests.
4547
selector = ActiveRecord::Tenanted::TenantSelector.new(fake_app)
4648

47-
response = selector.call(fake_env)
48-
49-
assert_nil(fake_app.env, "Rack app should not have been invoked")
50-
assert_equal(404, response.first)
49+
assert_raises(ActiveRecord::Tenanted::TenantDoesNotExistError) { selector.call(fake_env) }
5150
end
5251
end
5352

0 commit comments

Comments
 (0)