Module: Rails::Swagger
- Defined in:
- lib/rails/swagger.rb,
lib/rails/swagger/engine.rb,
lib/rails/swagger/router.rb,
lib/rails/swagger/controller.rb
Defined Under Namespace
Modules: Controller Classes: Endpoint, Engine, Router
Constant Summary collapse
- ALLOWED_FORMATS =
Defines the Swagger spec file formats that are parsable by this gem. Currently only the JSON format is supported.
[".json"].freeze
- RESOURCE_ROUTES =
Defines RESTful routing conventions
{ get: :index, post: :create }.freeze
- PARAM_ROUTES =
{ get: :show, patch: :update, put: :update, delete: :destroy }.freeze
Class Method Summary collapse
-
.Engine(base_module, file) ⇒ Object
Helper method to create a new engine based on a module namespace prefix and Swagger spec file.
Class Method Details
.Engine(base_module, file) ⇒ Object
Helper method to create a new engine based on a module namespace prefix and Swagger spec file. The engine ceated will be a subclass of Rails::Swagger::Engine, which itself inherits from Rails::Engine.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/rails/swagger/engine.rb', line 19 def self.Engine base_module, file # Convert the module prefix into a constant if passed in as a string base_module = Object.const_get base_module if String === base_module # Ensure the Swagger spec file is in an acceptable format ext = File.extname(file) unless ALLOWED_FORMATS.include? ext raise "Swagger files must end with #{ALLOWED_FORMATS.join(' or ')}. File given: #{file}" end # Attempt to read and parse the Swagger spec file document = File.read file case File.extname file when ".json" begin require 'json' document = JSON.parse document rescue JSON::ParserError raise $!, "Problem parsing swagger spec file \"#{file}\": #{$!..lines.first.strip}", $@ end else raise "Swagger files must end with #{ALLOWED_FORMATS.join(' or ')}. File given: #{file}" end # Verify that the swagger version is supported unless document["swagger"] == "2.0" raise "Unsupported swagger version: #{document["swagger"]}. #{self} supports only version 2.0" end # Builds a routing tree based on the swagger spec file. # We'll add each endpoint to the routing tree and additionally # store it in an array to be used below. router = Router.new endpoints = [] document["paths"].each do |url, actions| actions.each do |verb, definition| route = Endpoint.new(verb.downcase.to_sym, url, definition) router << route endpoints << route end end # Creates the engine that will be used to actually route the # contents of the swagger spec file. The engine will eventually be # attached to the base module (argument to this current method). # # Exposes `::router` and `::endpoints` methods to allow other parts # of the code to tie requests back to their spec file definitions. engine = Class.new Engine do @router = router @endpoints = Hash.new @schema = document class << self def router @router end def endpoints @endpoints end def schema @schema end end # Rack app for serving the original swagger file # swagger_app = Class.new do # def inspect # "Rails::Swagger::Engine" # end # define_method :call do |env| # [ # 200, # {"Content-Type" => "application/json"}, # [engine.schema.to_json] # ] # end # end # Adds routes to the engine by passing the Mapper to the top # of the routing tree. `self` inside the block refers to an # instance of `ActionDispatch::Routing::Mapper`. self.routes.draw do scope module: base_module.name.underscore, format: false do # get "swagger.json", to: swagger_app.new router.draw self end end end # Assign the engine as a class on the base module base_module.const_set :Engine, engine # Creates a hash that maps routes back to their swagger spec file # equivalents. This is accomplished by mocking a request for each # swagger spec file endpoint and determining which controller and # action the request is routed to. Swagger spec file definitions # are then attached to that controller/action pair. endpoints.each do |route| # Mocks a request using the route's URL url = ::ActionDispatch::Journey::Router::Utils.normalize_path route.path env = ::Rack::MockRequest.env_for url, method: route[:method].upcase req = ::ActionDispatch::Request.new env # Maps the swagger spec endpoint to the destination controller # action by routing the request. mapped = engine.routes.router.recognize(req){}.first[1] key = "#{mapped[:controller]}##{mapped[:action]}" engine.endpoints[key] = route end engine.endpoints.freeze # Defines a helper module on the base module that can be used to # properly generate swagger-aware controllers. Any controllers # referenced from a swagger spec file should include this module. mod = Module.new do @base = base_module def self.included controller base_module = @base controller.include Controller define_method :swagger_engine do base_module.const_get :Engine end end end base_module.const_set :SwaggerController, mod # Returns the new engine base_module.const_get :Engine end |