spring 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6828395a6b2b9a2d02ec15c9baba9305f36dbec9
4
- data.tar.gz: 62af73ac2056ca5a62ed440c0e9220f115c82830
3
+ metadata.gz: 0bae3c5f77134086e25e77df5d700895438e16ba
4
+ data.tar.gz: 882c5139fed3fe573bb75136e683ca8ee3744069
5
5
  SHA512:
6
- metadata.gz: 73d982d8d66de05071338ea45fd59b042c5f05a5cb2eb32a10143777e0ec8e120a8b0ecd6d02e18570ee8515b4c18079dc67f12a74c5523f5f6586e93ba3b54c
7
- data.tar.gz: 54cc11c7135f91337199ee65d4062516ceec762c87f943bdb823b58b646e10d16d48cc5248b33cabcf68b517319fb7397c469e1d3ce3f75a378152cca30256db
6
+ metadata.gz: c5d7a1655a09f56c5663024af741c3c58fe9542418603a59dddb0c19ee24203a1527911a4626f6a5eedd5daf5b6e19b1107582fdc2c7528563af1878034cf1a7
7
+ data.tar.gz: d143cad1d9b6f15440d80aa300b566a4fa19c0c90deada7fa627e3b230f9199ed56eae911c0005fa2ff83814bf3e66190777a42e0bb4cf5ee6d997df9d06b297
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ spec/reports
16
16
  test/tmp
17
17
  test/version_tmp
18
18
  tmp
19
+ .ruby-version
@@ -1,3 +1,12 @@
1
+ ## 1.2.0
2
+
3
+ * Accept -e and --environment options for `rails console`.
4
+ * Watch `config/secrets.yml` by default. #289 - @morgoth
5
+ * Change monkey-patched `Kernel.raise` from public to private (to match default Ruby behavior) #351 - @mattbrictson
6
+ * Let application_id also respect RUBY_VERSION for the use case of switching between Ruby versions for a given Rails app - @methodmissing
7
+ * Extract the 'listen' watcher to a separate `spring-watcher-listen`
8
+ gem. This allows it to be developed/maintained separately.
9
+
1
10
  ## 1.1.3
2
11
 
3
12
  * The `rails runner` command no longer passes environment switches to
@@ -1,3 +1,8 @@
1
+ # Don't use the issue tracker to ask questions
2
+
3
+ Please use Stack Overflow or similar. If you subsequently feel that the
4
+ documentation is inadequate then plase submit a pull request to fix it.
5
+
1
6
  # Contributing guide
2
7
 
3
8
  ## Getting set up
data/Gemfile CHANGED
@@ -2,5 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in spring.gemspec
4
4
  gemspec
5
-
6
- gem 'listen', "~> 1.0", :require => false
data/README.md CHANGED
@@ -7,8 +7,6 @@ Spring is a Rails application preloader. It speeds up development by
7
7
  keeping your application running in the background so you don't need to
8
8
  boot it every time you run a test, rake task or migration.
9
9
 
10
- **Upgrading to 1.1? It's recommended to run `bundle exec spring binstub --all` to regenerate your binstubs.**
11
-
12
10
  ## Features
13
11
 
14
12
  * Totally automatic; no need to explicitly start and stop the background process
@@ -61,8 +59,10 @@ will just be silently ignored and the lines after it will be executed as
61
59
  normal.
62
60
 
63
61
  If you don't want to prefix every command you type with `bin/`, you
64
- can [use direnv](https://github.com/zimbatm/direnv) to automatically add
65
- `./bin` to your `PATH` when you `cd` into your application.
62
+ can [use direnv](https://github.com/zimbatm/direnv#the-stdlib) to
63
+ automatically add `./bin` to your `PATH` when you `cd` into your application.
64
+ Simply create an `.envrc` file with the command `PATH_add bin` in your
65
+ Rails directory.
66
66
 
67
67
  ### Usage
68
68
 
@@ -179,6 +179,17 @@ To remove spring:
179
179
  * 'Unspring' your bin/ executables: `bin/spring binstub --remove --all`
180
180
  * Remove spring from your Gemfile
181
181
 
182
+ ### Deployment
183
+
184
+ You must not install Spring on your production environment. To prevent it from
185
+ being installed, provide the `--without development test` argument to the
186
+ `bundle install` command which is used to install gems on your production
187
+ machines:
188
+
189
+ ```
190
+ $ bundle install --without development test
191
+ ```
192
+
182
193
  ## Commands
183
194
 
184
195
  ### `rake`
@@ -333,13 +344,10 @@ Spring.watch "config/some_config_file.yml"
333
344
 
334
345
  By default Spring polls the filesystem for changes once every 0.2 seconds. This
335
346
  method requires zero configuration, but if you find that it's using too
336
- much CPU, then you can turn on event-based file system listening:
337
-
338
- ```ruby
339
- Spring.watch_method = :listen
340
- ```
341
-
342
- You may need to add the [`listen` gem](https://github.com/guard/listen) to your `Gemfile`.
347
+ much CPU, then you can use event-based file system listening by
348
+ installing the
349
+ [spring-watcher-listen](https://github.com/jonleighton/spring-watcher-listen)
350
+ gem.
343
351
 
344
352
  ## Troubleshooting
345
353
 
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ namespace :test do
10
10
 
11
11
  Rake::TestTask.new(:acceptance) do |t|
12
12
  t.libs << "test"
13
- t.test_files = FileList["test/acceptance/*_test.rb"]
13
+ t.test_files = FileList["test/acceptance_test.rb"]
14
14
  t.verbose = true
15
15
  end
16
16
 
@@ -108,6 +108,9 @@ module Spring
108
108
  if defined?(Rails) && Rails.application
109
109
  watcher.add Rails.application.paths["config/initializers"]
110
110
  watcher.add Rails.application.paths["config/database"]
111
+ if secrets_path = Rails.application.paths["config/secrets"]
112
+ watcher.add secrets_path
113
+ end
111
114
  end
112
115
  end
113
116
 
@@ -267,6 +270,7 @@ module Spring
267
270
  end
268
271
  end
269
272
  end
273
+ private :raise
270
274
  end
271
275
  end
272
276
 
@@ -36,7 +36,7 @@ unless defined?(Spring)
36
36
  require "rubygems"
37
37
  require "bundler"
38
38
 
39
- if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ spring \((.*?)\)$.*?^$/m)
39
+ if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)
40
40
  ENV["GEM_PATH"] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR)
41
41
  ENV["GEM_HOME"] = ""
42
42
  Gem.paths = ENV
@@ -32,8 +32,17 @@ module Spring
32
32
  # then we need to be under bundler.
33
33
  require "bundler/setup"
34
34
 
35
- Gem::Specification.map(&:name).grep(/^spring-commands-/).each do |command|
36
- require command
35
+ # Auto-require any spring extensions which are in the Gemfile
36
+ Gem::Specification.map(&:name).grep(/^spring-/).each do |command|
37
+ begin
38
+ require command
39
+ rescue LoadError => error
40
+ if error.message.include?(command)
41
+ require command.gsub("-", "/")
42
+ else
43
+ raise
44
+ end
45
+ end
37
46
  end
38
47
 
39
48
  config = File.expand_path("./config/spring.rb")
@@ -13,7 +13,19 @@ module Spring
13
13
 
14
14
  class RailsConsole < Rails
15
15
  def env(args)
16
- args.first if args.first && !args.first.index("-")
16
+ return args.first if args.first && !args.first.index("-")
17
+
18
+ environment = nil
19
+
20
+ args.each.with_index do |arg, i|
21
+ if arg =~ /--environment=(\w+)/
22
+ environment = $1
23
+ elsif i > 0 && args[i - 1] == "-e"
24
+ environment = arg
25
+ end
26
+ end
27
+
28
+ environment
17
29
  end
18
30
 
19
31
  def command_name
@@ -32,13 +32,13 @@ module Spring
32
32
  end
33
33
 
34
34
  def tmp_path
35
- path = Pathname.new(Dir.tmpdir + "/spring")
35
+ path = Pathname.new(File.join(ENV['XDG_RUNTIME_DIR'] || Dir.tmpdir, "spring"))
36
36
  FileUtils.mkdir_p(path) unless path.exist?
37
37
  path
38
38
  end
39
39
 
40
40
  def application_id
41
- Digest::MD5.hexdigest(project_root.to_s)
41
+ Digest::MD5.hexdigest(RUBY_VERSION + project_root.to_s)
42
42
  end
43
43
 
44
44
  def socket_path
@@ -25,7 +25,7 @@ module Spring
25
25
  if Process.respond_to?(:getsid)
26
26
  # Ruby 2
27
27
  Process.getsid
28
- elsif defined?(Fiddle)
28
+ elsif defined?(Fiddle) and defined?(DL)
29
29
  # Ruby 1.9.3 compiled with libffi support
30
30
  fiddle_func.call(0)
31
31
  else
@@ -0,0 +1,15 @@
1
+ require "active_support/test_case"
2
+
3
+ module Spring
4
+ module Test
5
+ class << self
6
+ attr_accessor :root
7
+ end
8
+
9
+ require "spring/test/application"
10
+ require "spring/test/application_generator"
11
+ require "spring/test/rails_version"
12
+ require "spring/test/watcher_test"
13
+ require "spring/test/acceptance_test"
14
+ end
15
+ end
@@ -0,0 +1,333 @@
1
+ # encoding: utf-8
2
+
3
+ require "io/wait"
4
+ require "timeout"
5
+ require "spring/sid"
6
+ require "spring/client"
7
+
8
+ module Spring
9
+ module Test
10
+ class AcceptanceTest < ActiveSupport::TestCase
11
+ runnables.delete self # prevent Minitest running this class
12
+
13
+ DEFAULT_SPEEDUP = 0.8
14
+
15
+ def rails_version
16
+ ENV['RAILS_VERSION'] || '~> 4.0.0'
17
+ end
18
+
19
+ # Extension point for spring-watchers-listen
20
+ def generator_klass
21
+ Spring::Test::ApplicationGenerator
22
+ end
23
+
24
+ def generator
25
+ @@generator ||= generator_klass.new(rails_version)
26
+ end
27
+
28
+ def app
29
+ @app ||= Spring::Test::Application.new("#{Spring::Test.root}/apps/tmp")
30
+ end
31
+
32
+ def assert_output(artifacts, expected)
33
+ expected.each do |stream, output|
34
+ assert artifacts[stream].include?(output),
35
+ "expected #{stream} to include '#{output}'.\n\n#{app.debug(artifacts)}"
36
+ end
37
+ end
38
+
39
+ def assert_success(command, expected_output = nil)
40
+ artifacts = app.run(*Array(command))
41
+ assert artifacts[:status].success?, "expected successful exit status\n\n#{app.debug(artifacts)}"
42
+ assert_output artifacts, expected_output if expected_output
43
+ end
44
+
45
+ def assert_failure(command, expected_output = nil)
46
+ artifacts = app.run(*Array(command))
47
+ assert !artifacts[:status].success?, "expected unsuccessful exit status\n\n#{app.debug(artifacts)}"
48
+ assert_output artifacts, expected_output if expected_output
49
+ end
50
+
51
+ def assert_speedup(ratio = DEFAULT_SPEEDUP)
52
+ if ENV['CI']
53
+ yield
54
+ else
55
+ app.with_timing do
56
+ yield
57
+ assert app.timing_ratio < ratio, "#{app.last_time} was not less than #{ratio} of #{app.first_time}"
58
+ end
59
+ end
60
+ end
61
+
62
+ setup do
63
+ generator.generate_if_missing
64
+ generator.install_spring
65
+ generator.copy_to(app.root)
66
+ end
67
+
68
+ teardown do
69
+ app.stop_spring
70
+ end
71
+
72
+ test "basic" do
73
+ assert_speedup do
74
+ 2.times { app.run app.spring_test_command }
75
+ end
76
+ end
77
+
78
+ test "help message when called without arguments" do
79
+ assert_success "bin/spring", stdout: 'Usage: spring COMMAND [ARGS]'
80
+ end
81
+
82
+ test "test changes are picked up" do
83
+ assert_speedup do
84
+ assert_success app.spring_test_command, stdout: "0 failures"
85
+
86
+ File.write(app.test, app.test.read.sub("get :index", "raise 'omg'"))
87
+ assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
88
+ end
89
+ end
90
+
91
+ test "code changes are picked up" do
92
+ assert_speedup do
93
+ assert_success app.spring_test_command, stdout: "0 failures"
94
+
95
+ File.write(app.controller, app.controller.read.sub("@posts = Post.all", "raise 'omg'"))
96
+ assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
97
+ end
98
+ end
99
+
100
+ test "code changes in pre-referenced app files are picked up" do
101
+ File.write(app.path("config/initializers/load_posts_controller.rb"), "PostsController\n")
102
+
103
+ assert_speedup do
104
+ assert_success app.spring_test_command, stdout: "0 failures"
105
+
106
+ File.write(app.controller, app.controller.read.sub("@posts = Post.all", "raise 'omg'"))
107
+ assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
108
+ end
109
+ end
110
+
111
+ test "app gets reloaded when preloaded files change" do
112
+ assert_success app.spring_test_command
113
+
114
+ File.write(app.application_config, app.application_config.read + <<-CODE)
115
+ class Foo
116
+ def self.omg
117
+ raise "omg"
118
+ end
119
+ end
120
+ CODE
121
+ File.write(app.test, app.test.read.sub("get :index", "Foo.omg"))
122
+
123
+ app.await_reload
124
+ assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
125
+ end
126
+
127
+ test "app recovers when a boot-level error is introduced" do
128
+ config = app.application_config.read
129
+
130
+ assert_success app.spring_test_command
131
+
132
+ File.write(app.application_config, "#{config}\nomg")
133
+ app.await_reload
134
+
135
+ assert_failure app.spring_test_command
136
+
137
+ File.write(app.application_config, config)
138
+ assert_success app.spring_test_command
139
+ end
140
+
141
+ test "stop command kills server" do
142
+ app.run app.spring_test_command
143
+ assert app.spring_env.server_running?, "The server should be running but it isn't"
144
+
145
+ assert_success "bin/spring stop"
146
+ assert !app.spring_env.server_running?, "The server should not be running but it is"
147
+ end
148
+
149
+ test "custom commands" do
150
+ File.write(app.spring_config, <<-CODE)
151
+ class CustomCommand
152
+ def call
153
+ puts "omg"
154
+ end
155
+
156
+ def exec_name
157
+ "rake"
158
+ end
159
+ end
160
+
161
+ Spring.register_command "custom", CustomCommand.new
162
+ CODE
163
+
164
+ assert_success "bin/spring custom", stdout: "omg"
165
+
166
+ assert_success "bin/spring binstub custom"
167
+ assert_success "bin/custom", stdout: "omg"
168
+
169
+ app.env["DISABLE_SPRING"] = "1"
170
+ assert_success %{bin/custom -e 'puts "foo"'}, stdout: "foo"
171
+ end
172
+
173
+ test "binstub" do
174
+ assert_success "bin/rails server --help", stdout: "Usage: rails server" # rails command fallback
175
+
176
+ assert_success "#{app.spring} binstub rake", stdout: "bin/rake: spring already present"
177
+
178
+ assert_success "#{app.spring} binstub --remove rake", stdout: "bin/rake: spring removed"
179
+ assert !app.path("bin/rake").read.include?(Spring::Client::Binstub::LOADER)
180
+ assert_success "bin/rake -T", stdout: "rake db:migrate"
181
+ end
182
+
183
+ test "binstub when spring is uninstalled" do
184
+ app.run! "gem uninstall --ignore-dependencies spring"
185
+ File.write(app.gemfile, app.gemfile.read.gsub(/gem 'spring.*/, ""))
186
+ assert_success "bin/rake -T", stdout: "rake db:migrate"
187
+ end
188
+
189
+ test "binstub upgrade" do
190
+ File.write(app.path("bin/rake"), <<CODE)
191
+ #!/usr/bin/env ruby
192
+
193
+ if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?
194
+ exec "bundle", "exec", "rake", *ARGV
195
+ else
196
+ ARGV.unshift "rake"
197
+ load Gem.bin_path("spring", "spring")
198
+ end
199
+ CODE
200
+
201
+ File.write(app.path("bin/rails"), <<CODE)
202
+ #!/usr/bin/env ruby
203
+
204
+ if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?
205
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
206
+ require_relative '../config/boot'
207
+ require 'rails/commands'
208
+ else
209
+ ARGV.unshift "rails"
210
+ load Gem.bin_path("spring", "spring")
211
+ end
212
+ CODE
213
+
214
+ assert_success "bin/spring binstub --all", stdout: "upgraded"
215
+
216
+ assert_equal app.path("bin/rake").read, <<CODE
217
+ #!/usr/bin/env ruby
218
+ #{Spring::Client::Binstub::LOADER.strip}
219
+ require 'bundler/setup'
220
+ load Gem.bin_path('rake', 'rake')
221
+ CODE
222
+
223
+ assert_equal app.path("bin/rails").read, <<CODE
224
+ #!/usr/bin/env ruby
225
+ #{Spring::Client::Binstub::LOADER.strip}
226
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
227
+ require_relative '../config/boot'
228
+ require 'rails/commands'
229
+ CODE
230
+ end
231
+
232
+ test "after fork callback" do
233
+ File.write(app.spring_config, "Spring.after_fork { puts '!callback!' }")
234
+ assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"
235
+ end
236
+
237
+ test "global config file evaluated" do
238
+ File.write("#{app.user_home}/.spring.rb", "Spring.after_fork { puts '!callback!' }")
239
+ assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"
240
+ end
241
+
242
+ test "missing config/application.rb" do
243
+ app.application_config.delete
244
+ assert_failure "bin/rake -T", stderr: "unable to find your config/application.rb"
245
+ end
246
+
247
+ test "piping" do
248
+ assert_success "bin/rake -T | grep db", stdout: "rake db:migrate"
249
+ end
250
+
251
+ test "status" do
252
+ assert_success "bin/spring status", stdout: "Spring is not running"
253
+ assert_success "bin/rails runner ''"
254
+ assert_success "bin/spring status", stdout: "Spring is running"
255
+ end
256
+
257
+ test "runner command sets Rails environment from command-line options" do
258
+ assert_success "bin/rails runner -e test 'puts Rails.env'", stdout: "test"
259
+ assert_success "bin/rails runner --environment=test 'puts Rails.env'", stdout: "test"
260
+ end
261
+
262
+ test "forcing rails env via environment variable" do
263
+ app.env['RAILS_ENV'] = 'test'
264
+ assert_success "bin/rake -p 'Rails.env'", stdout: "test"
265
+ end
266
+
267
+ test "setting env vars with rake" do
268
+ File.write(app.path("lib/tasks/env.rake"), <<-'CODE')
269
+ task :print_rails_env => :environment do
270
+ puts Rails.env
271
+ end
272
+
273
+ task :print_env do
274
+ ENV.each { |k, v| puts "#{k}=#{v}" }
275
+ end
276
+
277
+ task(:default).clear.enhance [:print_rails_env]
278
+ CODE
279
+
280
+ assert_success "bin/rake RAILS_ENV=test print_rails_env", stdout: "test"
281
+ assert_success "bin/rake FOO=bar print_env", stdout: "FOO=bar"
282
+ assert_success "bin/rake", stdout: "test"
283
+ end
284
+
285
+ test "changing the Gemfile works" do
286
+ assert_success %(bin/rails runner 'require "sqlite3"')
287
+
288
+ File.write(app.gemfile, app.gemfile.read.sub(%{gem 'sqlite3'}, %{# gem 'sqlite3'}))
289
+ app.await_reload
290
+
291
+ assert_failure %(bin/rails runner 'require "sqlite3"'), stderr: "sqlite3"
292
+ end
293
+
294
+ test "changing the Gemfile works when spring calls into itself" do
295
+ File.write(app.path("script.rb"), <<-CODE)
296
+ gemfile = Rails.root.join("Gemfile")
297
+ File.write(gemfile, "\#{gemfile.read}gem 'devise'\\n")
298
+ Bundler.with_clean_env do
299
+ system(#{app.env.inspect}, "bundle install")
300
+ end
301
+ output = `\#{Rails.root.join('bin/rails')} runner 'require "devise"; puts "done";'`
302
+ exit output == "done\n"
303
+ CODE
304
+
305
+ assert_success [%(bin/rails runner 'load Rails.root.join("script.rb")'), timeout: 60]
306
+ end
307
+
308
+ test "changing the environment between runs" do
309
+ File.write(app.application_config, "#{app.application_config.read}\nENV['BAR'] = 'bar'")
310
+
311
+ app.env["OMG"] = "1"
312
+ app.env["FOO"] = "1"
313
+ app.env["RUBYOPT"] = "-rubygems"
314
+
315
+ assert_success %(bin/rails runner 'p ENV["OMG"]'), stdout: "1"
316
+ assert_success %(bin/rails runner 'p ENV["BAR"]'), stdout: "bar"
317
+ assert_success %(bin/rails runner 'p ENV.key?("BUNDLE_GEMFILE")'), stdout: "true"
318
+ assert_success %(bin/rails runner 'p ENV["RUBYOPT"]'), stdout: "bundler"
319
+
320
+ app.env["OMG"] = "2"
321
+ app.env.delete "FOO"
322
+
323
+ assert_success %(bin/rails runner 'p ENV["OMG"]'), stdout: "2"
324
+ assert_success %(bin/rails runner 'p ENV.key?("FOO")'), stdout: "false"
325
+ end
326
+
327
+ test "Kernel.raise remains private" do
328
+ expr = "p Kernel.private_instance_methods.include?(:raise)"
329
+ assert_success %(bin/rails runner '#{expr}'), stdout: "true"
330
+ end
331
+ end
332
+ end
333
+ end