Skip to content

Commit

Permalink
Start Rails::Application object
Browse files Browse the repository at this point in the history
  • Loading branch information
Yehuda Katz + Carl Lerche committed Sep 26, 2009
1 parent 088ce29 commit 4129449
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 38 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -31,3 +31,4 @@ actionpack/bin
vendor/gems/
*/vendor/gems/
bin/
railties/tmp
2 changes: 2 additions & 0 deletions railties/lib/rails.rb
@@ -0,0 +1,2 @@
require "rails/application"
require "rails/initializer"
58 changes: 58 additions & 0 deletions railties/lib/rails/application.rb
@@ -0,0 +1,58 @@
require 'action_controller'

module Rails
class Application
# Loads a Rails application from a directory and returns a Rails
# Application object that responds to #call(env)
def self.load(path, options = {})
require "#{path}/config/environment"
new(path, options)
end

def initialize(path, options)
@path = path

ensure_tmp_dirs

if options[:config]
config = File.join(path, options[:config])
config = nil unless File.exist?(config)
end

@app = ::Rack::Builder.new {
use Rails::Rack::LogTailer unless options[:detach]
use Rails::Rack::Debugger if options[:debugger]
if options[:path]
base = options[:path]
ActionController::Base.relative_url_root = base
end

map base || "/" do
use Rails::Rack::Static

if config && config =~ /\.ru$/
instance_eval(File.read(config), config)
elsif config
require config
run Object.const_get(File.basename(config, '.rb').capitalize)
else
run ActionController::Dispatcher.new
end
end
}.to_app
end

def call(env)
@app.call(env)
end

private

def ensure_tmp_dirs
%w(cache pids sessions sockets).each do |dir_to_make|
FileUtils.mkdir_p(File.join(@path, 'tmp', dir_to_make))
end
end

end
end
40 changes: 2 additions & 38 deletions railties/lib/rails/commands/server.rb
@@ -1,7 +1,6 @@
require 'action_controller'

require 'fileutils'
require 'optparse'
require 'rails'

options = {
:Port => 3000,
Expand Down Expand Up @@ -46,10 +45,6 @@
puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}#{options[:path]}"

%w(cache pids sessions sockets).each do |dir_to_make|
FileUtils.mkdir_p(File.join(RAILS_ROOT, 'tmp', dir_to_make))
end

if options[:detach]
Process.daemon
pid = "#{RAILS_ROOT}/tmp/pids/server.pid"
Expand All @@ -60,38 +55,7 @@
ENV["RAILS_ENV"] = options[:environment]
RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV)

if File.exist?(options[:config])
config = options[:config]
if config =~ /\.ru$/
cfgfile = File.read(config)
if cfgfile[/^#\\(.*)/]
opts.parse!($1.split(/\s+/))
end
inner_app = eval("Rack::Builder.new {( " + cfgfile + "\n )}.to_app", nil, config)
else
require config
inner_app = Object.const_get(File.basename(config, '.rb').capitalize)
end
else
require RAILS_ROOT + "/config/environment"
inner_app = ActionController::Dispatcher.new
end

if options[:path].nil?
map_path = "/"
else
ActionController::Base.relative_url_root = options[:path]
map_path = options[:path]
end

app = Rack::Builder.new {
use Rails::Rack::LogTailer unless options[:detach]
use Rails::Rack::Debugger if options[:debugger]
map map_path do
use Rails::Rack::Static
run inner_app
end
}.to_app
app = Rails::Application.load(RAILS_ROOT, options)

puts "=> Call with -d to detach"

Expand Down
98 changes: 98 additions & 0 deletions railties/test/application/load_test.rb
@@ -0,0 +1,98 @@
require "isolation/abstract_unit"
require "rails"
require "rack"

module ApplicationTests
class LoadTest < Test::Unit::TestCase
include ActiveSupport::Testing::Isolation

def setup
build_app
end

test "rails app is present" do
assert File.exist?(app_path("config"))
end

test "running Rails::Application.load on the path returns a (vaguely) useful application" do
@app = Rails::Application.load app_path
assert_welcome get("/")
end

test "setting the map_path of the application" do
controller "says", <<-CONTROLLER
class SaysController < ActionController::Base
def index ; render :text => "MOO!" ; end
end
CONTROLLER

@app = Rails::Application.load app_path, :path => "/the/cow"

assert_missing get("/")
assert_welcome get("/the/cow")
assert_body "MOO!", get("/the/cow/says")
end

test "url generation with a base path" do
controller "generatin", <<-CONTROLLER
class GeneratinController < ActionController::Base
def index ; render :text => url_for(:action => "index", :only_path => true) ; end
end
CONTROLLER

@app = Rails::Application.load app_path, :path => "/base"

assert_body "/base/generatin", get("/base/generatin")
end

test "config.ru is used" do
app_file "config.ru", <<-CONFIG
class MyMiddleware
def initialize(app)
@app = app
end
def call(env)
status, headers, body = @app.call(env)
headers["Config-Ru-Test"] = "TESTING"
[status, headers, body]
end
end
use MyMiddleware
run proc {|env| [200, {"Content-Type" => "text/html"}, ["VICTORY"]] }
CONFIG

@app = Rails::Application.load app_path, :config => "config.ru"

assert_body "VICTORY", get("/omg")
assert_header "Config-Ru-Test", "TESTING", get("/omg")
end

test "arbitrary.rb can be used as a config" do
app_file "myapp.rb", <<-CONFIG
Myapp = proc {|env| [200, {"Content-Type" => "text/html"}, ["OMG ROBOTS"]] }
CONFIG

@app = Rails::Application.load app_path, :config => "myapp.rb"

assert_body "OMG ROBOTS", get("/omg")
end

%w(cache pids sessions sockets).each do |dir|
test "creating tmp/#{dir} if it does not exist" do
FileUtils.rm_r(app_path("tmp/#{dir}"))
Rails::Application.load app_path
assert File.exist?(app_path("tmp/#{dir}"))
end
end

test "LogTailer middleware is present when not detached" do

end

test "Debugger middleware is present when using debugger option" do

end
end
end
107 changes: 107 additions & 0 deletions railties/test/isolation/abstract_unit.rb
@@ -0,0 +1,107 @@
# Note:
# It is important to keep this file as light as possible
# the goal for tests that require this is to test booting up
# rails from an empty state, so anything added here could
# hide potential failures
#
# It is also good to know what is the bare minimum to get
# Rails booted up.

# TODO: Remove rubygems when possible
require 'rubygems'
require 'test/unit'

# TODO: Remove setting this magic constant
RAILS_FRAMEWORK_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../..")

# These load paths usually get set inside of boot.rb
$:.unshift "#{RAILS_FRAMEWORK_ROOT}/railties/lib"
$:.unshift "#{RAILS_FRAMEWORK_ROOT}/actionpack/lib"

# These files do not require any others and are needed
# to run the tests
require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/testing/isolation"
require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/testing/declarative"

module TestHelpers
module Paths
module_function

def tmp_path(*args)
File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. tmp] + args))
end

def app_path(*args)
tmp_path(*%w[app] + args)
end
end

module Rack
def extract_body(response)
"".tap do |body|
response[2].each {|chunk| body << chunk }
end
end

def get(path)
@app.call(::Rack::MockRequest.env_for(path))
end

def assert_welcome(resp)
assert_equal 200, resp[0]
assert resp[1]["Content-Type"] = "text/html"
assert extract_body(resp).match(/Welcome aboard/)
end

def assert_success(resp)
assert_equal 202, resp[0]
end

def assert_missing(resp)
assert_equal 404, resp[0]
end

def assert_header(key, value, resp)
assert_equal value, resp[1][key.to_s]
end

def assert_body(expected, resp)
assert_equal expected, extract_body(resp)
end
end

module Generation
def build_app
FileUtils.cp_r(tmp_path('app_template'), app_path)
end

def app_file(path, contents)
File.open(app_path(path), 'w') do |f|
f.puts contents
end
end

def controller(name, contents)
app_file("app/controllers/#{name}_controller.rb", contents)
end
end
end

class Test::Unit::TestCase
include TestHelpers::Paths
include TestHelpers::Rack
include TestHelpers::Generation
extend ActiveSupport::Testing::Declarative
end

# Create a scope and build a fixture rails app
Module.new do
extend TestHelpers::Paths
# Build a rails app
if File.exist?(tmp_path)
FileUtils.rm_rf(tmp_path)
end

FileUtils.mkdir(tmp_path)
`#{Gem.ruby} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails #{tmp_path('app_template')}`
end

0 comments on commit 4129449

Please sign in to comment.