Skip to content

Commit

Permalink
Merge pull request #83 from rage-rb/cascade
Browse files Browse the repository at this point in the history
Allow to have both Rails and Rage controllers in one application
  • Loading branch information
rsamoilov authored May 7, 2024
2 parents 012a51c + 830226c commit 4f3d70a
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 30 deletions.
44 changes: 21 additions & 23 deletions lib/rage-rb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,25 @@

module Rage
def self.application
Application.new(__router)
app = Application.new(__router)

config.middleware.middlewares.reverse.inject(app) do |next_in_chain, (middleware, args, block)|
# in Rails compatibility mode we first check if the middleware is a part of the Rails middleware stack;
# if it is - it is expected to be built using `ActionDispatch::MiddlewareStack::Middleware#build`
if Rage.config.internal.rails_mode
rails_middleware = Rails.application.config.middleware.middlewares.find { |m| m.name == middleware.name }
end

if rails_middleware
rails_middleware.build(next_in_chain)
else
middleware.new(next_in_chain, *args, &block)
end
end
end

def self.multi_application
Rage::Router::Util::Cascade.new(application, Rails.application)
end

def self.routes
Expand Down Expand Up @@ -43,28 +61,8 @@ def self.logger
@logger ||= config.logger
end

def self.load_middlewares(rack_builder)
config.middleware.middlewares.each do |middleware, args, block|
# in Rails compatibility mode we first check if the middleware is a part of the Rails middleware stack;
# if it is - it is expected to be built using `ActionDispatch::MiddlewareStack::Middleware#build`, but Rack
# expects the middleware to respond to `#new`, so we wrap the middleware into a helper module
if Rage.config.internal.rails_mode
rails_middleware = Rails.application.config.middleware.middlewares.find { |m| m.name == middleware.name }
if rails_middleware
wrapper = Module.new do
extend self
attr_accessor :middleware
def new(app, *, &)
middleware.build(app)
end
end
wrapper.middleware = rails_middleware
middleware = wrapper
end
end

rack_builder.use(middleware, *args, &block)
end
def self.load_middlewares(_)
puts "`Rage.load_middlewares` is deprecated and has been merged into `Rage.application`. Please remove this call."
end

def self.code_loader
Expand Down
14 changes: 10 additions & 4 deletions lib/rage/router/backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,18 @@ def on(method, path, handler, constraints: {}, defaults: nil)
raise "Invalid route handler format, expected to match the 'controller#action' pattern" unless handler =~ STRING_HANDLER_REGEXP

controller, action = Rage::Router::Util.path_to_class($1), $2
run_action_method_name = controller.__register_action(action.to_sym)

meta[:controller] = $1
meta[:action] = $2
if controller.ancestors.include?(RageController::API)
run_action_method_name = controller.__register_action(action.to_sym)

handler = eval("->(env, params) { #{controller}.new(env, params).#{run_action_method_name} }")
meta[:controller] = $1
meta[:action] = $2

handler = eval("->(env, params) { #{controller}.new(env, params).#{run_action_method_name} }")
else
# this is a Rails controller; notify `Rage::Router::Util::Cascade` to forward the request to Rails
handler = ->(_, _) { [404, { "X-Cascade" => "pass" }, []] }
end
else
raise "Non-string route handler should respond to `call`" unless handler.respond_to?(:call)
# while regular handlers are expected to be called with the `env` and `params` objects,
Expand Down
15 changes: 15 additions & 0 deletions lib/rage/router/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,19 @@ def path_to_name(str)
end
end
end

# @private
class Cascade
def initialize(rage_app, rails_app)
@rage_app = rage_app
@rails_app = rails_app
end

def call(env)
result = @rage_app.call(env)
return result if result[0] == :__http_defer__ || result[1]["X-Cascade".freeze] != "pass".freeze

@rails_app.call(env)
end
end
end
1 change: 0 additions & 1 deletion lib/rage/templates/config.ru
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
require_relative "config/application"

run Rage.application
Rage.load_middlewares(self)
1 change: 0 additions & 1 deletion spec/integration/test_app/config.ru
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
require_relative "config/application"

run Rage.application
Rage.load_middlewares(self)
1 change: 0 additions & 1 deletion spec/rspec/config.ru
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
run Rage.application
Rage.load_middlewares(self)

0 comments on commit 4f3d70a

Please sign in to comment.