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
- #method_name ⇒ Object
- #mount_in(router) ⇒ Object
- #namespace ⇒ Object
- #prepare_default_path_settings ⇒ Object
- #prepare_default_route_attributes ⇒ 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
214 215 216 217 |
# File 'lib/grape/endpoint.rb', line 214 def call(env) lazy_initialize! dup.call!(env) end |
#call!(env) ⇒ Object
219 220 221 222 223 |
# File 'lib/grape/endpoint.rb', line 219 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.
227 228 229 |
# File 'lib/grape/endpoint.rb', line 227 def endpoints [:app].endpoints if [:app].respond_to?(:endpoints) end |
#equals?(endpoint) ⇒ Boolean
231 232 233 |
# File 'lib/grape/endpoint.rb', line 231 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.
238 239 240 241 242 |
# File 'lib/grape/endpoint.rb', line 238 def inspect return super unless env "#{self.class} in '#{route.origin}' endpoint" end |
#map_routes ⇒ Object
200 201 202 |
# File 'lib/grape/endpoint.rb', line 200 def map_routes [:method].map { |method| [:path].map { |path| yield method, path } } 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 |
# File 'lib/grape/endpoint.rb', line 147 def mount_in(router) return endpoints.each { |e| e.mount_in(router) } if endpoints reset_routes! routes.each do |route| router.append(route.apply(self)) next unless !namespace_inheritable(:do_not_route_head) && route.request_method == Rack::GET route.dup.then do |head_route| head_route.convert_to_head_request! router.append(head_route.apply(self)) end end end |
#namespace ⇒ Object
210 211 212 |
# File 'lib/grape/endpoint.rb', line 210 def namespace @namespace ||= Namespace.joined_space_path(namespace_stackable(:namespace)) end |
#prepare_default_path_settings ⇒ Object
204 205 206 207 208 |
# File 'lib/grape/endpoint.rb', line 204 def prepare_default_path_settings namespace_stackable_hash = inheritable_setting.namespace_stackable.to_hash namespace_inheritable_hash = inheritable_setting.namespace_inheritable.to_hash namespace_stackable_hash.merge!(namespace_inheritable_hash) end |
#prepare_default_route_attributes ⇒ Object
181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/grape/endpoint.rb', line 181 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_routes_requirements ⇒ Object
174 175 176 177 178 179 |
# File 'lib/grape/endpoint.rb', line 174 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
193 194 195 196 197 198 |
# File 'lib/grape/endpoint.rb', line 193 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
162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/grape/endpoint.rb', line 162 def to_routes = prepare_default_route_attributes default_path_settings = prepare_default_path_settings map_routes do |method, raw_path| prepared_path = Path.new(raw_path, namespace, default_path_settings) params = [:route_options].present? ? [:route_options].merge() : route = Grape::Router::Route.new(method, prepared_path.origin, prepared_path.suffix, params) route.apply(self) end.flatten end |