spring 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,30 @@
1
+ ## 0.0.10
2
+
3
+ * Added `Spring.watch_via=` configuration option to switch between
4
+ polling and the `listen` gem. Previously, we used the `listen` gem if
5
+ it was available, but this makes the option explicit. Set
6
+ `Spring.watch_via = :listen` to use the listen gem.
7
+ * Fallback when Process.fork is not available. In such cases, the user
8
+ will not receive the speedup that Spring provides, but won't receive
9
+ an error either.
10
+ * Don't preload `test_helper` or `spec_helper` by default. This was
11
+ causing people subtle problems (for example see #113) and is perhaps
12
+ surprising behaviour. It may be desirable but it depends on the
13
+ application, therefore we suggest it to people in the README but no
14
+ longer do it by default.
15
+ * Don't stay connected to database in the application processes. There's
16
+ no need to keep a connection open.
17
+ * Avoid using the database in the application processes. Previously,
18
+ reloading the autoloaded constants would inadvertantly cause a
19
+ connection to the database, which would then prevent tasks like
20
+ db:create from running (because at that point the database doesn't
21
+ exist)
22
+ * Removed ability to specify list of files for a command to preload. We
23
+ weren't using this any more internally, and this is easy to do by
24
+ placing requires in suitable locations in the Rails boot process
25
+ (which is not explained in the README).
26
+ * Seed the random number generator on each run.
27
+
1
28
  ## 0.0.9
2
29
 
3
30
  * Added `Spring::Commands::Rake.environment_matchers` for matching
data/Gemfile CHANGED
@@ -4,5 +4,3 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  gem 'listen', :require => false
7
- gem 'rb-inotify', :require => false
8
- gem 'rb-fsevent', :require => false
data/README.md CHANGED
@@ -233,15 +233,20 @@ spring repository.
233
233
 
234
234
  ### `testunit`
235
235
 
236
- Runs a test (e.g. Test::Unit, MiniTest::Unit, etc.) Preloads the `test_helper` file.
236
+ Runs a test (e.g. Test::Unit, MiniTest::Unit, etc.)
237
237
 
238
238
  This command can also recursively run a directory of tests. For example,
239
239
  `spring testunit test/functional` will run `test/functional/**/*_test.rb`.
240
240
 
241
+ If your test helper file takes a while to load, consider preloading it
242
+ (see "Running code before forking" below).
243
+
241
244
  ### `rspec`
242
245
 
243
- Runs an rspec spec, exactly the same as the `rspec` executable. Preloads
244
- the `spec_helper` file.
246
+ Runs an rspec spec, exactly the same as the `rspec` executable.
247
+
248
+ If your spec helper file takes a while to load, consider preloading it
249
+ (see "Running code before forking" below).
245
250
 
246
251
  ### `cucumber`
247
252
 
@@ -268,11 +273,11 @@ a different sub command (e.g. `rails server`) then spring will automatically
268
273
  pass it through to the underlying `rails` executable (without the
269
274
  speed-up).
270
275
 
271
- ## Configuration file
276
+ ## Configuration
272
277
 
273
278
  Spring will read `config/spring.rb` for custom settings, described below.
274
279
 
275
- ### Specifying application root
280
+ ### Application root
276
281
 
277
282
  Spring must know how to find your Rails application. If you have a
278
283
  normal app everything works out of the box. If you are working on a
@@ -283,26 +288,20 @@ Spring where your app is located:
283
288
  Spring.application_root = './test/dummy'
284
289
  ```
285
290
 
286
- ### Preloading files
287
-
288
- Every Spring command has the ability to preload a set of files. The
289
- `test` command for example preloads `test_helper` (it also adds the
290
- `test/` directory to your load path). If the
291
- defaults don't work for your application you can configure the
292
- preloads for every command:
293
-
294
- ```ruby
295
- # if your test helper is called "helper"
296
- Spring::Commands::TestUnit.preloads = %w(helper)
291
+ ### Running code before forking
297
292
 
298
- # if you don't want to preload spec_helper.rb
299
- Spring::Commands::RSpec.preloads = []
293
+ There is no `Spring.before_fork` callback. To run something before the
294
+ fork, you can place it in `config/spring.rb` or in any of the files
295
+ which get run when your application initializers, such as
296
+ `config/application.rb`, `config/environments/*.rb` or
297
+ `config/initializers/*.rb`.
300
298
 
301
- # if you want to preload additional files for the console
302
- Spring::Commands::RailsConsole.preloads << 'extensions/console_helper'
303
- ```
299
+ For example, if loading your test helper is slow, you might like to
300
+ preload it to speed up your test runs. To do this you could put a
301
+ `require Rails.root.join("test/helper")` in
302
+ `config/environments/test.rb`.
304
303
 
305
- ### Callbacks after forking
304
+ ### Running code after forking
306
305
 
307
306
  You might want to run code after Spring forked off the process but
308
307
  before the actual command is run. You might want to use an
@@ -320,31 +319,27 @@ If you want to register multiple callbacks you can simply call
320
319
 
321
320
  ### Watching files and directories
322
321
 
323
- As mentioned above, Spring will automatically detect file changes to any file loaded when the server
324
- boots. If you would like to watch additional files or directories, use `watch`:
322
+ Spring will automatically detect file changes to any file loaded when the server
323
+ boots. Changes will cause the affected environments to be restarted.
324
+
325
+ If there are additional files or directories which should trigger an
326
+ application restart, you can specify them with `Spring.watch`:
325
327
 
326
328
  ```ruby
327
329
  Spring.watch "spec/factories"
328
330
  ```
329
331
 
330
- ## Other configuration
331
-
332
- ### tmp directory
333
-
334
- Spring needs a tmp directory. This will default to `Rails.root.join('tmp', 'spring')`.
335
- You can set your own configuration directory by setting the `SPRING_TMP_PATH` environment variable.
336
-
337
- ### Filesystem polling speed
338
-
339
- By default Spring will check the filesystem for changes once every 0.2 seconds. This
332
+ By default Spring polls the filesystem for changes once every 0.2 seconds. This
340
333
  method requires zero configuration, but if you find that it's using too
341
- much CPU, then you can turn on event-based file system listening by
342
- adding the following to to your `Gemfile`:
334
+ much CPU, then you can turn on event-based file system listening:
343
335
 
344
336
  ```ruby
345
- group :development, :test do
346
- gem 'listen'
347
- end
337
+ Spring.watch_method = :listen
348
338
  ```
349
339
 
350
- Note that this make the initial application startup slightly slower.
340
+ You may need to add the [`listen` gem](https://github.com/guard/listen) to your `Gemfile`.
341
+
342
+ ### tmp directory
343
+
344
+ Spring needs a tmp directory. This will default to `Rails.root.join('tmp', 'spring')`.
345
+ You can set your own configuration directory by setting the `SPRING_TMP_PATH` environment variable.
data/bin/spring CHANGED
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
- require 'spring/client'
5
- Spring::Client.run(ARGV)
3
+ if Process.respond_to?(:fork)
4
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
5
+ require 'spring/client'
6
+ Spring::Client.run(ARGV)
7
+ else
8
+ exec "bundle", "exec", *ARGV
9
+ end
@@ -1,5 +1,4 @@
1
1
  require "set"
2
- require "json"
3
2
 
4
3
  require "spring/configuration"
5
4
  require "spring/watcher"
@@ -28,10 +27,17 @@ module Spring
28
27
  ActiveSupport::Dependencies.mechanism = :load
29
28
  end
30
29
 
30
+ # This initializer has issues after we disconnect from the DB, but we don't need it.
31
+ if defined?(ActiveRecord::Base)
32
+ ActiveRecord::Railtie.initializers.delete_if { |i| i.name == "active_record.set_reloader_hooks" }
33
+ end
34
+
31
35
  require Spring.application_root_path.join("config", "environment")
32
36
 
37
+ ActiveRecord::Base.remove_connection if defined?(ActiveRecord::Base)
38
+
33
39
  watcher.add loaded_application_features
34
- watcher.add "Gemfile", "Gemfile.lock"
40
+ watcher.add Spring.gemfile, "#{Spring.gemfile}.lock"
35
41
  watcher.add Rails.application.paths["config/initializers"]
36
42
 
37
43
  run
@@ -55,7 +61,7 @@ module Spring
55
61
  manager.puts
56
62
 
57
63
  streams = 3.times.map { client.recv_io }
58
- args = JSON.parse(client.read(client.gets.to_i))
64
+ args = JSON.load(client.read(client.gets.to_i))
59
65
  command = Spring.command(args.shift)
60
66
 
61
67
  setup command
@@ -67,8 +73,23 @@ module Spring
67
73
  Process.setsid
68
74
  [STDOUT, STDERR, STDIN].zip(streams).each { |a, b| a.reopen(b) }
69
75
  IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
76
+
77
+ ActiveRecord::Base.establish_connection if defined?(ActiveRecord::Base)
78
+ ARGV.replace(args)
79
+ srand
80
+
70
81
  invoke_after_fork_callbacks
71
- command.call(args)
82
+
83
+ if command.respond_to?(:call)
84
+ command.call
85
+ else
86
+ exec_name = command.exec_name
87
+ gem_name = command.gem_name if command.respond_to?(:gem_name)
88
+
89
+ exec = Gem.bin_path(gem_name || exec_name, exec_name)
90
+ $0 = exec
91
+ load exec
92
+ end
72
93
  }
73
94
 
74
95
  manager.puts pid
@@ -1,9 +1,10 @@
1
1
  require "spring/configuration"
2
+ require "spring/json"
3
+
2
4
  require "spring/client/command"
3
5
  require "spring/client/run"
4
6
  require "spring/client/help"
5
7
  require "spring/client/binstub"
6
- require "spring/client/start"
7
8
  require "spring/client/stop"
8
9
  require "spring/client/status"
9
10
  require "spring/client/rails"
@@ -13,7 +14,6 @@ module Spring
13
14
  COMMANDS = {
14
15
  "help" => Client::Help,
15
16
  "binstub" => Client::Binstub,
16
- "start" => Client::Start,
17
17
  "stop" => Client::Stop,
18
18
  "status" => Client::Status,
19
19
  "rails" => Client::Rails
@@ -48,6 +48,8 @@ module Spring
48
48
  def description_for_command(command)
49
49
  if command.respond_to?(:description)
50
50
  command.description
51
+ elsif command.respond_to?(:exec_name)
52
+ "Runs the #{command.exec_name} command"
51
53
  else
52
54
  "No description given."
53
55
  end
@@ -1,6 +1,5 @@
1
1
  require "rbconfig"
2
2
  require "socket"
3
- require "json"
4
3
 
5
4
  module Spring
6
5
  module Client
@@ -29,7 +28,10 @@ module Spring
29
28
 
30
29
  def boot_server
31
30
  env.socket_path.unlink if env.socket_path.exist?
32
- Process.spawn(BINFILE, "start")
31
+ fork {
32
+ require "spring/server"
33
+ Spring::Server.boot
34
+ }
33
35
  sleep 0.1 until env.socket_path.exist?
34
36
  end
35
37
 
@@ -48,7 +50,7 @@ ERROR
48
50
 
49
51
  def connect_to_application(client)
50
52
  server.send_io client
51
- send_json server, args: args, env: ENV.to_hash
53
+ send_json server, "args" => args, "default_rails_env" => default_rails_env
52
54
  server.gets or raise CommandNotFound
53
55
  end
54
56
 
@@ -95,9 +97,13 @@ ERROR
95
97
  def send_json(socket, data)
96
98
  data = JSON.dump(data)
97
99
 
98
- socket.puts data.length
100
+ socket.puts data.bytesize
99
101
  socket.write data
100
102
  end
103
+
104
+ def default_rails_env
105
+ ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
106
+ end
101
107
  end
102
108
  end
103
109
  end
@@ -1,9 +1,5 @@
1
1
  require "spring/watcher"
2
2
 
3
- # If the config/spring.rb contains requires for commands from other gems,
4
- # then we need to be under bundler.
5
- require "bundler/setup"
6
-
7
3
  module Spring
8
4
  @commands = {}
9
5
 
@@ -23,218 +19,15 @@ module Spring
23
19
  commands.fetch name
24
20
  end
25
21
 
26
- module Commands
27
- class Command
28
- @preloads = []
29
-
30
- def self.preloads
31
- @preloads ||= superclass.preloads.dup
32
- end
33
-
34
- def self.preloads=(val)
35
- @preloads = val
36
- end
37
-
38
- def preloads
39
- self.class.preloads
40
- end
41
-
42
- def setup
43
- preload_files
44
- end
45
-
46
- private
47
-
48
- def preload_files
49
- preloads.each do |file|
50
- begin
51
- require file
52
- rescue LoadError => e
53
- $stderr.puts <<-MESSAGE
54
- The #{self.class} command tried to preload #{file} but could not find it.
55
- You can configure what to preload in your `config/spring.rb` with:
56
- #{self.class}.preloads = %w(files to preload)
57
- MESSAGE
58
- end
59
- end
60
- end
61
- end
62
-
63
- class TestUnit < Command
64
- preloads << "test_helper"
65
-
66
- def env(*)
67
- "test"
68
- end
69
-
70
- def setup
71
- $LOAD_PATH.unshift "test"
72
- super
73
- end
74
-
75
- def call(args)
76
- if args.empty?
77
- args = ['test']
78
- end
79
-
80
- ARGV.replace args
81
- args.each do |arg|
82
- path = File.expand_path(arg)
83
- if File.directory?(path)
84
- Dir[File.join path, "**", "*_test.rb"].each { |f| require f }
85
- else
86
- require path
87
- end
88
- end
89
- end
90
-
91
- def description
92
- "Execute a Test::Unit test."
93
- end
94
- end
95
- Spring.register_command "testunit", TestUnit.new
96
-
97
- class RSpec < Command
98
- preloads << "spec_helper"
99
-
100
- def env(*)
101
- "test"
102
- end
103
-
104
- def setup
105
- $LOAD_PATH.unshift "spec"
106
- require 'rspec/core'
107
- ::RSpec::Core::Runner.disable_autorun!
108
- super
109
- end
110
-
111
- def call(args)
112
- $0 = "rspec"
113
- Kernel.exit ::RSpec::Core::Runner.run(args)
114
- end
115
-
116
- def description
117
- "Execute an RSpec spec."
118
- end
119
- end
120
- Spring.register_command "rspec", RSpec.new
121
-
122
- class Cucumber < Command
123
- def env(*)
124
- "test"
125
- end
22
+ require "spring/commands/rails"
23
+ require "spring/commands/rake"
24
+ require "spring/commands/testunit"
25
+ require "spring/commands/rspec"
26
+ require "spring/commands/cucumber"
126
27
 
127
- def setup
128
- super
129
- require 'cucumber'
130
- end
131
-
132
- def call(args)
133
- # Cucumber's execute funtion returns `true` if any of the steps failed or
134
- # some other error occured.
135
- Kernel.exit(1) if ::Cucumber::Cli::Main.execute(args)
136
- end
137
-
138
- def description
139
- "Execute a Cucumber feature."
140
- end
141
- end
142
- Spring.register_command "cucumber", Cucumber.new
143
-
144
- class Rake < Command
145
- class << self
146
- attr_accessor :environment_matchers
147
- end
148
-
149
- self.environment_matchers = {
150
- /^(test|spec|cucumber)($|:)/ => "test"
151
- }
152
-
153
- def env(args)
154
- self.class.environment_matchers.each do |matcher, environment|
155
- return environment if matcher === args.first
156
- end
157
- nil
158
- end
159
-
160
- def setup
161
- super
162
- require "rake"
163
- end
164
-
165
- def call(args)
166
- ARGV.replace args
167
- ::Rake.application.run
168
- end
169
-
170
- def description
171
- "Run a rake task."
172
- end
173
- end
174
- Spring.register_command "rake", Rake.new
175
-
176
- class RailsConsole < Command
177
- def env(args)
178
- args.first if args.first && !args.first.index("-")
179
- end
180
-
181
- def setup
182
- require "rails/commands/console"
183
- end
184
-
185
- def call(args)
186
- ARGV.replace args
187
- ::Rails::Console.start(::Rails.application)
188
- end
189
-
190
- def description
191
- nil
192
- end
193
- end
194
- Spring.register_command "rails_console", RailsConsole.new
195
-
196
- class RailsGenerate < Command
197
- def setup
198
- super
199
- Rails.application.load_generators
200
- end
201
-
202
- def call(args)
203
- ARGV.replace args
204
- require "rails/commands/generate"
205
- end
206
-
207
- def description
208
- nil
209
- end
210
- end
211
- Spring.register_command "rails_generate", RailsGenerate.new
212
-
213
- class RailsRunner < Command
214
- def env(tail)
215
- previous_option = nil
216
- tail.reverse.each do |option|
217
- case option
218
- when /--environment=(\w+)/ then return $1
219
- when '-e' then return previous_option
220
- end
221
- previous_option = option
222
- end
223
- nil
224
- end
225
-
226
- def call(args)
227
- Object.const_set(:APP_PATH, Rails.root.join('config/application'))
228
- ARGV.replace args
229
- require "rails/commands/runner"
230
- end
231
-
232
- def description
233
- nil
234
- end
235
- end
236
- Spring.register_command "rails_runner", RailsRunner.new
237
- end
28
+ # If the config/spring.rb contains requires for commands from other gems,
29
+ # then we need to be under bundler.
30
+ require "bundler/setup"
238
31
 
239
32
  # Load custom commands, if any.
240
33
  # needs to be at the end to allow modification of existing commands.