interpol 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  require 'interpol/request_params_parser'
2
+ require 'forwardable'
2
3
 
3
4
  module Interpol
4
5
  module Sinatra
@@ -11,89 +12,110 @@ module Interpol
11
12
  # it can take a config block.
12
13
  class RequestParamsParser
13
14
  def initialize(app, &block)
14
- @app = app
15
- hook_into(app, &block)
15
+ @original_app_instance = app
16
+ hook_into_app(&block)
16
17
  end
17
18
 
18
19
  def call(env)
19
- @app.call(env)
20
+ @original_app_instance.call(env)
21
+ end
22
+
23
+ ConfigurationError = Class.new(StandardError)
24
+
25
+ # Sinatra dups the app before each request, so we need to
26
+ # receive the app instance as an argument here.
27
+ def validate_and_parse_params(app)
28
+ return unless app.settings.parse_params?
29
+ SingleRequestParamsParser.parse_params(config, app)
20
30
  end
21
31
 
22
32
  private
23
33
 
24
- def hook_into(app, &block)
25
- return if defined?(app.settings.interpol_config)
26
- config = Configuration.default.customized_duplicate(&block)
34
+ attr_reader :config, :original_app_instance
35
+
36
+ def hook_into_app(&block)
37
+ return if defined?(@config)
38
+ check_configuration_validity
39
+
40
+ @config = Configuration.default.customized_duplicate(&block)
41
+ parser = self
27
42
 
28
- app.class.class_eval do
43
+ original_app_instance.class.class_eval do
29
44
  alias unparsed_params params
30
- helpers SinatraHelpers
31
- set :interpol_config, config
45
+ set :request_params_parser, parser
32
46
  enable :parse_params unless settings.respond_to?(:parse_params)
33
47
  include SinatraOverriddes
34
48
  end
35
49
  end
36
50
 
37
- module SinatraHelpers
38
- # Make the config available at the instance level for convenience.
39
- def interpol_config
40
- self.class.interpol_config
41
- end
51
+ def check_configuration_validity
52
+ return if original_app_instance.class.ancestors.include?(::Sinatra::Base)
42
53
 
43
- def endpoint_definition
44
- @endpoint_definition ||= begin
45
- version = available_versions = nil
46
-
47
- definition = interpol_config.endpoints.find_definition \
48
- env.fetch('REQUEST_METHOD'), request.path, 'request', nil do |endpoint|
49
- available_versions ||= endpoint.available_versions
50
- interpol_config.api_version_for(env, endpoint).tap do |_version|
51
- version ||= _version
52
- end
53
- end
54
-
55
- if definition == DefinitionFinder::NoDefinitionFound
56
- interpol_config.request_version_unavailable(self, version, available_versions)
57
- end
54
+ raise ConfigurationError, "#{self.class} must come last in the Sinatra " +
55
+ "middleware list but #{original_app_instance.class} " +
56
+ "currently comes after."
57
+ end
58
58
 
59
- definition
60
- end
59
+ # Handles finding parsing request params for a single request.
60
+ class SingleRequestParamsParser
61
+ def self.parse_params(config, app)
62
+ new(config, app).parse_params
61
63
  end
62
64
 
63
- def params
64
- (@_use_parsed_params && @_parsed_params) || super
65
+ def initialize(config, app)
66
+ @config = config
67
+ @app = app
65
68
  end
66
69
 
67
- def validate_params
68
- @_parsed_params ||= endpoint_definition.parse_request_params(params_to_parse)
70
+ def parse_params
71
+ endpoint_definition.parse_request_params(params_to_parse)
69
72
  rescue Interpol::ValidationError => error
70
73
  request_params_invalid(error)
71
74
  end
72
75
 
73
- def request_params_invalid(error)
74
- interpol_config.sinatra_request_params_invalid(self, error)
75
- end
76
+ private
76
77
 
77
- def with_parsed_params
78
- @_use_parsed_params = true
79
- validate_params if settings.parse_params?
80
- yield
81
- ensure
82
- @_use_parsed_params = false
78
+ attr_reader :app, :config
79
+ extend Forwardable
80
+ def_delegators :app, :request
81
+
82
+ def endpoint_definition
83
+ version = available_versions = nil
84
+
85
+ definition = config.endpoints.find_definition \
86
+ request.env.fetch('REQUEST_METHOD'), request.path, 'request', nil do |endpoint|
87
+ available_versions ||= endpoint.available_versions
88
+ config.api_version_for(request.env, endpoint).tap do |_version|
89
+ version ||= _version
90
+ end
91
+ end
92
+
93
+ if definition == DefinitionFinder::NoDefinitionFound
94
+ config.request_version_unavailable(app, version, available_versions)
95
+ end
96
+
97
+ definition
83
98
  end
84
99
 
85
100
  # Sinatra includes a couple of "meta" params that are always
86
101
  # present in the params hash even though they are not declared
87
102
  # as params: splat and captures.
88
103
  def params_to_parse
89
- unparsed_params.dup.tap do |p|
104
+ app.unparsed_params.dup.tap do |p|
90
105
  p.delete('splat')
91
106
  p.delete('captures')
92
107
  end
93
108
  end
109
+
110
+ def request_params_invalid(error)
111
+ config.sinatra_request_params_invalid(app, error)
112
+ end
94
113
  end
95
114
 
96
115
  module SinatraOverriddes
116
+ extend Forwardable
117
+ def_delegators :settings, :request_params_parser
118
+
97
119
  # We cannot access the full params (w/ path params) in a before hook,
98
120
  # due to the order that sinatra runs the hooks in relation to route
99
121
  # matching.
@@ -115,6 +137,17 @@ module Interpol
115
137
  return true unless block.respond_to?(:source_location)
116
138
  block.source_location.first.end_with?('sinatra/base.rb')
117
139
  end
140
+
141
+ def params
142
+ @_parsed_params || super
143
+ end
144
+
145
+ def with_parsed_params
146
+ @_parsed_params = request_params_parser.validate_and_parse_params(self)
147
+ yield
148
+ ensure
149
+ @_parsed_params = nil
150
+ end
118
151
  end
119
152
  end
120
153
  end
@@ -13,29 +13,17 @@ module Interpol
13
13
  builder.app
14
14
  end
15
15
 
16
- module Helpers
17
- def interpol_config
18
- self.class.interpol_config
19
- end
20
-
21
- def example_for(endpoint, version, message_type)
22
- example = endpoint.find_example_for!(version, message_type)
23
- rescue NoEndpointDefinitionFoundError
24
- interpol_config.request_version_unavailable(self, version, endpoint.available_versions)
25
- else
26
- example.apply_filters(interpol_config.filter_example_data_blocks, request.env)
27
- end
28
- end
29
-
30
16
  # Private: Builds a stub sinatra app for the given interpol
31
17
  # configuration.
32
18
  class Builder
33
- attr_reader :app
19
+ attr_reader :app, :config
34
20
 
35
21
  def initialize(config)
22
+ builder = self
23
+ @config = config
24
+
36
25
  @app = ::Sinatra.new do
37
- set :interpol_config, config
38
- helpers Helpers
26
+ set :stub_app_builder, builder
39
27
  not_found { JSON.dump(:error => "The requested resource could not be found") }
40
28
  before { content_type "application/json;charset=utf-8" }
41
29
  get('/__ping') { JSON.dump(:message => "Interpol stub app running.") }
@@ -47,21 +35,31 @@ module Interpol
47
35
  end
48
36
 
49
37
  def build
50
- @app.interpol_config.endpoints.each do |endpoint|
38
+ config.endpoints.each do |endpoint|
51
39
  app.send(endpoint.method, endpoint.route, &endpoint_definition(endpoint))
52
40
  end
53
41
  end
54
42
 
55
43
  def endpoint_definition(endpoint)
56
44
  lambda do
57
- version = interpol_config.api_version_for(request.env, endpoint)
58
- message_type = 'response'
59
- example = example_for(endpoint, version, message_type)
45
+ example, version = settings.
46
+ stub_app_builder.
47
+ example_and_version_for(endpoint, self)
60
48
  example.validate!
61
49
  status endpoint.find_example_status_code_for!(version)
62
50
  JSON.dump(example.data)
63
51
  end
64
52
  end
53
+
54
+ def example_and_version_for(endpoint, app)
55
+ version = config.api_version_for(app.request.env, endpoint)
56
+ example = endpoint.find_example_for!(version, 'response')
57
+ rescue NoEndpointDefinitionFoundError
58
+ config.request_version_unavailable(app, version, endpoint.available_versions)
59
+ else
60
+ example.apply_filters(config.filter_example_data_blocks, app.request.env)
61
+ return example, version
62
+ end
65
63
  end
66
64
  end
67
65
  end
@@ -1,3 +1,3 @@
1
1
  module Interpol
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interpol
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -223,7 +223,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
223
223
  version: '0'
224
224
  segments:
225
225
  - 0
226
- hash: -4117955588587785690
226
+ hash: 2654545236171025309
227
227
  required_rubygems_version: !ruby/object:Gem::Requirement
228
228
  none: false
229
229
  requirements:
@@ -232,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
232
232
  version: '0'
233
233
  segments:
234
234
  - 0
235
- hash: -4117955588587785690
235
+ hash: 2654545236171025309
236
236
  requirements: []
237
237
  rubyforge_project:
238
238
  rubygems_version: 1.8.24