rails_2_preload 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/rails_2_preload.rb +172 -0
- metadata +47 -0
@@ -0,0 +1,172 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
require "pathname"
|
3
|
+
|
4
|
+
# The purpose of Rails2Preload is to optimize testing with Spin and Rails 2.
|
5
|
+
# It does this by splitting the Rails 2 initialization method
|
6
|
+
# (Rails::Initializer#process) into two phases: preload and postload. This
|
7
|
+
# gives us the capability of using Spin:
|
8
|
+
#
|
9
|
+
# * without having to reboot Rails every time a class is modified
|
10
|
+
#
|
11
|
+
# * without having to disable class caching
|
12
|
+
#
|
13
|
+
module Rails2Preload
|
14
|
+
# All of the methods of the Rails initialization process, in order.
|
15
|
+
METHODS = [
|
16
|
+
:check_ruby_version,
|
17
|
+
:install_gem_spec_stubs,
|
18
|
+
:set_load_path,
|
19
|
+
:add_gem_load_paths,
|
20
|
+
:require_frameworks,
|
21
|
+
:set_autoload_paths,
|
22
|
+
:add_plugin_load_paths,
|
23
|
+
:load_environment,
|
24
|
+
:preload_frameworks,
|
25
|
+
:initialize_encoding,
|
26
|
+
:initialize_database,
|
27
|
+
:initialize_cache,
|
28
|
+
:initialize_framework_caches,
|
29
|
+
:initialize_logger,
|
30
|
+
:initialize_framework_logging,
|
31
|
+
:initialize_dependency_mechanism,
|
32
|
+
:initialize_whiny_nils,
|
33
|
+
:initialize_time_zone,
|
34
|
+
:initialize_i18n,
|
35
|
+
:initialize_framework_settings,
|
36
|
+
:initialize_framework_views,
|
37
|
+
:initialize_metal,
|
38
|
+
:add_support_load_paths,
|
39
|
+
:check_for_unbuilt_gems,
|
40
|
+
:load_gems,
|
41
|
+
:load_plugins,
|
42
|
+
:add_gem_load_paths,
|
43
|
+
:load_gems,
|
44
|
+
:check_gem_dependencies,
|
45
|
+
:load_application_initializers,
|
46
|
+
:after_initialize,
|
47
|
+
:initialize_database_middleware,
|
48
|
+
:prepare_dispatcher,
|
49
|
+
:initialize_routing,
|
50
|
+
:load_observers,
|
51
|
+
:load_view_paths,
|
52
|
+
:load_application_classes,
|
53
|
+
:disable_dependency_loading
|
54
|
+
]
|
55
|
+
|
56
|
+
class << self
|
57
|
+
# The methods run in the preload phase.
|
58
|
+
attr_reader :preload_methods
|
59
|
+
# The methods run in the postload phase.
|
60
|
+
attr_reader :postload_methods
|
61
|
+
end
|
62
|
+
|
63
|
+
# Given a method name, the methods of the Rails initialization process are
|
64
|
+
# split into two groups, preload and postload.
|
65
|
+
def self.preload_until(method)
|
66
|
+
index = METHODS.index(method)
|
67
|
+
raise(ArgumentError, method) if index.nil?
|
68
|
+
|
69
|
+
@preload_methods, @postload_methods = METHODS[0..index - 1], METHODS[index..-1]
|
70
|
+
end
|
71
|
+
|
72
|
+
# By default, we'll preload until the application classes (i.e. models) are
|
73
|
+
# loaded. This is optimal for unit testing.
|
74
|
+
self.preload_until(:load_application_classes)
|
75
|
+
|
76
|
+
# Called from .spin.rb to add all hooks necessary to integrate
|
77
|
+
# Rails2Preload.
|
78
|
+
def self.add_spin_hooks
|
79
|
+
Spin.hook(:before_preload) { Rails2Preload.prepare_rails }
|
80
|
+
|
81
|
+
Spin.hook(:after_preload) do
|
82
|
+
if Rails2Preload.preload_methods.include? :load_application_classes
|
83
|
+
# If classes are preloaded, empty the connection pool so forked
|
84
|
+
# processes are forced to establish new connections. Otherwise, the
|
85
|
+
# second time a test is run, an exception like this is raised:
|
86
|
+
# ActiveRecord::StatementInvalid PGError: no connection to the server
|
87
|
+
ActiveRecord::Base.connection_pool.disconnect!
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
Spin.hook(:after_fork) do
|
92
|
+
# Create a new initializer instance, but reuse the configuration already
|
93
|
+
# established by the preload phase.
|
94
|
+
initializer = Rails::Initializer.new(Rails.configuration)
|
95
|
+
initializer.postload
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Called by the Rails patch to run the preload phase.
|
100
|
+
def self.preload(initializer)
|
101
|
+
preload_methods.each { |method| benchmark(initializer, method) }
|
102
|
+
end
|
103
|
+
|
104
|
+
# Called by the Rails patch to run the postload phase.
|
105
|
+
def self.postload(initializer)
|
106
|
+
postload_methods.each { |method| benchmark(initializer, method) }
|
107
|
+
end
|
108
|
+
|
109
|
+
# Called by the :before_preload Spin hook to prepare Rails.
|
110
|
+
def self.prepare_rails
|
111
|
+
# We need to boot Rails before adding methods to Rails::Initializer.
|
112
|
+
# Otherwise, Rails.booted? returns true and Rails.boot! short-circuits.
|
113
|
+
boot_rails
|
114
|
+
apply_initializer_patch
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
# This is the monkey-patch that splits the Rails 2 initialization process
|
120
|
+
# (Rails::Initializer#process) into two phases, preload and postload.
|
121
|
+
def self.apply_initializer_patch
|
122
|
+
module_eval <<-RUBY , __FILE__, __LINE__ + 1
|
123
|
+
module ::Rails
|
124
|
+
class Initializer
|
125
|
+
# The run method *does* support calling an arbitrary method (the
|
126
|
+
# command parameter) to initialize Rails. However, my personal
|
127
|
+
# preference is to not change anything in the app (in this case,
|
128
|
+
# environment.rb) to support Spin.
|
129
|
+
def self.run(command = :preload, configuration = Configuration.new)
|
130
|
+
yield configuration if block_given?
|
131
|
+
initializer = new configuration
|
132
|
+
initializer.send(command)
|
133
|
+
initializer
|
134
|
+
end
|
135
|
+
|
136
|
+
# Runs the preload phase of the Rails initialization process.
|
137
|
+
def preload
|
138
|
+
Rails.configuration = configuration
|
139
|
+
Rails2Preload.preload(self)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Runs the postload phase of the Rails initialization process.
|
143
|
+
def postload
|
144
|
+
Rails2Preload.postload(self)
|
145
|
+
Rails.initialized = true
|
146
|
+
end
|
147
|
+
end # Initializer
|
148
|
+
end # Rails
|
149
|
+
RUBY
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns a Pathname object. We'll use it to determine what the Rails root
|
153
|
+
# is before the Rails module is available.
|
154
|
+
def self.rails_root
|
155
|
+
Bundler.root
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.boot_rails
|
159
|
+
require(rails_root + "config/boot")
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.initialize_rails
|
163
|
+
require(rails_root + "config/environment")
|
164
|
+
end
|
165
|
+
|
166
|
+
# Benchmarks a method sent to an object and prints the result.
|
167
|
+
def self.benchmark(object, method, *args)
|
168
|
+
print "[Rails2Preload] #{method}"
|
169
|
+
seconds = Benchmark.realtime { object.send(method, *args) }
|
170
|
+
puts "#{"%0.3f" % seconds}s".rjust(40 - method.to_s.length)
|
171
|
+
end
|
172
|
+
end # Rails2Preload
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails_2_preload
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Todd Mazierski
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-09 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! "The purpose of Rails2Preload is to optimize testing with Spin\n and
|
15
|
+
Rails 2. It does this by splitting the Rails 2 initialization method\n (Rails::Initializer#process)
|
16
|
+
into two phases: preload and postload."
|
17
|
+
email: todd@paperlesspost.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- lib/rails_2_preload.rb
|
23
|
+
homepage: https://github.com/paperlesspost/rails-2-preload
|
24
|
+
licenses: []
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 1.8.23
|
44
|
+
signing_key:
|
45
|
+
specification_version: 3
|
46
|
+
summary: Preloads Rails 2 for testing with Spin
|
47
|
+
test_files: []
|