Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Workday/doc_my_routes
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.11.1
Choose a base ref
...
head repository: Workday/doc_my_routes
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 10 commits
  • 16 files changed
  • 4 contributors

Commits on Nov 22, 2016

  1. removing log line 'Tracking new route'

    It isnt giving much value and it liters the logs.
    punkle committed Nov 22, 2016
    Copy the full SHA
    f80ea1f View commit details
  2. Merge pull request #14 from punkle/remove_log_line

    removing log line 'Tracking new route'
    captbirdsi authored Nov 22, 2016
    Copy the full SHA
    1c887d3 View commit details

Commits on May 26, 2017

  1. Add documentation for parameters

      - adds new annotation method `parameter`
      - adds default `in` option set to `:path` and `:required` for
        parameters specified in the route path
      - adds documentation for parameter description from options:
         parameter name, description: 'parameter description'
    vasyl-purchel committed May 26, 2017
    Copy the full SHA
    b4001f7 View commit details
  2. Copy the full SHA
    d212618 View commit details

Commits on Jun 9, 2017

  1. Updating parameters template to expand the table

      - expands table for parameters to include columns for required, type, location data instead of showing it in first column
    vasyl-purchel committed Jun 9, 2017
    Copy the full SHA
    e35e762 View commit details
  2. Copy the full SHA
    0d3f0de View commit details

Commits on Jun 15, 2017

  1. Merge pull request #15 from vasyl-purchel/master

    Add documentation for parameters
    punkle authored Jun 15, 2017
    Copy the full SHA
    33207ea View commit details

Commits on Jul 14, 2017

  1. Copy the full SHA
    eb3335f View commit details

Commits on Jul 21, 2017

  1. Merge pull request #16 from roryflynn/namespace_multiroute_support

    Add support for sinatra/namespace and sinatra/multi_route
    punkle authored Jul 21, 2017
    Copy the full SHA
    27bf2b8 View commit details
  2. Release v.0.13.0

    punkle committed Jul 21, 2017
    Copy the full SHA
    2198c2d View commit details
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -2,4 +2,4 @@ language: ruby
rvm:
- 2.1.5
- 2.1.7
before_install: gem install bundler -v 1.10.5
before_install: gem install bundler -v 1.15.0
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changes

### 2017-07-21 (0.13.0)

* Adds support for sinatra/namespace and sinatra/multi_route

### 2016-11-18 (0.11.1)

Bug fixing
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -64,6 +64,7 @@ class MyApp < Sinatra::Base
notes 'Simple route that gets an ID and returns a string'
produces 'text/plain'
status_codes [200]
parameter :id, description: 'some ID'
get '/:id' do |id|
"Received #{id}"
end
1 change: 1 addition & 0 deletions doc_my_routes.gemspec
Original file line number Diff line number Diff line change
@@ -25,5 +25,6 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'rack-test', '>= 0.6.2'
spec.add_development_dependency 'rubocop', '>= 0.16'
spec.add_development_dependency 'sinatra'
spec.add_development_dependency 'sinatra-contrib'
spec.add_development_dependency 'nokogiri'
end
4 changes: 2 additions & 2 deletions etc/css/base.css
Original file line number Diff line number Diff line change
@@ -248,7 +248,7 @@ table
table td
{
border-top:1px solid #ccc;
padding:.5em .5em .5em 0;
padding:.5em 1.5em .5em 0;
}

thead
@@ -282,4 +282,4 @@ article.example
{
color:#555;
margin:1em;
}
}
12 changes: 10 additions & 2 deletions etc/partial.html.erb
Original file line number Diff line number Diff line change
@@ -48,12 +48,20 @@
<thead>
<tr>
<th>Parameter</th>
<th>Required</th>
<th>Location</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody class="operation-params">
<% route[:parameters].each do |param| %>
<% route[:parameters].each do |param_name, param_options| %>
<tr>
<td><%= param %></td>
<td><%= param_name %></td>
<td><%= param_options[:required] ? 'Yes' : 'No' %></td>
<td><%= param_options[:in] %></td>
<td><%= param_options[:type] %></td>
<td><%= param_options[:description] %></td>
</tr>
<% end %>
</tbody>
16 changes: 16 additions & 0 deletions lib/doc_my_routes/doc/hash_helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module DocMyRoutes
# Define hash helpers for deep hash merge and transforming hash into array of keys
module HashHelpers
def self.deep_merge(first_hash, second_hash)
merger = proc do |key, first, second|
first.is_a?(Hash) && second.is_a?(Hash) ? first.merge(second, &merger) : second
end

first_hash.merge(second_hash, &merger)
end

def self.array_to_hash_keys(arr, default_value = {})
{}.tap { |hash| arr.each { |key| hash[key] = default_value } }
end
end
end
28 changes: 21 additions & 7 deletions lib/doc_my_routes/doc/mixins/annotatable.rb
Original file line number Diff line number Diff line change
@@ -18,10 +18,21 @@ class << self
# features are enabled
def extended(mod)
# Wrap sinatra's route method to register the defined routes
mod.define_singleton_method(:route) do
|verb, route_pattern, conditions = {}, &block|
result = super(verb, route_pattern, conditions, &block)
track_route(self, verb, route_pattern, conditions)
mod.define_singleton_method(:route) do |*args, &block|
result = super(*args, &block)

options = args.last.is_a?(Hash) ? args.pop : {}
routes = [*args.pop].map(&:to_s) # ensure routes are strings
verbs = args.map { |verb| verb.is_a?(Symbol) ? verb.to_s.upcase : verb }

verbs.each do |verb|
routes.each do |route_pattern|
reset_doc = verb.equal?(verbs.last) && route_pattern.equal?(routes.last)

track_route(self, verb, route_pattern, options, reset_doc, &block)
end
end

result
end

@@ -52,7 +63,6 @@ def extract_url_map

def route_documentation
@route_documentation ||= begin
DocMyRoutes.logger.debug 'Tracking new route'
RouteDocumentation.new
end
end
@@ -88,9 +98,13 @@ def notes_ref(value)
route_documentation.notes_ref = value
end

def parameter(value, options = {})
route_documentation.add_parameter(value, options)
end

private

def track_route(resource, verb, route_pattern, conditions)
def track_route(resource, verb, route_pattern, conditions, reset_doc)
unless route_documentation.hidden? || skip_route(verb)
route = Route.new(resource, verb, route_pattern, conditions,
route_documentation)
@@ -99,7 +113,7 @@ def track_route(resource, verb, route_pattern, conditions)
end

# Ensure values are reset
reset_doc_values
reset_doc_values if reset_doc
end

# The summary, notes and status codes are only valid for one route
25 changes: 16 additions & 9 deletions lib/doc_my_routes/doc/route.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# encoding: utf-8

require 'forwardable'
require_relative 'hash_helpers'

module DocMyRoutes
# Simple object representing a route
@@ -22,12 +23,16 @@ def initialize(resource, verb, route_pattern, conditions, documentation)
@documentation = documentation
end

# We need to use deep merge as param_info method will return a hash for parameters
# with extracted information from the route path, and documentation might also have
# parameters with some more documentation and we don't want to loose extracted data
# from route path
def to_hash
{
HashHelpers.deep_merge({
http_method: verb,
parameters: param_info,
path: path
}.merge(documentation.to_hash)
}, documentation.to_hash)
end

def path
@@ -60,13 +65,15 @@ def to_s
#
# Try to extract parameters from the route definition otherwise
def param_info
if conditions[:parameters]
conditions[:parameters]
else
route_pattern.split('/').map do |part|
part.start_with?(':') ? part[1..-1].to_sym : nil
end.compact
end
path_parameters_array = route_pattern.split('/').map do |part|
part.start_with?(':') ? part[1..-1].to_sym : nil
end.compact

path_parameters = HashHelpers.array_to_hash_keys(path_parameters_array,
{ in: :path, required: true })
condition_parameters = HashHelpers.array_to_hash_keys(conditions[:parameters] || [])

HashHelpers.deep_merge(condition_parameters, path_parameters)
end
end
end
8 changes: 7 additions & 1 deletion lib/doc_my_routes/doc/route_documentation.rb
Original file line number Diff line number Diff line change
@@ -3,12 +3,13 @@ module DocMyRoutes
class RouteDocumentation
attr_accessor :summary, :notes, :status_codes, :examples_regex, :hidden,
:produces, :notes_ref
attr_reader :examples
attr_reader :examples, :parameters

def initialize
@status_codes = { 200 => DocMyRoutes::StatusCodeInfo::STATUS_CODES[200] }
@hidden = false
@produces = []
@parameters = {}
end

# A route documentation object MUST have a summary, otherwise is not
@@ -25,6 +26,7 @@ def to_hash
examples_regex: examples_regex,
produces: produces,
examples: examples,
parameters: parameters,
hidden: hidden?
}
end
@@ -33,6 +35,10 @@ def produces=(values)
@produces = values.flatten.compact
end

def add_parameter(name, options)
@parameters[name] = options
end

def status_codes=(route_status_codes)
@status_codes = Hash[route_status_codes.map do |code|
[code, DocMyRoutes::StatusCodeInfo::STATUS_CODES[code]]
2 changes: 1 addition & 1 deletion lib/doc_my_routes/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# DocMyRoutes version
module DocMyRoutes
VERSION = '0.11.1'
VERSION = '0.13.0'
end
24 changes: 24 additions & 0 deletions spec/support/multirouteapp.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'sinatra/base'
require 'sinatra/multi_route'
require 'doc_my_routes'

module DocMyRoutes::Test
# App that utilises sinatra/multiroute
class MultirouteApp < Sinatra::Base
register Sinatra::MultiRoute

extend DocMyRoutes::Annotatable

get '/get_a', '/get_b' do
'GET A and GET B'
end

post '/post_a', '/post_b' do
'POST A and POST B'
end

route :get, :post, ['/get_or_post_a', '/get_or_post_b'] do
'GET/POST A and GET/POST B'
end
end
end
37 changes: 37 additions & 0 deletions spec/support/namespaceapp.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require 'sinatra/base'
require 'sinatra/namespace'
require 'doc_my_routes'

module DocMyRoutes::Test
# App with nested namespaces that uses DocMyRoutes
class NamespaceApp < Sinatra::Base
register Sinatra::Namespace

extend DocMyRoutes::Annotatable

DocMyRoutes.configure do |config|
config.title = 'Test application'
config.description = 'Example application to test DocMyRoutes'
end

namespace '/path_a' do
namespace '/subpath_1' do
summary 'Example GET'
notes 'Creates an example GET route that returns hello'
status_codes [200]
get '/sample_get' do
[200, {}, ['Hello from GET!']]
end
end

namespace '/subpath_2' do
summary 'Example POST'
notes 'Creates an example POST route that returns hello'
status_codes [200]
post '/sample_post' do
[200, {}, ['Hello from POST!']]
end
end
end
end
end
46 changes: 46 additions & 0 deletions spec/system/multiroute_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Encoding: UTF-8

require 'rspec/mocks'
require_relative '../spec_helper.rb'

describe 'Given an application utilising sinatra/multi_route' do
include Rack::Test::Methods

before do
# The tests are only focused on the route created in each context
# without taking into consideration the real DocMyRoutes routes
DocMyRoutes::RouteCollection.routes.clear
reload_app('multirouteapp')
end

let(:app_name) { 'DocMyRoutes::Test::MultirouteApp' }

context 'its routes' do
subject { DocMyRoutes::RouteCollection.routes[app_name] }

it 'contain all specified verbs' do
expect(subject.size).to be(8)
expect(subject.map(&:verb)).to eq(
%w[GET GET POST POST GET GET POST POST]
)
end

it 'have correct route patterns' do
expect(subject.map(&:route_pattern)).to eq(
['/get_a',
'/get_b',
'/post_a',
'/post_b',
'/get_or_post_a',
'/get_or_post_b',
'/get_or_post_a',
'/get_or_post_b']
)
end

it 'are not namespaced' do
# Namespaces are currently used for Sinatra Child Apps only
expect(subject.map(&:namespace)).to eq(Array.new(8, nil))
end
end
end
35 changes: 35 additions & 0 deletions spec/system/namespace_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Encoding: UTF-8

require 'rspec/mocks'
require_relative '../spec_helper.rb'

describe 'Given an application with nested namespaces' do
include Rack::Test::Methods

before do
# The tests are only focused on the route created in each context
# without taking into consideration the real DocMyRoutes routes
DocMyRoutes::RouteCollection.routes.clear
reload_app('namespaceapp')
end

let(:app_name) { 'DocMyRoutes::Test::NamespaceApp' }

context 'its routes' do
subject { DocMyRoutes::RouteCollection.routes[app_name] }

it 'contain only a GET and a POST route' do
expect(subject.size).to be(2)
expect(subject.map(&:verb)).to eq(['GET', 'POST'])
end

it 'have correct route patterns' do
expect(subject.map(&:route_pattern)).to eq(['/path_a/subpath_1/sample_get', '/path_a/subpath_2/sample_post'])
end

it 'are not namespaced' do
# Namespaces are currently used for Sinatra Child Apps only
expect(subject.map(&:namespace)).to eq([nil, nil])
end
end
end
Loading