Skip to content

Commit c6471b4

Browse files
committed
Ensure an application has the correct ENV
1 parent c579428 commit c6471b4

File tree

3 files changed

+66
-38
lines changed

3 files changed

+66
-38
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## Next Version
22

3+
* Ensure an application is started with the correct ENV - @eval
34
* Accept -e and --environment options for `rails console`.
45
* Watch `config/secrets.yml` by default. #289 - @morgoth
56
* Custom Spring commands that implement `#binstub_prelude` will have that

lib/spring/application.rb

+53-38
Original file line numberDiff line numberDiff line change
@@ -133,73 +133,88 @@ def run
133133
end
134134
end
135135

136+
def with_env_vars(env)
137+
# Allowed are keys currently not in ENV...
138+
allowed_keys = env.keys - ENV.keys
139+
# ...and ENV-keys whose values have not changed since the start of spring
140+
allowed_keys += original_env.select {|k, v| ENV[k] == v }.keys
141+
# never allowed:
142+
allowed_keys -= %w(RUBYOPT RUBY_ROOT BUNDLE_GEMFILE GEM_ROOT GEM_HOME GEM_PATH)
143+
allowed_keys.uniq!
144+
145+
allowed_keys.each{|k| ENV[k] = env[k] }
146+
147+
yield
148+
ensure
149+
allowed_keys.each do |k|
150+
original_env.has_key?(k) ? ENV[k] = original_env[k] : ENV.delete(k)
151+
end
152+
end
153+
136154
def serve(client)
137155
log "got client"
138156
manager.puts
139157

140158
stdout, stderr, stdin = streams = 3.times.map { client.recv_io }
141159
[STDOUT, STDERR, STDIN].zip(streams).each { |a, b| a.reopen(b) }
142160

143-
preload unless preloaded?
161+
client_args, client_env = JSON.load(client.read(client.gets.to_i)).values_at("args", "env")
144162

145-
args, env = JSON.load(client.read(client.gets.to_i)).values_at("args", "env")
146-
command = Spring.command(args.shift)
147-
148-
connect_database
149-
setup command
150-
151-
if Rails.application.reloaders.any?(&:updated?)
152-
ActionDispatch::Reloader.cleanup!
153-
ActionDispatch::Reloader.prepare!
154-
end
163+
@pid = nil
164+
with_env_vars(client_env) do
165+
preload unless preloaded?
166+
command = Spring.command(client_args.shift)
155167

156-
pid = fork {
157-
IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
158-
trap("TERM", "DEFAULT")
168+
connect_database
169+
setup command
159170

160-
ARGV.replace(args)
161-
$0 = command.process_title
171+
if Rails.application.reloaders.any?(&:updated?)
172+
ActionDispatch::Reloader.cleanup!
173+
ActionDispatch::Reloader.prepare!
174+
end
162175

163-
# Delete all env vars which are unchanged from before spring started
164-
original_env.each { |k, v| ENV.delete k if ENV[k] == v }
176+
@pid = fork {
177+
IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
178+
trap("TERM", "DEFAULT")
165179

166-
# Load in the current env vars, except those which *were* changed when spring started
167-
env.each { |k, v| ENV[k] ||= v }
180+
ARGV.replace(client_args)
181+
$0 = command.process_title
168182

169-
# requiring is faster, so if config.cache_classes was true in
170-
# the environment's config file, then we can respect that from
171-
# here on as we no longer need constant reloading.
172-
if @original_cache_classes
173-
ActiveSupport::Dependencies.mechanism = :require
174-
Rails.application.config.cache_classes = true
175-
end
183+
# requiring is faster, so if config.cache_classes was true in
184+
# the environment's config file, then we can respect that from
185+
# here on as we no longer need constant reloading.
186+
if @original_cache_classes
187+
ActiveSupport::Dependencies.mechanism = :require
188+
Rails.application.config.cache_classes = true
189+
end
176190

177-
connect_database
178-
srand
191+
connect_database
192+
srand
179193

180-
invoke_after_fork_callbacks
181-
shush_backtraces
194+
invoke_after_fork_callbacks
195+
shush_backtraces
182196

183-
command.call
184-
}
197+
command.call
198+
}
199+
end
185200

186201
disconnect_database
187202
reset_streams
188203

189-
log "forked #{pid}"
190-
manager.puts pid
204+
log "forked #{@pid}"
205+
manager.puts @pid
191206

192-
wait pid, streams, client
207+
wait @pid, streams, client
193208
rescue Exception => e
194209
log "exception: #{e}"
195-
manager.puts unless pid
210+
manager.puts unless @pid
196211

197212
if streams && !e.is_a?(SystemExit)
198213
print_exception(stderr, e)
199214
streams.each(&:close)
200215
end
201216

202-
client.puts(1) if pid
217+
client.puts(1) if @pid
203218
client.close
204219
end
205220

test/acceptance/app_test.rb

+12
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,18 @@ def binstub_prelude
291291
assert_success "bin/rake -p 'Rails.env'", stdout: "test"
292292
end
293293

294+
test "config via environment variable" do
295+
File.write(app.path('config/initializers/set_foo.rb'), <<-CONFIG)
296+
Rails.application.config.foo = !!ENV['FOO']
297+
CONFIG
298+
299+
app.env['FOO'] = '1'
300+
assert_success "bin/rails runner -e test 'p Rails.application.config.foo'", stdout: "true"
301+
302+
app.env['FOO'] = nil
303+
assert_success "bin/rails runner -e development 'p Rails.application.config.foo'", stdout: "false"
304+
end
305+
294306
test "setting env vars with rake" do
295307
File.write(app.path("lib/tasks/env.rake"), <<-'CODE')
296308
task :print_rails_env => :environment do

0 commit comments

Comments
 (0)