• Stars
    star
    2,782
  • Rank 15,705 (Top 0.4 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 11 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Rails application preloader

Spring

Build Status Gem Version

Spring is a Rails application preloader. It speeds up development by keeping your application running in the background, so you don't need to boot it every time you run a test, rake task or migration.

Features

  • Totally automatic; no need to explicitly start and stop the background process
  • Reloads your application code on each run
  • Restarts your application when configs / initializers / gem dependencies are changed

Compatibility

  • Ruby versions: MRI 2.7, MRI 3.0, MRI 3.1, MRI 3.2
  • Rails versions: 6.0, 6.1, 7.0
  • Bundler v2.1+

Spring makes extensive use of Process.fork, so won't be able to provide a speed up on platforms which don't support forking (Windows, JRuby).

Walkthrough

Setup

Add Spring to your Gemfile:

gem "spring", group: :development

(Note: using gem "spring", git: "..." won't work and is not a supported way of using Spring.)

It's recommended to 'springify' the executables in your bin/ directory:

$ bundle install
$ bundle exec spring binstub --all

This generates a bin/spring executable, and inserts a small snippet of code into relevant existing executables. The snippet looks like this:

begin
  load File.expand_path('../spring', __FILE__)
rescue LoadError => e
  raise unless e.message.include?('spring')
end

On platforms where Spring is installed and supported, this snippet hooks Spring into the execution of commands. In other cases, the snippet will just be silently ignored, and the lines after it will be executed as normal.

If you don't want to prefix every command you type with bin/, you can use direnv to automatically add ./bin to your PATH when you cd into your application. Simply create an .envrc file with the command PATH_add bin in your Rails directory.

Enable reloading

Spring reloads application code, and therefore needs the application to have reloading enabled.

Ensure that config.enable_reloading is true in the environments that Spring manages. That setting is typically configured in config/environments/*.rb. In particular, make sure it is true for the test environment.

Note: in versions of Rails before 7.1, the setting is called cache_classes, and it needs to be false for Spring to work.

Usage

For this walkthrough I've generated a new Rails application, and run rails generate scaffold post name:string.

Let's run a test:

$ time bin/rake test test/controllers/posts_controller_test.rb
Running via Spring preloader in process 2734
Run options:

# Running tests:

.......

Finished tests in 0.127245s, 55.0121 tests/s, 78.5887 assertions/s.

7 tests, 10 assertions, 0 failures, 0 errors, 0 skips

real    0m2.165s
user    0m0.281s
sys     0m0.066s

That wasn't particularly fast because it was the first run, so Spring had to boot the application. It's now running:

$ bin/spring status
Spring is running:

26150 spring server | spring-demo-app | started 3 secs ago
26155 spring app    | spring-demo-app | started 3 secs ago | test mode

The next run is faster:

$ time bin/rake test test/controllers/posts_controller_test.rb
Running via Spring preloader in process 8352
Run options:

# Running tests:

.......

Finished tests in 0.176896s, 39.5714 tests/s, 56.5305 assertions/s.

7 tests, 10 assertions, 0 failures, 0 errors, 0 skips

real    0m0.610s
user    0m0.276s
sys     0m0.059s

If we edit any of the application files, or test files, the changes will be picked up on the next run without the background process having to restart. This works in exactly the same way as the code reloading which allows you to refresh your browser and instantly see changes during development.

But if we edit any of the files which were used to start the application (configs, initializers, your gemfile), the application needs to be fully restarted. This happens automatically.

Let's "edit" config/application.rb:

$ touch config/application.rb
$ bin/spring status
Spring is running:

26150 spring server | spring-demo-app | started 36 secs ago
26556 spring app    | spring-demo-app | started 1 sec ago | test mode

The application detected that config/application.rb changed and automatically restarted itself.

If we run a command that uses a different environment, then that environment gets booted up:

$ bin/rake routes
Running via Spring preloader in process 2363
    posts GET    /posts(.:format)          posts#index
          POST   /posts(.:format)          posts#create
 new_post GET    /posts/new(.:format)      posts#new
edit_post GET    /posts/:id/edit(.:format) posts#edit
     post GET    /posts/:id(.:format)      posts#show
          PUT    /posts/:id(.:format)      posts#update
          DELETE /posts/:id(.:format)      posts#destroy

$ bin/spring status
Spring is running:

26150 spring server | spring-demo-app | started 1 min ago
26556 spring app    | spring-demo-app | started 42 secs ago | test mode
26707 spring app    | spring-demo-app | started 2 secs ago | development mode

There's no need to "shut down" Spring. This will happen automatically when you close your terminal. However, if you do want to do a manual shut down, use the stop command:

$ bin/spring stop
Spring stopped.

From within your code, you can check whether Spring is active with if defined?(Spring).

Removal

To remove Spring:

  • 'Unspring' your bin/ executables: bin/spring binstub --remove --all
  • Remove spring from your Gemfile

Deployment

You must not install Spring on your production environment. To prevent it from being installed, run the bundle config set without 'development test' before bundle install command which is used to install gems on your production machines:

$ bundle config set without 'development test'
$ bundle install

Commands

rake

Runs a rake task. Rake tasks run in the development environment by default. You can change this on the fly by using the RAILS_ENV environment variable. The environment is also configurable with the Spring::Commands::Rake.environment_matchers hash. This has sensible defaults, but if you need to match a specific task to a specific environment, you'd do it like this:

Spring::Commands::Rake.environment_matchers["perf_test"] = "test"
Spring::Commands::Rake.environment_matchers[/^perf/]     = "test"

# To change the environment when you run `rake` with no arguments
Spring::Commands::Rake.environment_matchers[:default] = "development"

rails console, rails generate, rails runner

These execute the rails command you already know and love. If you run a different sub command (e.g. rails server) then Spring will automatically pass it through to the underlying rails executable (without the speed-up).

Additional commands

You can add these to your Gemfile for additional commands:

Use without adding to bundle

If you don't want Spring-related code checked into your source repository, it's possible to use Spring without adding to your Gemfile. However, using Spring binstubs without adding Spring to the Gemfile is not supported.

To use Spring like this, do a gem install spring and then prefix commands with spring. For example, rather than running bin/rake -T, you'd run spring rake -T.

Temporarily disabling Spring

If you're using Spring binstubs, but temporarily don't want commands to run through Spring, set the DISABLE_SPRING environment variable.

Class reloading

Spring uses Rails' class reloading mechanism to keep your code up to date between test runs. This is the same mechanism which allows you to see changes during development when you refresh the page. However, you may never have used this mechanism with your test environment before, and this can cause problems.

It's important to realise that code reloading means that the constants in your application are different objects after files have changed:

$ bin/rails runner 'puts User.object_id'
70127987886040
$ touch app/models/user.rb
$ bin/rails runner 'puts User.object_id'
70127976764620

Suppose you have an initializer config/initializers/save_user_class.rb like so:

USER_CLASS = User

This saves off the first version of the User class, which will not be the same object as User after the code has been reloaded:

$ bin/rails runner 'puts User == USER_CLASS'
true
$ touch app/models/user.rb
$ bin/rails runner 'puts User == USER_CLASS'
false

So to avoid this problem, don't save off references to application constants in your initialization code.

Using Spring with a containerized development environment

As of Spring 1.7, there is some support for doing this. See this example repository for information about how to do it with Docker.

Configuration

Spring will read ~/.spring.rb and config/spring.rb for custom settings. Note that ~/.spring.rb is loaded before bundler, but config/spring.rb is loaded after bundler. So if you have any spring-commands-* gems installed that you want to be available in all projects without having to be added to the project's Gemfile, require them in your ~/.spring.rb.

config/spring_client.rb is also loaded before bundler and before a server process is started, it can be used to add new top-level commands.

Application root

Spring must know how to find your Rails application. If you have a normal app everything works out of the box. If you are working on a project with a special setup (an engine for example), you must tell Spring where your app is located:

Spring.application_root = './test/dummy'

Running code before forking

There is no Spring.before_fork callback. To run something before the fork, you can place it in ~/.spring.rb or config/spring.rb or in any of the files which get run when your application initializes, such as config/application.rb, config/environments/*.rb or config/initializers/*.rb.

Running code after forking

You might want to run code after Spring forked off the process but before the actual command is run. You might want to use an after_fork callback if you have to connect to an external service, do some general cleanup or set up dynamic configuration.

Spring.after_fork do
  # run arbitrary code
end

If you want to register multiple callbacks you can simply call Spring.after_fork multiple times with different blocks.

Watching files and directories

Spring will automatically detect file changes to any file loaded when the server boots. Changes will cause the affected environments to be restarted.

If there are additional files or directories which should trigger an application restart, you can specify them with Spring.watch:

Spring.watch "config/some_config_file.yml"

By default, Spring polls the filesystem for changes once every 0.2 seconds. This method requires zero configuration, but if you find that it's using too much CPU, then you can use event-based file system listening by installing the spring-watcher-listen gem.

Quiet output

To disable the "Running via Spring preloader" message which is shown each time a command runs:

Spring.quiet = true

You can also set the initial state of the quiet configuration option to true by setting the SPRING_QUIET environment variable before executing Spring. This is useful if you want to set quiet mode when invoking the Spring executable in a subprocess, and cannot or prefer not to set it programmatically via the Spring.quiet option in ~/.spring.rb or the app's config/spring.rb.

Environment variables

The following environment variables are used by Spring:

  • DISABLE_SPRING - If set, Spring will be bypassed, and your application will boot in a foreground process
  • SPRING_LOG - The path to a file which Spring will write log messages to.
  • SPRING_TMP_PATH - The directory where Spring should write its temporary files (a pidfile and a socket). By default, we use the XDG_RUNTIME_DIR environment variable, or else Dir.tmpdir, and then create a directory in that named spring-$UID. We don't use your Rails application's tmp/ directory because that may be on a filesystem which doesn't support UNIX sockets.
  • SPRING_APPLICATION_ID - Used to identify distinct Rails applications. By default, it is an MD5 hash of the current RUBY_VERSION, and the path to your Rails project root.
  • SPRING_SOCKET - The path which should be used for the UNIX socket which Spring uses to communicate with the long-running Spring server process. By default, this is SPRING_TMP_PATH/SPRING_APPLICATION_ID.
  • SPRING_PIDFILE - The path which should be used to store the pid of the long-running Spring server process. By default, this is related to the socket path; if the socket path is /foo/bar/spring.sock the pidfile will be /foo/bar/spring.pid.
  • SPRING_QUIET - If set, the initial state of the Spring.quiet configuration option will default to true.
  • SPRING_SERVER_COMMAND - The command to run to start up the Spring server when it is not already running. Defaults to spring _[version]_ server --background.

Troubleshooting

If you want to get more information about what Spring is doing, you can run Spring explicitly in a separate terminal:

$ spring server

Logging output will be printed to stdout. You can also send log output to a file with the SPRING_LOG environment variable.

More Repositories

1

rails

Ruby on Rails
Ruby
54,600
star
2

webpacker

Use Webpack to manage app-like JavaScript modules in Rails
Ruby
5,313
star
3

thor

Thor is a toolkit for building powerful command-line interfaces.
Ruby
5,066
star
4

jbuilder

Jbuilder: generate JSON objects with a Builder-style DSL
Ruby
4,298
star
5

jquery-ujs

Ruby on Rails unobtrusive scripting adapter for jQuery
JavaScript
2,610
star
6

rails-dev-box

A virtual machine for Ruby on Rails core development
Shell
2,049
star
7

tailwindcss-rails

Ruby
1,343
star
8

kredis

Higher-level data structures built on Redis
Ruby
1,341
star
9

activeresource

Connects business objects and REST web services
Ruby
1,309
star
10

strong_parameters

Taint and required checking for Action Pack and enforcement in Active Model
Ruby
1,271
star
11

docked

Running Rails from Docker for easy start to development
Dockerfile
1,262
star
12

globalid

Identify app models with a URI
Ruby
1,164
star
13

actioncable

Framework for real-time communication over websockets
1,087
star
14

importmap-rails

Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling.
Ruby
990
star
15

jquery-rails

A gem to automate using jQuery with Rails
Ruby
946
star
16

sprockets

Rack-based asset packaging system
Ruby
919
star
17

sass-rails

Ruby on Rails stylesheet engine for Sass
Ruby
858
star
18

exception_notification

NOTICE: official repository moved to https://github.com/smartinez87/exception_notification
Ruby
844
star
19

sdoc

Standalone sdoc generator
JavaScript
820
star
20

propshaft

Deliver assets for Rails
Ruby
785
star
21

jsbundling-rails

Bundle and transpile JavaScript in Rails with esbuild, rollup.js, or Webpack.
Ruby
778
star
22

rails-perftest

Benchmark and profile your Rails apps
Ruby
775
star
23

activejob

Declare job classes that can be run by a variety of queueing backends
Ruby
746
star
24

activestorage

Store files in Rails applications
734
star
25

solid_cache

A database-backed ActiveSupport::Cache::Store
Ruby
682
star
26

pjax_rails

PJAX integration for Rails
Ruby
670
star
27

actioncable-examples

Action Cable Examples
Ruby
663
star
28

cache_digests

Ruby
644
star
29

sprockets-rails

Sprockets Rails integration
Ruby
569
star
30

cssbundling-rails

Bundle and process CSS in Rails with Tailwind, PostCSS, and Sass via Node.js.
Ruby
539
star
31

activerecord-session_store

Active Record's Session Store extracted from Rails
Ruby
524
star
32

rails-observers

Rails observer (removed from core in Rails 4.0)
Ruby
513
star
33

execjs

Run JavaScript code from Ruby
Ruby
509
star
34

actiontext

Edit and display rich text in Rails applications
406
star
35

acts_as_list

NOTICE: official repository moved to https://github.com/swanandp/acts_as_list
Ruby
384
star
36

marcel

Find the mime type of files, examining file, filename and declared type
Ruby
369
star
37

request.js

JavaScript
356
star
38

actionpack-page_caching

Static page caching for Action Pack (removed from core in Rails 4.0)
Ruby
343
star
39

commands

Run Rake/Rails commands through the console
Ruby
338
star
40

ssl_requirement

NOTICE: official repository moved to https://github.com/retr0h/ssl_requirement
Ruby
315
star
41

rubocop-rails-omakase

Omakase Ruby styling for Rails
Ruby
310
star
42

rails-controller-testing

Brings back `assigns` and `assert_template` to your Rails tests
Ruby
295
star
43

rails-html-sanitizer

Ruby
294
star
44

open_id_authentication

NOTICE: official repository moved to https://github.com/Velir/open_id_authentication
Ruby
284
star
45

acts_as_tree

NOTICE: official repository moved to https://github.com/amerine/acts_as_tree
Ruby
279
star
46

actionpack-action_caching

Action caching for Action Pack (removed from core in Rails 4.0)
Ruby
260
star
47

in_place_editing

NOTICE: official repository moved to https://github.com/amerine/in_place_editing
Ruby
230
star
48

protected_attributes

Protect attributes from mass-assignment in ActiveRecord models.
Ruby
230
star
49

journey

A router for rails
Ruby
221
star
50

auto_complete

NOTICE: official repository moved to https://github.com/david-kerins/auto_complete
Ruby
211
star
51

dartsass-rails

Integrate Dart Sass with the asset pipeline in Rails
Ruby
192
star
52

dynamic_form

NOTICE: official repository moved to https://github.com/joelmoss/dynamic_form
Ruby
192
star
53

country_select

NOTICE: official repository moved to https://github.com/stefanpenner/country_select
Ruby
176
star
54

rails-dom-testing

Extracting DomAssertions and SelectorAssertions from ActionView.
Ruby
168
star
55

routing_concerns

Abstract common routing resource concerns to cut down on duplication.
Ruby
154
star
56

esbuild-rails

Bundle and transpile JavaScript in Rails with esbuild
Ruby
147
star
57

rails-contributors

The web application that runs https://contributors.rubyonrails.org
Ruby
138
star
58

actionmailbox

Receive and process incoming emails in Rails
125
star
59

requestjs-rails

JavaScript
103
star
60

activemodel-globalid

Serializing models to a single string makes it easy to pass references around
Ruby
90
star
61

account_location

NOTICE: official repository moved to https://github.com/bbommarito/account_location
Ruby
73
star
62

acts_as_nested_set

NOTICE: official repository moved to https://github.com/bbommarito/acts_as_nested_set
Ruby
71
star
63

iso-3166-country-select

WARNING: this repo is not maintained anymore, if you want to maintain it, please send an mail to rails-core
Ruby
70
star
64

activerecord-deprecated_finders

Ruby
68
star
65

spring-watcher-listen

Ruby
63
star
66

weblog

Superseded by https://github.com/rails/website
HTML
63
star
67

prototype-ujs

JavaScript
62
star
68

prototype_legacy_helper

WARNING: this repo is not maintained anymore, if you want to maintain it, please send an mail to rails-core
Ruby
60
star
69

verification

NOTICE: official repository moved to https://github.com/sikachu/verification
Ruby
58
star
70

website

HTML
55
star
71

prototype-rails

Add RJS, Prototype, and Scriptaculous helpers to Rails 3.1+ apps
Ruby
55
star
72

activemodel-serializers-xml

Ruby
52
star
73

record_tag_helper

ActionView Record Tag Helpers
Ruby
50
star
74

homepage

Superseded by https://github.com/rails/website
HTML
50
star
75

rollupjs-rails

Bundle and transpile JavaScript in Rails with rollup.js
Ruby
49
star
76

actionpack-xml_parser

XML parameters parser for Action Pack (removed from core in Rails 4.0)
Ruby
49
star
77

activesupport-json_encoder

Ruby
48
star
78

etagger

Declare what goes in to your ETags: asset versions, account ID, etc.
Ruby
41
star
79

upload_progress

NOTICE: official repository moved to https://github.com/rishav/upload_progress
Ruby
39
star
80

atom_feed_helper

NOTICE: official repository moved to https://github.com/TrevorBramble/atom_feed_helper
Ruby
38
star
81

render_component

NOTICE: official repository moved to https://github.com/malev/render_component. Components allow you to call other actions for their rendered response while executing another action
Ruby
38
star
82

gsoc2014

Project website and wiki for Ruby on Rails proposals to Google Summer of Code 2014
37
star
83

gsoc2013

Project website and wiki for Ruby on Rails proposals to Google Summer of Code 2013
31
star
84

ruby-coffee-script

Ruby CoffeeScript Compiler
Ruby
28
star
85

asset_server

NOTICE: official repository moved to https://github.com/andhapp/asset_server
Ruby
27
star
86

homepage-2011

This repo is now legacy. New homepage is at rails/homepage
HTML
26
star
87

deadlock_retry

NOTICE: official repository moved to https://github.com/heaps/deadlock_retry
Ruby
26
star
88

token_generator

NOTICE: official repository moved to https://github.com/bbommarito/token_generator
Ruby
25
star
89

rails-docs-server

Ruby
24
star
90

http_authentication

NOTICE: official repository moved to https://github.com/dshimy/http_authentication
Ruby
22
star
91

irs_process_scripts

WARNING: this repo is not maintained anymore, if you want to maintain it, please send an mail to rails-core. The extracted inspector, reaper, and spawner scripts from script/process/*
22
star
92

javascript_test

WARNING: this repo is not maintained anymore, if you want to maintain it, please send an mail to rails-core
JavaScript
19
star
93

rails_fast_attributes

Experimental project
Rust
18
star
94

scriptaculous_slider

WARNING: this repo is not maintained anymore, if you want to maintain it, please send an mail to rails-core
JavaScript
18
star
95

rails-ujs

Ruby on Rails unobtrusive scripting adapter
17
star
96

request_profiler

WARNING: this repo is not maintained anymore, if you want to maintain it, please send an mail to rails-core. Request profiler based on integration test scripts
Ruby
17
star
97

scaffolding

NOTICE: official repository moved to https://github.com/KeysetTS/scaffolding
Ruby
17
star
98

rails-new

Shell
16
star
99

buildkite-config

Fallback configuration for branches that lack a .buildkite/ directory
Ruby
16
star
100

tzinfo_timezone

WARNING: this repo is not maintained anymore, if you want to maintain it, please send an mail to rails-core
Ruby
13
star