Skip to content

Commit 6dfb610

Browse files
authored
Delegates calls to inner object is some classes by extends Forwardable (#2535)
* Add forwardable to api.rb and delegate functions to base_instance and instance_for_rack Use `delegate_missing_to` instead of method_missing Add forwardable in endpoint.rb. Delegate `params` and `headers` to `request` Remove LazyObject for build_headers since its not forced in endpoint.rb anymore. Small refactor to request.rb Use `each_header` from Rack::Request instead of `env.each_pair` Remove `.to_s` since Ruby 2.7 added `start_with?` to symbols Add forwardable in stack.rb. * Add CHANGELOG.md
1 parent 430a45d commit 6dfb610

File tree

5 files changed

+28
-68
lines changed

5 files changed

+28
-68
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#### Features
44

55
* [#2532](https://github.com/ruby-grape/grape/pull/2532): Update RuboCop 1.71.2 - [@ericproulx](https://github.com/ericproulx).
6+
* [#2535](https://github.com/ruby-grape/grape/pull/2535): Delegates calls to inner objects - [@ericproulx](https://github.com/ericproulx).
67
* Your contribution here.
78

89
#### Fixes

lib/grape/api.rb

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,18 @@ class Instance
2020
end
2121

2222
class << self
23+
extend Forwardable
2324
attr_accessor :base_instance, :instances
2425

25-
# Rather than initializing an object of type Grape::API, create an object of type Instance
26-
def new(...)
27-
base_instance.new(...)
28-
end
26+
delegate_missing_to :base_instance
27+
def_delegators :base_instance, :new, :configuration
28+
29+
# This is the interface point between Rack and Grape; it accepts a request
30+
# from Rack and ultimately returns an array of three values: the status,
31+
# the headers, and the body. See [the rack specification]
32+
# (http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.
33+
# NOTE: This will only be called on an API directly mounted on RACK
34+
def_delegators :instance_for_rack, :call, :compile!
2935

3036
# When inherited, will create a list of all instances (times the API was mounted)
3137
# It will listen to the setup required to mount that endpoint, and replicate it on any new instance
@@ -69,15 +75,6 @@ def configure
6975
end
7076
end
7177

72-
# This is the interface point between Rack and Grape; it accepts a request
73-
# from Rack and ultimately returns an array of three values: the status,
74-
# the headers, and the body. See [the rack specification]
75-
# (http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.
76-
# NOTE: This will only be called on an API directly mounted on RACK
77-
def call(...)
78-
instance_for_rack.call(...)
79-
end
80-
8178
# The remountable class can have a configuration hash to provide some dynamic class-level variables.
8279
# For instance, a description could be done using: `desc configuration[:description]` if it may vary
8380
# depending on where the endpoint is mounted. Use with care, if you find yourself using configuration
@@ -98,27 +95,6 @@ def replay_setup_on(instance)
9895
end
9996
end
10097

101-
def respond_to?(method, include_private = false)
102-
super || base_instance.respond_to?(method, include_private)
103-
end
104-
105-
def respond_to_missing?(method, include_private = false)
106-
base_instance.respond_to?(method, include_private)
107-
end
108-
109-
def method_missing(method, *args, &block)
110-
# If there's a missing method, it may be defined on the base_instance instead.
111-
if respond_to_missing?(method)
112-
base_instance.send(method, *args, &block)
113-
else
114-
super
115-
end
116-
end
117-
118-
def compile!
119-
instance_for_rack.compile! # See API::Instance.compile!
120-
end
121-
12298
private
12399

124100
def instance_for_rack

lib/grape/endpoint.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ module Grape
66
# on the instance level of this class may be called
77
# from inside a `get`, `post`, etc.
88
class Endpoint
9+
extend Forwardable
910
include Grape::DSL::Settings
1011
include Grape::DSL::InsideRoute
1112

1213
attr_accessor :block, :source, :options
13-
attr_reader :env, :request, :headers, :params
14+
attr_reader :env, :request
15+
16+
def_delegators :request, :params, :headers
1417

1518
class << self
1619
def new(...)
@@ -247,8 +250,6 @@ def run
247250
ActiveSupport::Notifications.instrument('endpoint_run.grape', endpoint: self, env: env) do
248251
@header = Grape::Util::Header.new
249252
@request = Grape::Request.new(env, build_params_with: namespace_inheritable(:build_params_with))
250-
@params = @request.params
251-
@headers = @request.headers
252253
begin
253254
cookies.read(@request)
254255
self.class.run_before_each(self)

lib/grape/middleware/stack.rb

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@ module Middleware
55
# Class to handle the stack of middlewares based on ActionDispatch::MiddlewareStack
66
# It allows to insert and insert after
77
class Stack
8+
extend Forwardable
89
class Middleware
10+
extend Forwardable
11+
912
attr_reader :args, :block, :klass
1013

14+
def_delegators :klass, :name
15+
1116
def initialize(klass, *args, &block)
1217
@klass = klass
1318
@args = args
1419
@block = block
1520
end
1621

17-
def name
18-
klass.name
19-
end
20-
2122
def ==(other)
2223
case other
2324
when Middleware
@@ -32,35 +33,21 @@ def inspect
3233
end
3334

3435
def use_in(builder)
35-
builder.use(@klass, *@args, &@block)
36+
builder.use(klass, *args, &block)
3637
end
3738
end
3839

3940
include Enumerable
4041

4142
attr_accessor :middlewares, :others
4243

44+
def_delegators :middlewares, :each, :size, :last, :[]
45+
4346
def initialize
4447
@middlewares = []
4548
@others = []
4649
end
4750

48-
def each(&block)
49-
@middlewares.each(&block)
50-
end
51-
52-
def size
53-
middlewares.size
54-
end
55-
56-
def last
57-
middlewares.last
58-
end
59-
60-
def [](index)
61-
middlewares[index]
62-
end
63-
6451
def insert(index, *args, &block)
6552
index = assert_index(index, :before)
6653
middleware = self.class::Middleware.new(*args, &block)

lib/grape/request.rb

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,16 @@ def headers
2626
private
2727

2828
def grape_routing_args
29-
args = env[Grape::Env::GRAPE_ROUTING_ARGS].dup
3029
# preserve version from query string parameters
31-
args.delete(:version)
32-
args.delete(:route_info)
33-
args
30+
env[Grape::Env::GRAPE_ROUTING_ARGS].except(:version, :route_info)
3431
end
3532

3633
def build_headers
37-
Grape::Util::Lazy::Object.new do
38-
env.each_pair.with_object(Grape::Util::Header.new) do |(k, v), headers|
39-
next unless k.to_s.start_with? HTTP_PREFIX
34+
each_header.with_object(Grape::Util::Header.new) do |(k, v), headers|
35+
next unless k.start_with? HTTP_PREFIX
4036

41-
transformed_header = Grape::Http::Headers::HTTP_HEADERS[k] || transform_header(k)
42-
headers[transformed_header] = v
43-
end
37+
transformed_header = Grape::Http::Headers::HTTP_HEADERS[k] || transform_header(k)
38+
headers[transformed_header] = v
4439
end
4540
end
4641

0 commit comments

Comments
 (0)