mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Allow a new server
Railtie block:
- This is similar to other railties blocks (such as `console`, `tasks` ...). The goal of this block is to allow the application or a railtie to load code after the server start. The use case can be to fire the webpack or react server in development or start some job worker like sidekiq or resque. Right now, all these tasks needs to be done in a separate shell and gem maintainer needs to add documentation on how to run their libraries if another program needs to run next to the Rails server. This feature can be used like this: ```ruby class SuperRailtie < Rails::Railtie server do WebpackServer.run end end ```
This commit is contained in:
parent
4dd61b4318
commit
868866c1fd
8 changed files with 104 additions and 1 deletions
|
@ -1,3 +1,20 @@
|
|||
* Added `Railtie#server` hook called when Rails starts a server.
|
||||
This is useful in case your application or a library needs to run
|
||||
another process next to the Rails server. This is quite common in development
|
||||
for instance to run the Webpack or the React server.
|
||||
|
||||
It can be used like this:
|
||||
|
||||
```ruby
|
||||
class MyRailtie < Rails::Railtie
|
||||
server do
|
||||
WebpackServer.run
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
*Edouard Chin*
|
||||
|
||||
* Remove deprecated `rake dev:cache` tasks.
|
||||
|
||||
*Rafael Mendonça França*
|
||||
|
@ -94,7 +111,6 @@
|
|||
|
||||
*Eileen M. Uchitelle*, *John Crepezzi*
|
||||
|
||||
|
||||
* Accept params from url to prepopulate the Inbound Emails form in Rails conductor.
|
||||
|
||||
*Chris Oliver*
|
||||
|
|
|
@ -322,6 +322,12 @@ module Rails
|
|||
self.class.generators(&blk)
|
||||
end
|
||||
|
||||
# Sends any server called in the instance of a new application up
|
||||
# to the +server+ method defined in Rails::Railtie.
|
||||
def server(&blk)
|
||||
self.class.server(&blk)
|
||||
end
|
||||
|
||||
# Sends the +isolate_namespace+ method up to the class method.
|
||||
def isolate_namespace(mod)
|
||||
self.class.isolate_namespace(mod)
|
||||
|
@ -536,6 +542,11 @@ module Rails
|
|||
super
|
||||
end
|
||||
|
||||
def run_server_blocks(app) #:nodoc:
|
||||
railties.each { |r| r.run_server_blocks(app) }
|
||||
super
|
||||
end
|
||||
|
||||
# Returns the ordered railties for this application considering railties_order.
|
||||
def ordered_railties #:nodoc:
|
||||
@ordered_railties ||= begin
|
||||
|
|
|
@ -470,6 +470,13 @@ module Rails
|
|||
self
|
||||
end
|
||||
|
||||
# Invoke the server registered hooks.
|
||||
# Check <tt>Rails::Railtie.server</tt> for more info.
|
||||
def load_server(app = self)
|
||||
run_server_blocks(app)
|
||||
self
|
||||
end
|
||||
|
||||
def eager_load!
|
||||
# Already done by Zeitwerk::Loader.eager_load_all. We need this guard to
|
||||
# easily provide a compatible API for both zeitwerk and classic modes.
|
||||
|
|
|
@ -143,6 +143,7 @@ module Rails
|
|||
@config_target_version = Rails.application.config.loaded_config_version || "5.0"
|
||||
|
||||
config
|
||||
configru
|
||||
|
||||
unless cookie_serializer_config_exist
|
||||
gsub_file "config/initializers/cookies_serializer.rb", /json(?!,)/, "marshal"
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
require_relative "config/environment"
|
||||
|
||||
run Rails.application
|
||||
Rails.application.load_server
|
||||
|
|
|
@ -108,6 +108,23 @@ module Rails
|
|||
# Since filenames on the load path are shared across gems, be sure that files you load
|
||||
# through a railtie have unique names.
|
||||
#
|
||||
# == Run another program when the Rails server starts
|
||||
#
|
||||
# In development, it's very usual to have to run another process next to the Rails Server. In example
|
||||
# you might want to start the Webpack or React server. Or maybe you need to run your job scheduler process
|
||||
# like Sidekiq. This is usually done by opening a new shell and running the program from here.
|
||||
#
|
||||
# Rails allow you to specify a +server+ block which will get called when a Rails server starts.
|
||||
# This way, your users don't need to remember to have to open a new shell and run another program, making
|
||||
# this less confusing for everyone.
|
||||
# It can be used like this:
|
||||
#
|
||||
# class MyRailtie < Rails::Railtie
|
||||
# server do
|
||||
# WebpackServer.start
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# == Application and Engine
|
||||
#
|
||||
# An engine is nothing more than a railtie with some initializers already set. And since
|
||||
|
@ -152,6 +169,10 @@ module Rails
|
|||
register_block_for(:generators, &blk)
|
||||
end
|
||||
|
||||
def server(&blk)
|
||||
register_block_for(:server, &blk)
|
||||
end
|
||||
|
||||
def abstract_railtie?
|
||||
ABSTRACT_RAILTIES.include?(name)
|
||||
end
|
||||
|
@ -246,6 +267,10 @@ module Rails
|
|||
each_registered_block(:rake_tasks) { |block| instance_exec(app, &block) }
|
||||
end
|
||||
|
||||
def run_server_blocks(app) #:nodoc:
|
||||
each_registered_block(:server) { |block| block.call(app) }
|
||||
end
|
||||
|
||||
private
|
||||
# run `&block` in every registered block in `#register_block_for`
|
||||
def each_registered_block(type, &block)
|
||||
|
|
|
@ -42,6 +42,32 @@ module ApplicationTests
|
|||
end
|
||||
end
|
||||
|
||||
test "run +server+ blocks after the server starts" do
|
||||
skip "PTY unavailable" unless available_pty?
|
||||
|
||||
File.open("#{app_path}/config/boot.rb", "w") do |f|
|
||||
f.puts "ENV['BUNDLE_GEMFILE'] = '#{Bundler.default_gemfile}'"
|
||||
f.puts 'require "bundler/setup"'
|
||||
end
|
||||
|
||||
add_to_config(<<~CODE)
|
||||
server do
|
||||
puts 'Hello world'
|
||||
end
|
||||
CODE
|
||||
|
||||
primary, replica = PTY.open
|
||||
pid = nil
|
||||
|
||||
Bundler.with_original_env do
|
||||
pid = Process.spawn("bin/rails server -b localhost", chdir: app_path, in: replica, out: primary, err: replica)
|
||||
assert_output("Hello world", primary)
|
||||
assert_output("Listening", primary)
|
||||
ensure
|
||||
kill(pid) if pid
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def kill(pid)
|
||||
Process.kill("TERM", pid)
|
||||
|
|
|
@ -170,6 +170,22 @@ module RailtiesTest
|
|||
assert $ran_block
|
||||
end
|
||||
|
||||
test "server block is executed when MyApp.load_server is called" do
|
||||
$ran_block = false
|
||||
|
||||
class MyTie < Rails::Railtie
|
||||
server do
|
||||
$ran_block = true
|
||||
end
|
||||
end
|
||||
|
||||
require "#{app_path}/config/environment"
|
||||
|
||||
assert_not $ran_block
|
||||
Rails.application.load_server
|
||||
assert $ran_block
|
||||
end
|
||||
|
||||
test "runner block is executed when MyApp.load_runner is called" do
|
||||
$ran_block = false
|
||||
|
||||
|
|
Loading…
Reference in a new issue