Skip to content

Commit fc17db7

Browse files
committed
Merge pull request #29 from zipmark/dsl_split
Split up DSL into resource/endpoint/callback concerns. Ref #28
2 parents ebae41c + 8691bdc commit fc17db7

File tree

4 files changed

+234
-208
lines changed

4 files changed

+234
-208
lines changed

Diff for: lib/rspec_api_documentation/dsl.rb

+7-208
Original file line numberDiff line numberDiff line change
@@ -1,218 +1,17 @@
1-
require 'rspec/core/formatters/base_formatter'
2-
3-
module RspecApiDocumentation
4-
module DSL
5-
extend ActiveSupport::Concern
6-
7-
delegate :response_headers, :status, :response_body, :to => :client
8-
delegate :request_method, :request_headers, :request_body, :to => :destination
9-
10-
module ClassMethods
11-
def self.define_action(method)
12-
define_method method do |*args, &block|
13-
options = if args.last.is_a?(Hash) then args.pop else {} end
14-
options[:method] = method
15-
options[:route] = args.first
16-
args.push(options)
17-
args[0] = "#{method.to_s.upcase} #{args[0]}"
18-
context(*args, &block)
19-
end
20-
end
21-
22-
define_action :get
23-
define_action :post
24-
define_action :put
25-
define_action :delete
26-
27-
def parameter(name, description, options = {})
28-
parameters.push(options.merge(:name => name.to_s, :description => description))
29-
end
30-
31-
def required_parameters(*names)
32-
names.each do |name|
33-
param = parameters.find { |param| param[:name] == name.to_s }
34-
raise "Undefined parameters can not be required." unless param
35-
param[:required] = true
36-
end
37-
end
38-
39-
def callback(description, &block)
40-
require 'webmock'
41-
self.send(:include, WebMock::API)
42-
context(description, &block)
43-
end
44-
45-
def trigger_callback(&block)
46-
define_method(:do_callback) do
47-
require 'rack'
48-
stub_request(:any, callback_url).to_rack(destination)
49-
instance_eval &block
50-
end
51-
end
52-
53-
def scope_parameters(scope, keys)
54-
return unless metadata[:parameters]
55-
56-
if keys == :all
57-
keys = parameter_keys.map(&:to_s)
58-
else
59-
keys = keys.map(&:to_s)
60-
end
61-
62-
keys.each do |key|
63-
param = parameters.detect { |param| param[:name] == key }
64-
param[:scope] = scope if param
65-
end
66-
end
67-
68-
def example_request(description, params = {}, &block)
69-
file_path = caller.first[0, caller.first =~ /:/]
70-
71-
location = caller.first[0, caller.first =~ /(:in|$)/]
72-
location = RSpec::Core::Formatters::BaseFormatter::relative_path(location)
73-
74-
example description, :location => location, :file_path => file_path do
75-
do_request(params)
76-
instance_eval &block if block_given?
77-
end
78-
end
79-
80-
private
81-
def parameters
82-
metadata[:parameters] ||= []
83-
if superclass_metadata && metadata[:parameters].equal?(superclass_metadata[:parameters])
84-
metadata[:parameters] = Marshal.load(Marshal.dump(superclass_metadata[:parameters]))
85-
end
86-
metadata[:parameters]
87-
end
88-
89-
def parameter_keys
90-
parameters.map { |param| param[:name] }
91-
end
92-
end
93-
94-
def client
95-
@client ||= RackTestClient.new(self)
96-
end
97-
98-
def destination
99-
@destination ||= TestServer.new(self)
100-
end
101-
102-
def callback_url
103-
raise "You must define callback_url"
104-
end
105-
106-
def do_request(extra_params = {})
107-
@extra_params = extra_params
108-
109-
params_or_body = nil
110-
path_or_query = path
111-
112-
if method == :get && !query_string.blank?
113-
path_or_query = path + "?#{query_string}"
114-
else
115-
params_or_body = respond_to?(:raw_post) ? raw_post : params
116-
end
117-
118-
client.send(method, path_or_query, params_or_body)
119-
end
120-
121-
def no_doc(&block)
122-
requests = example.metadata[:requests]
123-
example.metadata[:requests] = []
124-
125-
instance_eval &block
126-
127-
example.metadata[:requests] = requests
128-
end
129-
130-
def query_string
131-
query = params.to_a.map do |param|
132-
param.map! { |a| CGI.escape(a.to_s) }
133-
param.join("=")
134-
end
135-
query.join("&")
136-
end
137-
138-
def params
139-
return unless example.metadata[:parameters]
140-
parameters = example.metadata[:parameters].inject({}) do |hash, param|
141-
set_param(hash, param)
142-
end
143-
parameters.merge!(extra_params)
144-
parameters
145-
end
146-
147-
def method
148-
example.metadata[:method]
149-
end
150-
151-
def in_path?(param)
152-
path_params.include?(param)
153-
end
154-
155-
def path_params
156-
example.metadata[:route].scan(/:(\w+)/).flatten
157-
end
158-
159-
def path
160-
example.metadata[:route].gsub(/:(\w+)/) do |match|
161-
if extra_params.keys.include?($1)
162-
delete_extra_param($1)
163-
elsif respond_to?($1)
164-
send($1)
165-
else
166-
match
167-
end
168-
end
169-
end
170-
171-
def app
172-
RspecApiDocumentation.configuration.app
173-
end
174-
175-
def explanation(text)
176-
example.metadata[:explanation] = text
177-
end
178-
179-
private
180-
def extra_params
181-
return {} if @extra_params.nil?
182-
@extra_params.inject({}) do |h, (k, v)|
183-
h[k.to_s] = v
184-
h
185-
end
186-
end
187-
188-
def delete_extra_param(key)
189-
@extra_params.delete(key.to_sym) || @extra_params.delete(key.to_s)
190-
end
191-
192-
def set_param(hash, param)
193-
key = param[:name]
194-
return hash if !respond_to?(key) || in_path?(key)
195-
196-
if param[:scope]
197-
hash[param[:scope].to_s] ||= {}
198-
hash[param[:scope].to_s][key] = send(key)
199-
else
200-
hash[key] = send(key)
201-
end
202-
203-
hash
204-
end
205-
end
206-
end
1+
require "rspec_api_documentation/dsl/resource"
2+
require "rspec_api_documentation/dsl/endpoint"
3+
require "rspec_api_documentation/dsl/callback"
2074

2085
def self.resource(*args, &block)
2096
options = if args.last.is_a?(Hash) then args.pop else {} end
210-
options[:api_docs_dsl] = true
7+
options[:api_doc_dsl] = :resource
2118
options[:resource_name] = args.first
2129
options[:document] ||= :all
21310
args.push(options)
21411
describe(*args, &block)
21512
end
21613

217-
RSpec.configuration.include RspecApiDocumentation::DSL, :api_docs_dsl => true
14+
RSpec.configuration.include RspecApiDocumentation::DSL::Resource, :api_doc_dsl => :resource
15+
RSpec.configuration.include RspecApiDocumentation::DSL::Endpoint, :api_doc_dsl => :endpoint
16+
RSpec.configuration.include RspecApiDocumentation::DSL::Callback, :api_doc_dsl => :callback
21817
RSpec.configuration.backtrace_clean_patterns << %r{lib/rspec_api_documentation/dsl\.rb}

Diff for: lib/rspec_api_documentation/dsl/callback.rb

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module RspecApiDocumentation::DSL
2+
module Callback
3+
extend ActiveSupport::Concern
4+
5+
delegate :request_method, :request_headers, :request_body, :to => :destination
6+
7+
module ClassMethods
8+
def trigger_callback(&block)
9+
define_method(:do_callback) do
10+
require 'rack'
11+
stub_request(:any, callback_url).to_rack(destination)
12+
instance_eval &block
13+
end
14+
end
15+
end
16+
17+
def destination
18+
@destination ||= RspecApiDocumentation::TestServer.new(self)
19+
end
20+
21+
def callback_url
22+
raise "You must define callback_url"
23+
end
24+
end
25+
end

Diff for: lib/rspec_api_documentation/dsl/endpoint.rb

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
require 'rspec/core/formatters/base_formatter'
2+
3+
module RspecApiDocumentation::DSL
4+
module Endpoint
5+
extend ActiveSupport::Concern
6+
7+
delegate :response_headers, :status, :response_body, :to => :client
8+
9+
module ClassMethods
10+
def example_request(description, params = {}, &block)
11+
file_path = caller.first[0, caller.first =~ /:/]
12+
13+
location = caller.first[0, caller.first =~ /(:in|$)/]
14+
location = RSpec::Core::Formatters::BaseFormatter::relative_path(location)
15+
16+
example description, :location => location, :file_path => file_path do
17+
do_request(params)
18+
instance_eval &block if block_given?
19+
end
20+
end
21+
end
22+
23+
def do_request(extra_params = {})
24+
@extra_params = extra_params
25+
26+
params_or_body = nil
27+
path_or_query = path
28+
29+
if method == :get && !query_string.blank?
30+
path_or_query = path + "?#{query_string}"
31+
else
32+
params_or_body = respond_to?(:raw_post) ? raw_post : params
33+
end
34+
35+
client.send(method, path_or_query, params_or_body)
36+
end
37+
38+
def query_string
39+
query = params.to_a.map do |param|
40+
param.map! { |a| CGI.escape(a.to_s) }
41+
param.join("=")
42+
end
43+
query.join("&")
44+
end
45+
46+
def params
47+
return unless example.metadata[:parameters]
48+
parameters = example.metadata[:parameters].inject({}) do |hash, param|
49+
set_param(hash, param)
50+
end
51+
parameters.merge!(extra_params)
52+
parameters
53+
end
54+
55+
def method
56+
example.metadata[:method]
57+
end
58+
59+
def in_path?(param)
60+
path_params.include?(param)
61+
end
62+
63+
def path_params
64+
example.metadata[:route].scan(/:(\w+)/).flatten
65+
end
66+
67+
def path
68+
example.metadata[:route].gsub(/:(\w+)/) do |match|
69+
if extra_params.keys.include?($1)
70+
delete_extra_param($1)
71+
elsif respond_to?($1)
72+
send($1)
73+
else
74+
match
75+
end
76+
end
77+
end
78+
79+
def explanation(text)
80+
example.metadata[:explanation] = text
81+
end
82+
83+
private
84+
def extra_params
85+
return {} if @extra_params.nil?
86+
@extra_params.inject({}) do |h, (k, v)|
87+
h[k.to_s] = v
88+
h
89+
end
90+
end
91+
92+
def delete_extra_param(key)
93+
@extra_params.delete(key.to_sym) || @extra_params.delete(key.to_s)
94+
end
95+
96+
def set_param(hash, param)
97+
key = param[:name]
98+
return hash if !respond_to?(key) || in_path?(key)
99+
100+
if param[:scope]
101+
hash[param[:scope].to_s] ||= {}
102+
hash[param[:scope].to_s][key] = send(key)
103+
else
104+
hash[key] = send(key)
105+
end
106+
107+
hash
108+
end
109+
end
110+
end

0 commit comments

Comments
 (0)