Skip to content

Commit

Permalink
Merge pull request #312 from sineed/sineed-custom-parameter-method
Browse files Browse the repository at this point in the history
Custom parameter method
  • Loading branch information
oestrich authored Dec 8, 2016
2 parents 470da85 + 2b79b8a commit ba62ae1
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 43 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,12 @@ Special values:

* `:required => true` Will display a red '*' to show it's required
* `:scope => :the_scope` Will scope parameters in the hash, scoping can be nested. See example
* `:method => :method_name` Will use specified method as a parameter value

The value of scoped parameters can be set with both scoped (`let(:order_item_item_id)`) and unscoped (`let(:item_id)`) methods. It always searches for the scoped method first and falls back to the unscoped method.
Retrieving of parameter value goes through several steps:
1. if `method` option is defined and test case responds to this method then this method is used;
2. if test case responds to scoped method then this method is used;
3. overwise unscoped method is used.

```ruby
resource "Orders" do
Expand All @@ -428,10 +432,13 @@ resource "Orders" do
post "/orders" do
parameter :name, "Order Name", :required => true, :scope => :order
parameter :item, "Order items", :scope => :order
parameter :item_id, "Item id", :scope => [:order, :item]
parameter :item_id, "Item id", :scope => [:order, :item], method: :custom_item_id

let(:name) { "My Order" } # OR let(:order_name) { "My Order" }
let(:item_id) { 1 } # OR let(:order_item_item_id) { 1 }
let(:name) { "My Order" }
# OR let(:order_name) { "My Order" }
let(:item_id) { 1 }
# OR let(:custom_item_id) { 1 }
# OR let(:order_item_item_id) { 1 }

example "Creating an order" do
params.should eq({
Expand Down
36 changes: 2 additions & 34 deletions lib/rspec_api_documentation/dsl/endpoint.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require 'rspec/core/formatters/base_formatter'
require 'rack/utils'
require 'rack/test/utils'
require 'rspec_api_documentation/dsl/endpoint/params'

module RspecApiDocumentation::DSL
# DSL methods available inside the RSpec example.
Expand Down Expand Up @@ -63,11 +64,7 @@ def query_string
end

def params
parameters = example.metadata.fetch(:parameters, {}).inject({}) do |hash, param|
set_param(hash, param)
end
parameters.deep_merge!(extra_params)
parameters
Params.new(self, example, extra_params).call
end

def header(name, value)
Expand Down Expand Up @@ -99,14 +96,6 @@ def status
rspec_api_documentation_client.status
end

def in_path?(param)
path_params.include?(param)
end

def path_params
example.metadata[:route].scan(/:(\w+)/).flatten
end

def path
example.metadata[:route].gsub(/:(\w+)/) do |match|
if extra_params.keys.include?($1)
Expand Down Expand Up @@ -146,26 +135,5 @@ def delete_extra_param(key)
@extra_params.delete(key.to_sym) || @extra_params.delete(key.to_s)
end

def set_param(hash, param)
key = param[:name]

keys = [param[:scope], key].flatten.compact
method_name = keys.join('_')

return hash if in_path?(method_name)

unless respond_to?(method_name)
method_name = key
return hash unless respond_to?(method_name)
end

hash.deep_merge(build_param_hash(keys, method_name))
end

def build_param_hash(keys, method_name)
value = keys[1] ? build_param_hash(keys[1..-1], method_name) : send(method_name)
{ keys[0].to_s => value }
end

end
end
30 changes: 30 additions & 0 deletions lib/rspec_api_documentation/dsl/endpoint/params.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require 'rspec_api_documentation/dsl/endpoint/set_param'

module RspecApiDocumentation
module DSL
module Endpoint
class Params
attr_reader :example_group, :example

def initialize(example_group, example, extra_params)
@example_group = example_group
@example = example
@extra_params = extra_params
end

def call
parameters = example.metadata.fetch(:parameters, {}).inject({}) do |hash, param|
SetParam.new(self, hash, param).call
end
parameters.deep_merge!(extra_params)
parameters
end

private

attr_reader :extra_params

end
end
end
end
62 changes: 62 additions & 0 deletions lib/rspec_api_documentation/dsl/endpoint/set_param.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module RspecApiDocumentation
module DSL
module Endpoint
class SetParam
def initialize(parent, hash, param)
@parent = parent
@hash = hash
@param = param
end

def call
return hash if path_params.include?(path_name)
return hash unless method_name

hash.deep_merge build_param_hash(key_scope || [key])
end

private

attr_reader :parent, :hash, :param
delegate :example_group, :example, to: :parent

def key
@key ||= param[:name]
end

def key_scope
@key_scope ||= param[:scope] && Array(param[:scope]).dup.push(key)
end

def scoped_key
@scoped_key ||= key_scope && key_scope.join('_')
end

def custom_method_name
param[:method]
end

def path_name
scoped_key || key
end

def path_params
example.metadata[:route].scan(/:(\w+)/).flatten
end

def method_name
@method_name ||= begin
[custom_method_name, scoped_key, key].find do |name|
name && example_group.respond_to?(name)
end
end
end

def build_param_hash(keys)
value = keys[1] ? build_param_hash(keys[1..-1]) : example_group.send(method_name)
{ keys[0].to_s => value }
end
end
end
end
end
21 changes: 16 additions & 5 deletions spec/dsl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
post "/orders" do
parameter :type, "The type of drink you want.", :required => true
parameter :size, "The size of drink you want.", :required => true
parameter :note, "Any additional notes about your order."
parameter :name, :scope => :order
parameter :note, "Any additional notes about your order.", method: :custom_note
parameter :name, :scope => :order, method: :custom_order_name

response_field :type, "The type of drink you ordered.", :scope => :order
response_field :size, "The size of drink you ordered.", :scope => :order
Expand All @@ -71,6 +71,12 @@
let(:type) { "coffee" }
let(:size) { "medium" }

let(:note) { "Made in Brazil" }
let(:custom_note) { "Made in India" }

let(:order_name) { "Nescoffee" }
let(:custom_order_name) { "Jakobz" }

describe "example metadata" do
subject { |example| example.metadata }

Expand All @@ -79,8 +85,8 @@
[
{ :name => "type", :description => "The type of drink you want.", :required => true },
{ :name => "size", :description => "The size of drink you want.", :required => true },
{ :name => "note", :description => "Any additional notes about your order." },
{ :name => "name", :description => "Order name", :scope => :order},
{ :name => "note", :description => "Any additional notes about your order.", method: :custom_note },
{ :name => "name", :description => "Order name", :scope => :order, method: :custom_order_name },
]
)
end
Expand All @@ -103,7 +109,12 @@

describe "params" do
it "should equal the assigned parameter values" do
expect(params).to eq("type" => "coffee", "size" => "medium")
expect(params).to eq({
"type" => "coffee",
"size" => "medium",
"note" => "Made in India",
"order" => { "name" => "Jakobz" }
})
end
end
end
Expand Down

0 comments on commit ba62ae1

Please sign in to comment.