From 230b690f7ea7be615c9dfeb291e7cb78e3674eba Mon Sep 17 00:00:00 2001 From: Eric Proulx Date: Wed, 17 Dec 2025 20:35:28 +0000 Subject: [PATCH] Add compile! in mount_in function. --- CHANGELOG.md | 2 ++ UPGRADING.md | 6 +++++ lib/grape/endpoint.rb | 27 +++++++------------ lib/grape/router.rb | 14 +++++----- .../api/defines_boolean_in_params_spec.rb | 8 ------ 5 files changed, 24 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30074b603..423d3bdc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ * [#2643](https://github.com/ruby-grape/grape/pull/2638): Remove `try` method in codebase - [@ericproulx](https://github.com/ericproulx). * [#2646](https://github.com/ruby-grape/grape/pull/2646): Call `valid_encoding?` before scrub - [@ericproulx](https://github.com/ericproulx). * [#2644](https://github.com/ruby-grape/grape/pull/2644): Clean useless/not valuable dependencies - [@ericproulx](https://github.com/ericproulx). +* [#2645](https://github.com/ruby-grape/grape/pull/2645): Endpoints are compiled when API is compiled - [@ericproulx](https://github.com/ericproulx). + * Your contribution here. #### Fixes diff --git a/UPGRADING.md b/UPGRADING.md index 1e6b1b991..92e734759 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,6 +1,12 @@ Upgrading Grape =============== +### Upgrading to >= 3.1.0 + +#### Enhanced API compile! + +Endpoints are now "compiled" instead of lazy loaded. Historically, when calling `YourAPI.compile!` in `config.ru` (or just receiving the first API call), only routing was compiled see [Grape::Router#compile!](https://github.com/ruby-grape/grape/blob/bf90e95c3b17c415c944363b1c07eb9727089ee7/lib/grape/router.rb#L41-L54) and endpoints were lazy loaded. Now, it's part of the API compilation. See [#2645](https://github.com/ruby-grape/grape/pull/2645) for more information. + ### Upgrading to >= 3.0.0 #### Ruby 3+ Argument Delegation Modernization diff --git a/lib/grape/endpoint.rb b/lib/grape/endpoint.rb index bb52eb106..041b89640 100644 --- a/lib/grape/endpoint.rb +++ b/lib/grape/endpoint.rb @@ -71,11 +71,8 @@ def initialize(new_settings, **options, &block) @options[:path] = Array(options[:path]) @options[:path] << '/' if options[:path].empty? - @options[:method] = Array(options[:method]) - @lazy_initialize_lock = Mutex.new - @lazy_initialized = nil @status = nil @stream = nil @body = nil @@ -105,9 +102,13 @@ def reset_routes! end def mount_in(router) - return endpoints.each { |e| e.mount_in(router) } if endpoints + if endpoints + compile! + return endpoints.each { |e| e.mount_in(router) } + end reset_routes! + compile! routes.each do |route| router.append(route.apply(self)) next unless !inheritable_setting.namespace_inheritable[:do_not_route_head] && route.request_method == Rack::GET @@ -124,7 +125,6 @@ def namespace end def call(env) - lazy_initialize! dup.call!(env) end @@ -203,18 +203,6 @@ def execute end end - def lazy_initialize! - return true if @lazy_initialized - - @lazy_initialize_lock.synchronize do - return true if @lazy_initialized - - @app = options[:app] || build_stack - @helpers = build_helpers - @lazy_initialized = true - end - end - def run_validators(validators, request) validation_errors = [] @@ -266,6 +254,11 @@ def options? attr_reader :before_filter_passed + def compile! + @app = options[:app] || build_stack + @helpers = build_helpers + end + def to_routes route_options = options[:route_options] default_route_options = prepare_default_route_attributes(route_options) diff --git a/lib/grape/router.rb b/lib/grape/router.rb index dcc61fe99..6710c03b2 100644 --- a/lib/grape/router.rb +++ b/lib/grape/router.rb @@ -2,8 +2,6 @@ module Grape class Router - attr_reader :map, :compiled - # Taken from Rails # normalize_path("/foo") # => "/foo" # normalize_path("/foo/") # => "/foo" @@ -39,14 +37,14 @@ def initialize end def compile! - return if compiled + return if @compiled @union = Regexp.union(@neutral_regexes) @neutral_regexes = nil (Grape::HTTP_SUPPORTED_METHODS + ['*']).each do |method| - next unless map.key?(method) + next unless @map.key?(method) - routes = map[method] + routes = @map[method] optimized_map = routes.map.with_index { |route, index| route.to_regexp(index) } @optimized_map[method] = Regexp.union(optimized_map) end @@ -54,7 +52,7 @@ def compile! end def append(route) - map[route.request_method] << route + @map[route.request_method] << route end def associate_routes(greedy_route) @@ -91,7 +89,7 @@ def identity(input, method, env) def rotation(input, method, env, exact_route) response = nil - map[method].each do |route| + @map[method].each do |route| next if exact_route == route next unless route.match?(input) @@ -143,7 +141,7 @@ def process_route(route, input, env, include_allow_header: false) end def with_optimization - compile! unless compiled + compile! yield || default_response end diff --git a/spec/grape/api/defines_boolean_in_params_spec.rb b/spec/grape/api/defines_boolean_in_params_spec.rb index e885eff0d..bbc48a3c2 100644 --- a/spec/grape/api/defines_boolean_in_params_spec.rb +++ b/spec/grape/api/defines_boolean_in_params_spec.rb @@ -22,13 +22,5 @@ expect(last_response.status).to eq(201) expect(last_response.body).to eq expected_body end - - context 'Params endpoint type' do - subject { app.new.router.map[Rack::POST].first.options[:params]['message'][:type] } - - it 'params type is a boolean' do - expect(subject).to eq 'Grape::API::Boolean' - end - end end end