Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Padrino::Mounter support the Rack application #1787

Merged
merged 1 commit into from Oct 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
77 changes: 70 additions & 7 deletions padrino-core/lib/padrino-core/mounter.rb
@@ -1,3 +1,5 @@
require 'delegate'

module Padrino
##
# Represents a particular mounted Padrino application.
Expand All @@ -12,6 +14,55 @@ class Mounter
class MounterException < RuntimeError
end

class ApplicationWrapper < SimpleDelegator
attr_accessor :uri_root
attr_writer :public_folder

def initialize(app, options = {})
@options = options
super(app)
end

def dependencies
@__dependencies ||= Dir["#{root}/**/*.rb"]
end

def prerequisite
@__prerequisite ||= []
end

def app_file
return @__app_file if @__app_file
obj = __getobj__
@__app_file = obj.respond_to?(:app_file) ? obj.app_file : @options[:app_file]
end

def root
return @__root if @__root
obj = __getobj__
@__root = obj.respond_to?(:root) ? obj.root : File.expand_path("#{app_file}/../")
end

def public_folder
return @public_folder if @public_folder
obj = __getobj__
@public_folder = obj.respond_to?(:public_folder) ? obj.public_folder : ""
end

def app_name
@__app_name ||= @options[:app_name] || __getobj__.to_s.underscore.to_sym
end

def setup_application!
@configured ||=
begin
$LOAD_PATH.concat(prerequisite)
Padrino.require_dependencies(dependencies, :force => true)
true
end
end
end

attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host, :cascade

##
Expand All @@ -32,12 +83,19 @@ def initialize(name, options={})
@app_file = options[:app_file] || locate_app_file
@app_obj = options[:app_obj] || app_constant || locate_app_object
ensure_app_file! || ensure_app_object!
@app_obj = ApplicationWrapper.new(@app_obj, options) unless padrino_application?
@app_root = options[:app_root] || (@app_obj.respond_to?(:root) && @app_obj.root || File.dirname(@app_file))
@uri_root = "/"
@cascade = options[:cascade] ? true == options[:cascade] ? DEFAULT_CASCADE.dup : Array(options[:cascade]) : []
Padrino::Reloader.exclude_constants << @app_class
end

def padrino_application?
@app_obj.ancestors.include?(Padrino::Application)
rescue NameError
false
end

##
# Registers the mounted application onto Padrino.
#
Expand Down Expand Up @@ -84,13 +142,18 @@ def host(mount_host)
def map_onto(router)
app_data = self
app_obj = @app_obj
app_obj.set :uri_root, app_data.uri_root
app_obj.set :app_name, app_data.app_obj.app_name.to_s
app_obj.set :app_file, app_data.app_file unless ::File.exist?(app_obj.app_file)
app_obj.set :root, app_data.app_root unless app_data.app_root.blank?
app_obj.set :public_folder, Padrino.root('public', app_data.uri_root) unless File.exist?(app_obj.public_folder)
app_obj.set :static, File.exist?(app_obj.public_folder) if app_obj.nil?
app_obj.set :cascade, app_data.cascade
if padrino_application?
app_obj.set :uri_root, app_data.uri_root
app_obj.set :app_name, app_data.app_obj.app_name.to_s
app_obj.set :app_file, app_data.app_file unless ::File.exist?(app_obj.app_file)
app_obj.set :root, app_data.app_root unless app_data.app_root.blank?
app_obj.set :public_folder, Padrino.root('public', app_data.uri_root) unless File.exist?(app_obj.public_folder)
app_obj.set :static, File.exist?(app_obj.public_folder) if app_obj.nil?
app_obj.set :cascade, app_data.cascade
else
app_obj.uri_root = app_data.uri_root
app_obj.public_folder = Padrino.root('public', app_data.uri_root) unless ::File.exist?(app_obj.public_folder)
end
app_obj.setup_application! # Initializes the app here with above settings.
router.map(:to => app_obj, :path => app_data.uri_root, :host => app_data.app_host)
end
Expand Down
7 changes: 7 additions & 0 deletions padrino-core/test/fixtures/apps/demo_project/api/app.rb
@@ -0,0 +1,7 @@
module DemoProject
class API
def self.call(_)
[200, {}, ["api app"]]
end
end
end
@@ -0,0 +1,3 @@
module DemoProject
APILib = Class.new
end
7 changes: 7 additions & 0 deletions padrino-core/test/fixtures/apps/demo_project/app.rb
@@ -0,0 +1,7 @@
module DemoProject
class App < Padrino::Application
get :index do
"padrino app"
end
end
end
15 changes: 15 additions & 0 deletions padrino-core/test/fixtures/apps/rack_apps.rb
@@ -0,0 +1,15 @@

class RackApp
def self.call(_)
[200, {}, ["hello rack app"]]
end
end

RackApp2 = lambda{|_| [200, {}, ["hello rack app2"]] }

class SinatraApp < Sinatra::Base
set :public_folder, File.dirname(__FILE__)
get "/" do
"hello sinatra app"
end
end
1 change: 1 addition & 0 deletions padrino-core/test/fixtures/apps/static.html
@@ -0,0 +1 @@
hello static file
32 changes: 32 additions & 0 deletions padrino-core/test/test_mounter.rb
Expand Up @@ -253,5 +253,37 @@ def spec.full_gem_path
assert_equal AppGem::App, mounter.app_obj
assert_equal Padrino.root('public'), mounter.app_obj.public_folder
end

it 'should support the Rack Application' do
path = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/rack_apps')
require path
Padrino.mount('rack_app', :app_class => 'RackApp', :app_file => path).to('/rack_app')
Padrino.mount('rack_app2', :app_class => 'RackApp2', :app_file => path).to('/rack_app2')
Padrino.mount('sinatra_app', :app_class => 'SinatraApp', :app_file => path).to('/sinatra_app')
app = Padrino.application
res = Rack::MockRequest.new(app).get("/rack_app")
assert_equal "hello rack app", res.body
res = Rack::MockRequest.new(app).get("/rack_app2")
assert_equal "hello rack app2", res.body
res = Rack::MockRequest.new(app).get("/sinatra_app")
assert_equal "hello sinatra app", res.body
res = Rack::MockRequest.new(app).get("/sinatra_app/static.html")
assert_equal "hello static file\n", res.body
end

it 'should support the Rack Application inside padrino project' do
path = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/demo_project/app')
api_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/demo_project/api/app')
require path
require api_path
Padrino.mount('api_app', :app_class => 'DemoProject::API', :app_file => api_path).to('/api')
Padrino.mount('main_app', :app_class => 'DemoProject::App').to('/')
app = Padrino.application
res = Rack::MockRequest.new(app).get("/")
assert_equal "padrino app", res.body
res = Rack::MockRequest.new(app).get("/api/hey")
assert_equal "api app", res.body
assert defined?(DemoProject::APILib)
end
end
end