nimboids-spork 0.8.99
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +6 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +129 -0
- data/assets/bootstrap.rb +29 -0
- data/bin/spork +20 -0
- data/ext/mkrf_conf.rb +26 -0
- data/features/at_exit_during_each_run.feature +36 -0
- data/features/cucumber_rails_integration.feature +107 -0
- data/features/diagnostic_mode.feature +41 -0
- data/features/gemfiles/rails3.0/Gemfile +10 -0
- data/features/gemfiles/rails3.0/Gemfile.lock +116 -0
- data/features/rails_delayed_loading_workarounds.feature +150 -0
- data/features/rspec_rails_integration.feature +92 -0
- data/features/spork_debugger.feature +108 -0
- data/features/steps/general_steps.rb +3 -0
- data/features/steps/rails_steps.rb +67 -0
- data/features/steps/sandbox_steps.rb +115 -0
- data/features/support/background_job.rb +63 -0
- data/features/support/bundler_helpers.rb +41 -0
- data/features/support/env.rb +105 -0
- data/features/unknown_app_framework.feature +42 -0
- data/lib/spork.rb +155 -0
- data/lib/spork/app_framework.rb +80 -0
- data/lib/spork/app_framework/padrino.rb +22 -0
- data/lib/spork/app_framework/rails.rb +82 -0
- data/lib/spork/app_framework/unknown.rb +6 -0
- data/lib/spork/custom_io_streams.rb +25 -0
- data/lib/spork/diagnoser.rb +105 -0
- data/lib/spork/ext/rails-reloader.rb +14 -0
- data/lib/spork/ext/ruby-debug.rb +150 -0
- data/lib/spork/forker.rb +71 -0
- data/lib/spork/run_strategy.rb +44 -0
- data/lib/spork/run_strategy/forking.rb +32 -0
- data/lib/spork/run_strategy/magazine.rb +141 -0
- data/lib/spork/run_strategy/magazine/magazine_slave.rb +30 -0
- data/lib/spork/run_strategy/magazine/magazine_slave_provider.rb +27 -0
- data/lib/spork/run_strategy/magazine/ring_server.rb +10 -0
- data/lib/spork/runner.rb +90 -0
- data/lib/spork/server.rb +76 -0
- data/lib/spork/test_framework.rb +167 -0
- data/lib/spork/test_framework/cucumber.rb +24 -0
- data/lib/spork/test_framework/rspec.rb +14 -0
- data/spec/spec_helper.rb +113 -0
- data/spec/spork/app_framework/rails_spec.rb +22 -0
- data/spec/spork/app_framework/unknown_spec.rb +12 -0
- data/spec/spork/app_framework_spec.rb +16 -0
- data/spec/spork/diagnoser_spec.rb +105 -0
- data/spec/spork/forker_spec.rb +44 -0
- data/spec/spork/run_strategy/forking_spec.rb +38 -0
- data/spec/spork/runner_spec.rb +50 -0
- data/spec/spork/server_spec.rb +15 -0
- data/spec/spork/test_framework/cucumber_spec.rb +11 -0
- data/spec/spork/test_framework/rspec_spec.rb +10 -0
- data/spec/spork/test_framework_shared_examples.rb +23 -0
- data/spec/spork/test_framework_spec.rb +90 -0
- data/spec/spork_spec.rb +153 -0
- data/spec/support/fake_framework.rb +15 -0
- data/spec/support/fake_run_strategy.rb +21 -0
- metadata +158 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
class BackgroundJob
|
2
|
+
attr_reader :stdin, :stdout, :stderr, :pid
|
3
|
+
def initialize(pid, stdin, stdout, stderr)
|
4
|
+
@pid, @stdin, @stdout, @stderr = pid, stdin, stdout, stderr
|
5
|
+
ObjectSpace.define_finalizer(self) { kill }
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.run(command)
|
9
|
+
command = sanitize_params(command) if command.is_a?(Array)
|
10
|
+
child_stdin, parent_stdin = IO::pipe
|
11
|
+
parent_stdout, child_stdout = IO::pipe
|
12
|
+
parent_stderr, child_stderr = IO::pipe
|
13
|
+
|
14
|
+
pid = Kernel.fork do
|
15
|
+
[parent_stdin, parent_stdout, parent_stderr].each { |io| io.close }
|
16
|
+
|
17
|
+
STDIN.reopen(child_stdin)
|
18
|
+
STDOUT.reopen(child_stdout)
|
19
|
+
STDERR.reopen(child_stderr)
|
20
|
+
|
21
|
+
[child_stdin, child_stdout, child_stderr].each { |io| io.close }
|
22
|
+
|
23
|
+
exec command
|
24
|
+
end
|
25
|
+
|
26
|
+
[child_stdin, child_stdout, child_stderr].each { |io| io.close }
|
27
|
+
parent_stdin.sync = true
|
28
|
+
|
29
|
+
new(pid, parent_stdin, parent_stdout, parent_stderr)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.sanitize_params(params)
|
33
|
+
params.map { |p| p.gsub(' ', '\ ') }.join(" ")
|
34
|
+
end
|
35
|
+
|
36
|
+
def kill(signal = 'TERM')
|
37
|
+
if running?
|
38
|
+
Process.kill(Signal.list[signal], @pid)
|
39
|
+
true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def interrupt
|
44
|
+
kill('INT')
|
45
|
+
end
|
46
|
+
|
47
|
+
def running?
|
48
|
+
return false unless @pid
|
49
|
+
Process.getpgid(@pid)
|
50
|
+
true
|
51
|
+
rescue Errno::ESRCH
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
def wait(timeout = 1000)
|
56
|
+
Timeout.timeout(timeout) do
|
57
|
+
Process.wait(@pid)
|
58
|
+
end
|
59
|
+
true
|
60
|
+
rescue Timeout::Error
|
61
|
+
false
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
module BundlerHelpers
|
3
|
+
extend self
|
4
|
+
def install_bundle(dir)
|
5
|
+
Dir.chdir(dir) do
|
6
|
+
command = "env RUBYOPT= BUNDLE_GEMFILE=Gemfile bundle install"
|
7
|
+
system(command)
|
8
|
+
$?.exitstatus
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def ensure_installed(dir)
|
13
|
+
gemfile_lock = dir + "/Gemfile.lock"
|
14
|
+
gemfile = dir + "/Gemfile"
|
15
|
+
bundle_environment = dir + "/.bundle/environment.rb"
|
16
|
+
case
|
17
|
+
when File.exist?(gemfile_lock) && File.mtime(gemfile) > File.mtime(gemfile_lock)
|
18
|
+
puts "Gemfile #{gemfile} has changed since it was locked. Re-locking..."
|
19
|
+
FileUtils.rm(gemfile_lock)
|
20
|
+
FileUtils.rm_rf(dir + "/.bundle")
|
21
|
+
when ! File.exist?(bundle_environment)
|
22
|
+
puts "Bundle #{gemfile} not installed. Installing..."
|
23
|
+
when File.mtime(bundle_environment) < File.mtime(gemfile_lock)
|
24
|
+
puts "#{gemfile_lock} is newer than #{bundle_environment}. Reinstalling"
|
25
|
+
else
|
26
|
+
return false
|
27
|
+
end
|
28
|
+
install_bundle(dir)
|
29
|
+
end
|
30
|
+
|
31
|
+
def expand_gemfile(gemfile)
|
32
|
+
possibilities = [File.expand_path(gemfile, Dir.pwd), SporkWorld::GEMFILES_ROOT + gemfile + "Gemfile"]
|
33
|
+
possibilities.detect {|f| File.exist?(f)} || raise(RuntimeError, %(Gemfile not found:\n #{possibilities * "\n"}))
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_gemfile(gemfile)
|
37
|
+
gemfile = expand_gemfile(gemfile || "rails3.0")
|
38
|
+
ensure_installed(File.dirname(gemfile))
|
39
|
+
ENV["BUNDLE_GEMFILE"] = gemfile
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'pathname'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'forwardable'
|
5
|
+
require 'tempfile'
|
6
|
+
require 'rspec/expectations'
|
7
|
+
require 'timeout'
|
8
|
+
|
9
|
+
require(File.dirname(__FILE__) + '/background_job.rb')
|
10
|
+
|
11
|
+
SPORK_ROOT = Pathname.new(File.expand_path('../../', File.dirname(__FILE__)))
|
12
|
+
class SporkWorld
|
13
|
+
RUBY_BINARY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
|
14
|
+
BINARY = SPORK_ROOT + 'bin/spork'
|
15
|
+
SANDBOX_DIR = SPORK_ROOT + "tmp/sandbox"
|
16
|
+
GEMFILES_ROOT = SPORK_ROOT + "features/gemfiles"
|
17
|
+
SPORK_LIBDIR = SPORK_ROOT + "lib"
|
18
|
+
|
19
|
+
extend Forwardable
|
20
|
+
def_delegators SporkWorld, :sandbox_dir, :spork_lib_dir
|
21
|
+
|
22
|
+
def spork_lib_dir
|
23
|
+
@spork_lib_dir ||= File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
@current_dir = SANDBOX_DIR
|
28
|
+
@background_jobs = []
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
attr_reader :last_exit_status, :last_stderr, :last_stdout, :background_jobs
|
33
|
+
def last_stderr
|
34
|
+
return @last_stderr if @last_stderr
|
35
|
+
if @background_job
|
36
|
+
@last_stderr = @background_job.stderr.read
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def last_stdout
|
42
|
+
return @last_stdout if @last_stdout
|
43
|
+
if @background_job
|
44
|
+
@last_stdout = @background_job.stdout.read
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_file(file_name, file_content)
|
49
|
+
file_content.gsub!("SPORK_LIB", "'#{spork_lib_dir}'") # Some files, such as Rakefiles need to use the lib dir
|
50
|
+
in_current_dir do
|
51
|
+
FileUtils.mkdir_p(File.dirname(file_name))
|
52
|
+
File.open(file_name, 'w') { |f| f << file_content }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def in_current_dir(&block)
|
57
|
+
Dir.chdir(@current_dir, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def run(command)
|
61
|
+
stderr_file = Tempfile.new('spork')
|
62
|
+
stderr_file.close
|
63
|
+
in_current_dir do
|
64
|
+
@last_stdout = `env RUBYOPT= bundle exec #{command} 2> #{stderr_file.path}`
|
65
|
+
@last_exit_status = $?.exitstatus
|
66
|
+
end
|
67
|
+
@last_stderr = IO.read(stderr_file.path)
|
68
|
+
end
|
69
|
+
|
70
|
+
def run_in_background(command)
|
71
|
+
in_current_dir do
|
72
|
+
@background_job = BackgroundJob.run("env RUBYOPT= bundle exec " + command)
|
73
|
+
end
|
74
|
+
@background_jobs << @background_job
|
75
|
+
@background_job
|
76
|
+
end
|
77
|
+
|
78
|
+
def terminate_background_jobs
|
79
|
+
if @background_jobs
|
80
|
+
@background_jobs.each do |background_job|
|
81
|
+
background_job.kill
|
82
|
+
end
|
83
|
+
end
|
84
|
+
@background_jobs.clear
|
85
|
+
@background_job = nil
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
require(SPORK_ROOT + "features/support/bundler_helpers.rb")
|
90
|
+
BundlerHelpers.set_gemfile(ENV["GEMFILE"])
|
91
|
+
|
92
|
+
|
93
|
+
World do
|
94
|
+
SporkWorld.new
|
95
|
+
end
|
96
|
+
|
97
|
+
Before do
|
98
|
+
FileUtils.rm_rf SporkWorld::SANDBOX_DIR
|
99
|
+
FileUtils.mkdir_p SporkWorld::SANDBOX_DIR
|
100
|
+
end
|
101
|
+
|
102
|
+
After do
|
103
|
+
# FileUtils.rm_rf SporkWorld::SANDBOX_DIR
|
104
|
+
terminate_background_jobs
|
105
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
Feature: Unknown app frameworks
|
2
|
+
To increase to usefulness of Spork
|
3
|
+
Spork will work with unknown (or no) application frameworks
|
4
|
+
|
5
|
+
Scenario: Unsporked spec_helper
|
6
|
+
|
7
|
+
Given a file named "spec/spec_helper.rb" with:
|
8
|
+
"""
|
9
|
+
require 'rubygems'
|
10
|
+
require 'spec'
|
11
|
+
"""
|
12
|
+
When I run spork
|
13
|
+
Then the error output should contain "Using RSpec"
|
14
|
+
Then the error output should match /You must bootstrap .+spec\/spec_helper\.rb to continue/
|
15
|
+
|
16
|
+
Scenario: Sporked spec_helper
|
17
|
+
Given a file named "spec/spec_helper.rb" with:
|
18
|
+
"""
|
19
|
+
require 'rubygems'
|
20
|
+
require 'spork'
|
21
|
+
|
22
|
+
Spork.prefork do
|
23
|
+
require 'spec'
|
24
|
+
end
|
25
|
+
|
26
|
+
Spork.each_run do
|
27
|
+
$each_run
|
28
|
+
end
|
29
|
+
"""
|
30
|
+
And a file named "spec/did_it_work_spec.rb" with:
|
31
|
+
"""
|
32
|
+
describe "Did it work?" do
|
33
|
+
it "checks to see if all worked" do
|
34
|
+
Spork.state.should == :using_spork
|
35
|
+
puts "Specs successfully run within spork"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
"""
|
39
|
+
When I fire up a spork instance with "spork rspec"
|
40
|
+
And I run spec --drb spec/did_it_work_spec.rb
|
41
|
+
Then the output should contain "Specs successfully run within spork"
|
42
|
+
|
data/lib/spork.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
|
2
|
+
require 'pathname'
|
3
|
+
module Spork
|
4
|
+
BINARY = File.expand_path(File.dirname(__FILE__) + '/../bin/spork')
|
5
|
+
LIBDIR = Pathname.new(File.expand_path(File.dirname(__FILE__)))
|
6
|
+
|
7
|
+
autoload :Server, (LIBDIR + 'spork/server').to_s
|
8
|
+
autoload :TestFramework, (LIBDIR + 'spork/test_framework').to_s
|
9
|
+
autoload :AppFramework, (LIBDIR + 'spork/app_framework').to_s
|
10
|
+
autoload :RunStrategy, (LIBDIR + 'spork/run_strategy').to_s
|
11
|
+
autoload :Runner, (LIBDIR + 'spork/runner').to_s
|
12
|
+
autoload :Forker, (LIBDIR + 'spork/forker').to_s
|
13
|
+
autoload :Diagnoser, (LIBDIR + 'spork/diagnoser').to_s
|
14
|
+
|
15
|
+
class << self
|
16
|
+
# Run a block, during prefork mode. By default, if prefork is called twice in the same file and line number, the supplied block will only be ran once.
|
17
|
+
#
|
18
|
+
# == Parameters
|
19
|
+
#
|
20
|
+
# * +prevent_double_run+ - Pass false to disable double run prevention
|
21
|
+
def prefork(prevent_double_run = true, &block)
|
22
|
+
return if prevent_double_run && already_ran?(caller.first)
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
|
26
|
+
# Run a block AFTER the fork occurs. By default, if prefork is called twice in the same file and line number, the supplied block will only be ran once.
|
27
|
+
#
|
28
|
+
# == Parameters
|
29
|
+
#
|
30
|
+
# * +prevent_double_run+ - Pass false to disable double run prevention
|
31
|
+
def each_run(prevent_double_run = true, &block)
|
32
|
+
return if prevent_double_run && already_ran?(caller.first)
|
33
|
+
if state == :prefork
|
34
|
+
each_run_procs << block
|
35
|
+
else
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Run a block after specs are run.
|
41
|
+
#
|
42
|
+
# == Parameters
|
43
|
+
#
|
44
|
+
# * +prevent_double_run+ - Pass false to disable double run prevention
|
45
|
+
def after_each_run(prevent_double_run = true, &block)
|
46
|
+
return if prevent_double_run && already_ran?(caller.first)
|
47
|
+
after_each_run_procs << block
|
48
|
+
end
|
49
|
+
|
50
|
+
def using_spork?
|
51
|
+
state != :not_using_spork
|
52
|
+
end
|
53
|
+
|
54
|
+
def state
|
55
|
+
@state ||= :not_using_spork
|
56
|
+
end
|
57
|
+
|
58
|
+
# Used by the server. Called when loading the prefork blocks of the code.
|
59
|
+
def exec_prefork(&block)
|
60
|
+
@state = :prefork
|
61
|
+
yield
|
62
|
+
end
|
63
|
+
|
64
|
+
# Used by the server. Called to run all of the prefork blocks.
|
65
|
+
def exec_each_run(&block)
|
66
|
+
@state = :run
|
67
|
+
activate_after_each_run_at_exit_hook
|
68
|
+
each_run_procs.each { |p| p.call }
|
69
|
+
each_run_procs.clear
|
70
|
+
yield if block_given?
|
71
|
+
end
|
72
|
+
|
73
|
+
# Used by the server. Called to run all of the after_each_run blocks.
|
74
|
+
def exec_after_each_run
|
75
|
+
# processes in reverse order similar to at_exit
|
76
|
+
while p = after_each_run_procs.pop; p.call; end
|
77
|
+
true
|
78
|
+
end
|
79
|
+
|
80
|
+
# Traps an instance method of a class (or module) so any calls to it don't actually run until Spork.exec_each_run
|
81
|
+
def trap_method(klass, method_name)
|
82
|
+
method_name_without_spork, method_name_with_spork = alias_method_names(method_name, :spork)
|
83
|
+
|
84
|
+
klass.class_eval <<-EOF, __FILE__, __LINE__ + 1
|
85
|
+
alias :#{method_name_without_spork} :#{method_name} unless method_defined?(:#{method_name_without_spork})
|
86
|
+
def #{method_name}(*args, &block)
|
87
|
+
Spork.each_run(false) do
|
88
|
+
#{method_name_without_spork}(*args, &block)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
EOF
|
92
|
+
end
|
93
|
+
|
94
|
+
# Same as trap_method, but for class methods instead
|
95
|
+
def trap_class_method(klass, method_name)
|
96
|
+
trap_method((class << klass; self; end), method_name)
|
97
|
+
end
|
98
|
+
|
99
|
+
def detect_and_require(subfolder)
|
100
|
+
([LIBDIR.to_s] + other_spork_gem_load_paths).uniq.each do |gem_path|
|
101
|
+
Dir.glob(File.join(gem_path, subfolder)).each { |file| require file }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def other_spork_gem_load_paths
|
106
|
+
@other_spork_gem_load_paths ||= (
|
107
|
+
Gem.latest_load_paths.grep(/spork/).select do |g|
|
108
|
+
not g.match(%r{/spork-[0-9\-.]+/lib}) # don't include other versions of spork
|
109
|
+
end
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
def activate_after_each_run_at_exit_hook
|
115
|
+
Kernel.module_eval do
|
116
|
+
def at_exit(&block)
|
117
|
+
Spork.after_each_run(false, &block)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def alias_method_names(method_name, feature)
|
123
|
+
/^(.+?)([\?\!]{0,1})$/.match(method_name.to_s)
|
124
|
+
["#{$1}_without_spork#{$2}", "#{$1}_with_spork#{$2}"]
|
125
|
+
end
|
126
|
+
|
127
|
+
def already_ran
|
128
|
+
@already_ran ||= []
|
129
|
+
end
|
130
|
+
|
131
|
+
def expanded_caller(caller_line)
|
132
|
+
file, line = caller_line.split(/:(\d+)/)
|
133
|
+
line.gsub(/:.+/, '')
|
134
|
+
expanded = File.expand_path(file, Dir.pwd) + ":" + line
|
135
|
+
if ENV['OS'] == 'Windows_NT' # windows
|
136
|
+
expanded = expanded[2..-1]
|
137
|
+
end
|
138
|
+
expanded
|
139
|
+
end
|
140
|
+
|
141
|
+
def already_ran?(caller_script_and_line)
|
142
|
+
return true if already_ran.include?(expanded_caller(caller_script_and_line))
|
143
|
+
already_ran << expanded_caller(caller_script_and_line)
|
144
|
+
false
|
145
|
+
end
|
146
|
+
|
147
|
+
def each_run_procs
|
148
|
+
@each_run_procs ||= []
|
149
|
+
end
|
150
|
+
|
151
|
+
def after_each_run_procs
|
152
|
+
@after_each_run_procs ||= []
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class Spork::AppFramework
|
2
|
+
# A hash of procs where the key is the class name, and the proc takes no arguments and returns true if it detects that said application framework is being used in the project.
|
3
|
+
#
|
4
|
+
# The key :Rails maps to Spork::AppFramework::Rails
|
5
|
+
#
|
6
|
+
# This is used to reduce the amount of code needed to be loaded - only the detected application framework's support code is loaded.
|
7
|
+
SUPPORTED_FRAMEWORKS = {
|
8
|
+
:Padrino => lambda {
|
9
|
+
File.exist?("config/boot.rb") && File.read("config/boot.rb").include?('PADRINO')
|
10
|
+
},
|
11
|
+
:Rails => lambda {
|
12
|
+
File.exist?("config/environment.rb") && (
|
13
|
+
File.read("config/environment.rb").include?('RAILS_GEM_VERSION') ||
|
14
|
+
(File.exist?("config/application.rb") && File.read("config/application.rb").include?("Rails::Application"))
|
15
|
+
)
|
16
|
+
}
|
17
|
+
} unless defined? SUPPORTED_FRAMEWORKS
|
18
|
+
|
19
|
+
def self.setup_autoload
|
20
|
+
([:Unknown] + SUPPORTED_FRAMEWORKS.keys).each do |name|
|
21
|
+
autoload name, File.join(File.dirname(__FILE__), "app_framework", name.to_s.downcase)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Iterates through all SUPPORTED_FRAMEWORKS and returns the symbolic name of the project application framework detected. Otherwise, returns :Unknown
|
26
|
+
def self.detect_framework_name
|
27
|
+
SUPPORTED_FRAMEWORKS.each do |key, value|
|
28
|
+
return key if value.call
|
29
|
+
end
|
30
|
+
:Unknown
|
31
|
+
end
|
32
|
+
|
33
|
+
# Same as detect_framework_name, but returns an instance of the specific AppFramework class.
|
34
|
+
def self.detect_framework
|
35
|
+
name = detect_framework_name
|
36
|
+
self[name]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Initializes, stores, and returns a singleton instance of the named AppFramework.
|
40
|
+
#
|
41
|
+
# == Parameters
|
42
|
+
#
|
43
|
+
# # +name+ - A symbolic name of a AppFramework subclass
|
44
|
+
#
|
45
|
+
# == Example
|
46
|
+
#
|
47
|
+
# Spork::AppFramework[:Rails]
|
48
|
+
def self.[](name)
|
49
|
+
instances[name] ||= const_get(name).new
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.short_name
|
53
|
+
name.gsub('Spork::AppFramework::', '')
|
54
|
+
end
|
55
|
+
|
56
|
+
# If there is some stuff out of the box that the Spork can do to speed up tests without the test helper file being bootstrapped, this should return false.
|
57
|
+
def bootstrap_required?
|
58
|
+
entry_point.nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Abstract: The path to the file that loads the project environment, ie config/environment.rb. Returns nil if there is none.
|
62
|
+
def entry_point
|
63
|
+
raise NotImplementedError
|
64
|
+
end
|
65
|
+
|
66
|
+
def preload(&block)
|
67
|
+
yield
|
68
|
+
end
|
69
|
+
|
70
|
+
def short_name
|
71
|
+
self.class.short_name
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
def self.instances
|
76
|
+
@instances ||= {}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
Spork::AppFramework.setup_autoload
|