Class: Grape::Endpoint
- Inherits:
-
Object
- Object
- Grape::Endpoint
- Includes:
- DSL::InsideRoute, DSL::Settings
- Defined in:
- lib/grape/endpoint.rb
Overview
An Endpoint is the proxy scope in which all routing
blocks are executed. In other words, any methods
on the instance level of this class may be called
from inside a get
, post
, etc.
Instance Attribute Summary collapse
-
#block ⇒ Object
Returns the value of attribute block.
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#headers ⇒ Object
readonly
Returns the value of attribute headers.
-
#options ⇒ Object
Returns the value of attribute options.
-
#params ⇒ Object
readonly
Returns the value of attribute params.
-
#request ⇒ Object
readonly
Returns the value of attribute request.
-
#source ⇒ Object
Returns the value of attribute source.
Attributes included from DSL::Settings
#inheritable_setting, #top_level_setting
Class Method Summary collapse
- .before_each(new_setup = false, &block) ⇒ Object
-
.generate_api_method(method_name, &block) ⇒ Proc
private
Create an UnboundMethod that is appropriate for executing an endpoint route.
- .new ⇒ Object
- .run_before_each(endpoint) ⇒ Object
Instance Method Summary collapse
- #call(env) ⇒ Object
- #call!(env) ⇒ Object
-
#endpoints ⇒ Object
Return the collection of endpoints within this endpoint.
- #equals?(endpoint) ⇒ Boolean
-
#inherit_settings(namespace_stackable) ⇒ Object
Update our settings from a given set of stackable parameters.
-
#initialize(new_settings, options = {}) { ... } ⇒ Endpoint
constructor
Create a new endpoint.
-
#inspect ⇒ Object
The purpose of this override is solely for stripping internals when an error occurs while calling an endpoint through an api.
- #map_routes ⇒ Object
- #merge_route_options(**default) ⇒ Object
- #method_name ⇒ Object
- #mount_in(router) ⇒ Object
- #namespace ⇒ Object
- #prepare_default_route_attributes ⇒ Object
- #prepare_path(path) ⇒ Object
- #prepare_routes_requirements ⇒ Object
- #prepare_version ⇒ Object
- #require_option(options, key) ⇒ Object
- #reset_routes! ⇒ Object
- #routes ⇒ Object
- #to_routes ⇒ Object
Methods included from DSL::InsideRoute
#api_format, #body, #configuration, #content_type, #context, #cookies, #declared, #entity_class_for_obj, #entity_representation_for, #error!, #http_version, post_filter_methods, #present, #rack_response, #redirect, #return_no_content, #route, #sendfile, #status, #stream, #version
Methods included from DSL::Headers
Methods included from DSL::Settings
#api_class_setting, #get_or_set, #global_setting, #namespace_end, #namespace_inheritable, #namespace_inheritable_to_nil, #namespace_reverse_stackable, #namespace_reverse_stackable_with_hash, #namespace_setting, #namespace_stackable, #namespace_stackable_with_hash, #namespace_start, #route_end, #route_setting, #unset, #unset_api_class_setting, #unset_global_setting, #unset_namespace_inheritable, #unset_namespace_setting, #unset_namespace_stackable, #unset_route_setting, #within_namespace
Constructor Details
#initialize(new_settings, options = {}) { ... } ⇒ Endpoint
This happens at the time of API definition, so in this context the
Create a new endpoint. endpoint does not know if it will be mounted under a different endpoint.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/grape/endpoint.rb', line 76 def initialize(new_settings, = {}, &block) require_option(, :path) require_option(, :method) self.inheritable_setting = new_settings.point_in_time_copy # now +namespace_stackable(:declared_params)+ contains all params defined for # this endpoint and its parents, but later it will be cleaned up, # see +reset_validations!+ in lib/grape/dsl/validations.rb route_setting(:declared_params, namespace_stackable(:declared_params).flatten) route_setting(:saved_validations, namespace_stackable(:validations)) namespace_stackable(:representations, []) unless namespace_stackable(:representations) namespace_inheritable(:default_error_status, 500) unless namespace_inheritable(:default_error_status) @options = @options[:path] = Array([:path]) @options[:path] << '/' if [:path].empty? @options[:method] = Array([:method]) @options[:route_options] ||= {} @lazy_initialize_lock = Mutex.new @lazy_initialized = nil @block = nil @status = nil @stream = nil @body = nil @proc = nil return unless block @source = block @block = self.class.generate_api_method(method_name, &block) end |
Instance Attribute Details
#block ⇒ Object
Returns the value of attribute block.
12 13 14 |
# File 'lib/grape/endpoint.rb', line 12 def block @block end |
#env ⇒ Object (readonly)
Returns the value of attribute env.
13 14 15 |
# File 'lib/grape/endpoint.rb', line 13 def env @env end |
#headers ⇒ Object (readonly)
Returns the value of attribute headers.
13 14 15 |
# File 'lib/grape/endpoint.rb', line 13 def headers @headers end |
#options ⇒ Object
Returns the value of attribute options.
12 13 14 |
# File 'lib/grape/endpoint.rb', line 12 def @options end |
#params ⇒ Object (readonly)
Returns the value of attribute params.
13 14 15 |
# File 'lib/grape/endpoint.rb', line 13 def params @params end |
#request ⇒ Object (readonly)
Returns the value of attribute request.
13 14 15 |
# File 'lib/grape/endpoint.rb', line 13 def request @request end |
#source ⇒ Object
Returns the value of attribute source.
12 13 14 |
# File 'lib/grape/endpoint.rb', line 12 def source @source end |
Class Method Details
.before_each(new_setup = false, &block) ⇒ Object
20 21 22 23 24 25 26 27 28 29 |
# File 'lib/grape/endpoint.rb', line 20 def before_each(new_setup = false, &block) @before_each ||= [] if new_setup == false return @before_each unless block @before_each << block else @before_each = [new_setup] end end |
.generate_api_method(method_name, &block) ⇒ Proc
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Create an UnboundMethod that is appropriate for executing an endpoint route.
The unbound method allows explicit calls to +return+ without raising a +LocalJumpError+. The method will be removed, but a +Proc+ reference to it will be returned. The returned +Proc+ expects a single argument: the instance of +Endpoint+ to bind to the method during the call.
49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/grape/endpoint.rb', line 49 def generate_api_method(method_name, &block) raise NameError.new("method #{method_name.inspect} already exists and cannot be used as an unbound method name") if method_defined?(method_name) define_method(method_name, &block) method = instance_method(method_name) remove_method(method_name) proc do |endpoint_instance| ActiveSupport::Notifications.instrument('endpoint_render.grape', endpoint: endpoint_instance) do method.bind_call(endpoint_instance) end end end |
.new ⇒ Object
16 17 18 |
# File 'lib/grape/endpoint.rb', line 16 def new(...) self == Endpoint ? Class.new(Endpoint).new(...) : super end |
.run_before_each(endpoint) ⇒ Object
31 32 33 34 |
# File 'lib/grape/endpoint.rb', line 31 def run_before_each(endpoint) superclass.run_before_each(endpoint) unless self == Endpoint before_each.each { |blk| blk.call(endpoint) if blk.respond_to?(:call) } end |
Instance Method Details
#call(env) ⇒ Object
218 219 220 221 |
# File 'lib/grape/endpoint.rb', line 218 def call(env) lazy_initialize! dup.call!(env) end |
#call!(env) ⇒ Object
223 224 225 226 227 |
# File 'lib/grape/endpoint.rb', line 223 def call!(env) env[Grape::Env::API_ENDPOINT] = self @env = env @app.call(env) end |
#endpoints ⇒ Object
Return the collection of endpoints within this endpoint. This is the case when an Grape::API mounts another Grape::API.
231 232 233 |
# File 'lib/grape/endpoint.rb', line 231 def endpoints [:app].endpoints if [:app].respond_to?(:endpoints) end |
#equals?(endpoint) ⇒ Boolean
235 236 237 |
# File 'lib/grape/endpoint.rb', line 235 def equals?(endpoint) ( == endpoint.) && (inheritable_setting.to_hash == endpoint.inheritable_setting.to_hash) end |
#inherit_settings(namespace_stackable) ⇒ Object
Update our settings from a given set of stackable parameters. Used when the endpoint's API is mounted under another one.
116 117 118 119 120 121 122 123 |
# File 'lib/grape/endpoint.rb', line 116 def inherit_settings(namespace_stackable) parent_validations = namespace_stackable[:validations] inheritable_setting.route[:saved_validations].concat(parent_validations) if parent_validations.any? parent_declared_params = namespace_stackable[:declared_params] inheritable_setting.route[:declared_params].concat(parent_declared_params.flatten) if parent_declared_params.any? endpoints&.each { |e| e.inherit_settings(namespace_stackable) } end |
#inspect ⇒ Object
The purpose of this override is solely for stripping internals when an error occurs while calling an endpoint through an api. See https://github.com/ruby-grape/grape/issues/2398 Otherwise, it calls super.
242 243 244 245 246 |
# File 'lib/grape/endpoint.rb', line 242 def inspect return super unless env "#{self.class} in '#{route.origin}' endpoint" end |
#map_routes ⇒ Object
203 204 205 |
# File 'lib/grape/endpoint.rb', line 203 def map_routes [:method].map { |method| [:path].map { |path| yield method, path } } end |
#merge_route_options(**default) ⇒ Object
199 200 201 |
# File 'lib/grape/endpoint.rb', line 199 def (**default) [:route_options].clone.merge!(**default) end |
#method_name ⇒ Object
129 130 131 132 133 134 135 |
# File 'lib/grape/endpoint.rb', line 129 def method_name [[:method], Namespace.joined_space(namespace_stackable(:namespace)), (namespace_stackable(:mount_path) || []).join('/'), [:path].join('/')] .join(' ') end |
#mount_in(router) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/grape/endpoint.rb', line 147 def mount_in(router) if endpoints endpoints.each { |e| e.mount_in(router) } else reset_routes! routes.each do |route| methods = [route.request_method] methods << Rack::HEAD if !namespace_inheritable(:do_not_route_head) && route.request_method == Rack::GET methods.each do |method| route = Grape::Router::Route.new(method, route.origin, **route.attributes.to_h) unless route.request_method == method router.append(route.apply(self)) end end end end |
#namespace ⇒ Object
214 215 216 |
# File 'lib/grape/endpoint.rb', line 214 def namespace @namespace ||= Namespace.joined_space_path(namespace_stackable(:namespace)) end |
#prepare_default_route_attributes ⇒ Object
180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/grape/endpoint.rb', line 180 def prepare_default_route_attributes { namespace: namespace, version: prepare_version, requirements: prepare_routes_requirements, prefix: namespace_inheritable(:root_prefix), anchor: [:route_options].fetch(:anchor, true), settings: inheritable_setting.route.except(:declared_params, :saved_validations), forward_match: [:forward_match] } end |
#prepare_path(path) ⇒ Object
207 208 209 210 211 212 |
# File 'lib/grape/endpoint.rb', line 207 def prepare_path(path) namespace_stackable_hash = inheritable_setting.namespace_stackable.to_hash namespace_inheritable_hash = inheritable_setting.namespace_inheritable.to_hash path_settings = namespace_stackable_hash.merge!(namespace_inheritable_hash) Path.new(path, namespace, path_settings) end |
#prepare_routes_requirements ⇒ Object
173 174 175 176 177 178 |
# File 'lib/grape/endpoint.rb', line 173 def prepare_routes_requirements {}.merge!(*namespace_stackable(:namespace).map(&:requirements)).tap do |requirements| endpoint_requirements = .dig(:route_options, :requirements) requirements.merge!(endpoint_requirements) if endpoint_requirements end end |
#prepare_version ⇒ Object
192 193 194 195 196 197 |
# File 'lib/grape/endpoint.rb', line 192 def prepare_version version = namespace_inheritable(:version) return if version.blank? version.length == 1 ? version.first : version end |
#require_option(options, key) ⇒ Object
125 126 127 |
# File 'lib/grape/endpoint.rb', line 125 def require_option(, key) raise Grape::Exceptions::MissingOption.new(key) unless .key?(key) end |
#reset_routes! ⇒ Object
141 142 143 144 145 |
# File 'lib/grape/endpoint.rb', line 141 def reset_routes! endpoints&.each(&:reset_routes!) @namespace = nil @routes = nil end |
#routes ⇒ Object
137 138 139 |
# File 'lib/grape/endpoint.rb', line 137 def routes @routes ||= endpoints ? endpoints.collect(&:routes).flatten : to_routes end |
#to_routes ⇒ Object
163 164 165 166 167 168 169 170 171 |
# File 'lib/grape/endpoint.rb', line 163 def to_routes = prepare_default_route_attributes map_routes do |method, path| path = prepare_path(path) params = (**.merge(suffix: path.suffix)) route = Router::Route.new(method, path.path, **params) route.apply(self) end.flatten end |