summary refs log tree commit
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2022-08-05 02:36:13 +1200
committerGitHub <noreply@github.com>2022-08-04 07:36:13 -0700
commit1e4c18d895cde0af92e9286cfda52b4c10bb0488 (patch)
treec31e9a8c2781a0579df10a92a2b7198d7ab294a5
parent882cbb32d6472bbaa386ca220d2512ccfdcb86c0 (diff)
downloadrack-1e4c18d895cde0af92e9286cfda52b4c10bb0488.tar.gz
Allow `Rack::Builder#run` to take a block instead of an argument. (#1942)
* Raise ArgumentError if both app and block given.
-rw-r--r--CHANGELOG.md1
-rw-r--r--lib/rack/builder.rb34
-rw-r--r--test/spec_builder.rb7
3 files changed, 35 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3b0d96ca..076783e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,6 +40,7 @@ All notable changes to this project will be documented in this file. For info on
 - The RFC 7239 Forwarded header is now supported and considered by default when looking for information on forwarding, falling back to the X-Forwarded-* headers. `Rack::Request.forwarded_priority` accessor has been added for configuring the priority of which header to check.  ([#1423](https://github.com/rack/rack/issues/1423), [@jeremyevans])
 - Allow response headers to contain array of values. ([#1598](https://github.com/rack/rack/issues/1598), [@ioquatix])
 - Support callable body for explicit streaming support and clarify streaming response body behaviour. ([#1745](https://github.com/rack/rack/pull/1745), [@ioquatix], [#1748](https://github.com/rack/rack/pull/1748), [@wjordan])
+- Allow `Rack::Builder#run` to take a block instead of an argument. ([#1942](https://github.com/rack/rack/pull/1942), [@ioquatix])
 
 ### Changed
 
diff --git a/lib/rack/builder.rb b/lib/rack/builder.rb
index fa5e876f..6d40b534 100644
--- a/lib/rack/builder.rb
+++ b/lib/rack/builder.rb
@@ -157,22 +157,42 @@ module Rack
     ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
     # :nocov:
 
-    # Takes an argument that is an object that responds to #call and returns a Rack response.
-    # The simplest form of this is a lambda object:
+    # Takes a block or argument that is an object that responds to #call and
+    # returns a Rack response.
+    #
+    # You can use a block:
+    #
+    #   run do |env|
+    #     [200, { "content-type" => "text/plain" }, ["Hello World!"]]
+    #   end
+    #
+    # You can also provide a lambda:
     #
     #   run lambda { |env| [200, { "content-type" => "text/plain" }, ["OK"]] }
     #
-    # However this could also be a class:
+    # You can also provide a class instance:
     #
     #   class Heartbeat
-    #     def self.call(env)
+    #     def call(env)
     #      [200, { "content-type" => "text/plain" }, ["OK"]]
     #     end
     #   end
     #
-    #   run Heartbeat
-    def run(app)
-      @run = app
+    #   run Heartbeat.new
+    #
+    # It could also be a module:
+    #
+    #   module HelloWorld
+    #     def call(env)
+    #      [200, { "content-type" => "text/plain" }, ["Hello World"]]
+    #     end
+    #   end
+    #
+    #   run HelloWorld
+    def run(app = nil, &block)
+      raise ArgumentError, "Both app and block given!" if app && block_given?
+
+      @run = app || block
     end
 
     # Takes a lambda or block that is used to warm-up the application. This block is called
diff --git a/test/spec_builder.rb b/test/spec_builder.rb
index 52bdf76c..6ca28477 100644
--- a/test/spec_builder.rb
+++ b/test/spec_builder.rb
@@ -34,6 +34,13 @@ describe Rack::Builder do
     Rack::Lint.new Rack::Builder.new(&block).to_app
   end
 
+  it "supports run with block" do
+    app = builder_to_app do
+      run {|env| [200, { "content-type" => "text/plain" }, ["OK"]]}
+    end
+    Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'OK'
+  end
+
   it "supports mapping" do
     app = builder_to_app do
       map '/' do |outer_env|