Commit d6f8e09e authored by Zac Wood's avatar Zac Wood

Moved from RSpec APi Docs to Apipie

this is sooooo much nicer and easier to work with
parent 902cbaca
Pipeline #2834 failed with stage
in 2 minutes and 4 seconds
...@@ -11,4 +11,3 @@ ENV RAILS_ENV production ...@@ -11,4 +11,3 @@ ENV RAILS_ENV production
RUN bundle install RUN bundle install
RUN rails db:migrate RUN rails db:migrate
RUN rails db:seed RUN rails db:seed
RUN rails docs:generate
...@@ -65,11 +65,4 @@ gem 'rubyXL' ...@@ -65,11 +65,4 @@ gem 'rubyXL'
# Linting # Linting
gem "rubocop", "~> 0.58.2" gem "rubocop", "~> 0.58.2"
# RSpec gem 'apipie-rails'
gem 'rspec-rails'
# Generate API documentation
gem 'rspec_api_documentation'
# Pretty API docs
gem "apitome"
...@@ -40,9 +40,8 @@ GEM ...@@ -40,9 +40,8 @@ GEM
tzinfo (~> 1.1) tzinfo (~> 1.1)
addressable (2.5.2) addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0) public_suffix (>= 2.0.2, < 4.0)
apitome (0.2.0) apipie-rails (0.5.10)
kramdown rails (>= 4.1)
railties
arel (8.0.0) arel (8.0.0)
ast (2.4.0) ast (2.4.0)
bindex (0.5.0) bindex (0.5.0)
...@@ -60,7 +59,6 @@ GEM ...@@ -60,7 +59,6 @@ GEM
coderay (1.1.2) coderay (1.1.2)
concurrent-ruby (1.0.5) concurrent-ruby (1.0.5)
crass (1.0.4) crass (1.0.4)
diff-lcs (1.3)
erubi (1.7.1) erubi (1.7.1)
ffi (1.9.25) ffi (1.9.25)
globalid (0.4.1) globalid (0.4.1)
...@@ -74,7 +72,6 @@ GEM ...@@ -74,7 +72,6 @@ GEM
jbuilder (2.7.0) jbuilder (2.7.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
multi_json (>= 1.2) multi_json (>= 1.2)
kramdown (1.17.0)
listen (3.1.5) listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4) rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7) rb-inotify (~> 0.9, >= 0.9.7)
...@@ -90,7 +87,6 @@ GEM ...@@ -90,7 +87,6 @@ GEM
minitest (5.11.3) minitest (5.11.3)
multi_json (1.13.1) multi_json (1.13.1)
multi_xml (0.6.0) multi_xml (0.6.0)
mustache (1.0.5)
nio4r (2.3.1) nio4r (2.3.1)
nokogiri (1.8.3) nokogiri (1.8.3)
mini_portile2 (~> 2.3.0) mini_portile2 (~> 2.3.0)
...@@ -138,31 +134,6 @@ GEM ...@@ -138,31 +134,6 @@ GEM
rb-fsevent (0.10.3) rb-fsevent (0.10.3)
rb-inotify (0.9.10) rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2) ffi (>= 0.5.0, < 2)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-rails (3.8.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
rspec_api_documentation (6.0.0)
activesupport (>= 3.0.0)
mustache (~> 1.0, >= 0.99.4)
rspec (~> 3.0)
rubocop (0.58.2) rubocop (0.58.2)
jaro_winkler (~> 1.5.1) jaro_winkler (~> 1.5.1)
parallel (~> 1.10) parallel (~> 1.10)
...@@ -229,7 +200,7 @@ PLATFORMS ...@@ -229,7 +200,7 @@ PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
apitome apipie-rails
byebug byebug
capybara (~> 2.13) capybara (~> 2.13)
httparty httparty
...@@ -242,8 +213,6 @@ DEPENDENCIES ...@@ -242,8 +213,6 @@ DEPENDENCIES
puma (~> 3.7) puma (~> 3.7)
rack-cors rack-cors
rails (~> 5.1.6) rails (~> 5.1.6)
rspec-rails
rspec_api_documentation
rubocop (~> 0.58.2) rubocop (~> 0.58.2)
rubyXL rubyXL
sass-rails (~> 5.0) sass-rails (~> 5.0)
......
# Contains all actions having to do with CourseSections. # Contains all actions having to do with CourseSections.
# This is a nested controller -- see +config/routes.rb+ for details # This is a nested controller -- see +config/routes.rb+ for details
class CourseSectionsController < ApplicationController class CourseSectionsController < ApplicationController
# Render JSON of all Sections belonging to a given Course. resource_description do
short 'Working with course sections, e.g. CS 112 001'
end
api :GET, '/courses_sections', 'Get a list of course sections'
param :course_id, Fixnum, desc: "Only get the course sections belonging to the course with this ID"
param :crn, String, desc: "Get the course section with this CRN"
def index def index
@sections = CourseSection.all @sections = CourseSection.all
......
# Contains all actions having to do with Courses. # Contains all actions having to do with Courses.
class CoursesController < ApplicationController class CoursesController < ApplicationController
# Renders JSON of courses matching params. resource_description do
short 'Working with courses, e.g. CS 112'
end
api :GET, '/courses', "Get a list of courses."
param :subject, String, desc: 'Course subject, e.g. "CS" or "ACCT"'
param :course_number, :number, desc: 'Course number, e.g. "112"'
def index def index
@courses = Course.all @courses = Course.all
...@@ -12,6 +18,8 @@ class CoursesController < ApplicationController ...@@ -12,6 +18,8 @@ class CoursesController < ApplicationController
end end
# Renders JSON of details of a singluar course, such as its sections # Renders JSON of details of a singluar course, such as its sections
api :GET, '/courses/:id', "Get a list of all course sections for the course with the given id."
param :id, :number, desc: 'Course ID', required: true
def show def show
@sections = CourseSection.where(course_id: params[:id]) @sections = CourseSection.where(course_id: params[:id])
......
...@@ -3,8 +3,13 @@ require 'time' ...@@ -3,8 +3,13 @@ require 'time'
# Contains functionality for generating schedules. # Contains functionality for generating schedules.
class SchedulesController < ApplicationController class SchedulesController < ApplicationController
resource_description do
short 'Endpoints for generating iCal files'
end
# Render an iCal file containing the schedules of all the # Render an iCal file containing the schedules of all the
# course sections with the given CRNs. # course sections with the given CRNs.
api :GET, '/schedules', 'Generate an iCal file with events for the given CRNs'
param :crns, Array, of: String, desc: 'Array of CRNs to include as events in the calendar', required: true
def index def index
crns = params["crns"].split ',' crns = params["crns"].split ','
@schedule = Schedule.new crns @schedule = Schedule.new crns
......
Apipie.configure do |config|
config.app_name = "SRCT Schedules API"
config.api_base_url = "/api"
config.doc_base_url = "/api"
# where is your API defined?
config.api_controllers_matcher = "#{Rails.root}/app/controllers/**/*.rb"
config.api_routes = Rails.application.routes
# use Markdown for writing docs
config.markup = Apipie::Markup::Markdown.new
# Fixes annoying "can't find resource" bug, see https://github.com/Apipie/apipie-rails/issues/549
config.translate = false
config.default_locale = nil
config.app_info["1.0"] = "The SRCT Schedules API provides data about courses, sections, and professors offered at GMU."
end
Apitome.setup do |config|
# This determines where the Apitome routes will be mounted. Changing this to '/api/documentation' for instance would
# allow you to browse to http://localhost:3000/api/documentation to see your api documentation. Set to nil and mount
# it yourself if you need to.
config.mount_at = "/api"
# This defaults to Rails.root if left nil. If you're providing documentation for an engine using a dummy application
# it can be useful to set this to your engines root.. E.g. Application::Engine.root
config.root = nil
# This is where rspec_api_documentation outputs the JSON files. This is configurable within RAD, and so is
# configurable here.
config.doc_path = "doc/api"
# Set a parent controller that Apitome::DocsController inherits from. Useful if you want to use a custom
# `before_action`.
config.parent_controller = "ActionController::Base"
# The title of the documentation -- If your project has a name, you'll want to put it here.
config.title = "SRCT Schedules API"
# The main layout view for all documentation pages. By default this is pretty basic, but you may want to use your own
# application layout.
config.layout = "apitome/application"
# We're using highlight.js (https://github.com/isagalaev/highlight.js) for code highlighting, and it comes with some
# great themes. You can check http://softwaremaniacs.org/media/soft/highlight/test.html for themes, and enter the
# theme as lowercase/underscore.
config.code_theme = "default"
# This allows you to override the css manually. You typically want to require `apitome/application` within the
# override, but if you want to override it entirely you can do so.
config.css_override = nil
# This allows you to override the javascript manually. You typically want to require `apitome/application` within the
# override, but if you want to override it entirely you can do so.
config.js_override = nil
# You can provide a 'README' style markdown file for the documentation, which is a useful place to include general
# information. This path is relative to your doc_path configuration.
config.readme = "../api.md"
# Apitome can render the documentation into a single page that uses scrollspy, or it can render the documentation on
# individual pages on demand. This allows you to specify which one you want, as a single page may impact performance.
config.single_page = true
# You can specify how urls are formatted using a Proc or other callable object.
# Your proc will be called with a resource name or link, giving you the opportunity to modify it as necessary for in the documentation url.
config.url_formatter = ->(str) { str.gsub(/\.json$/, '').underscore.gsub(/[^0-9a-z\:]+/i, '-') }
# You can setup the docs to be loaded from a remote URL if they are
# not available in the application environment. This defaults to
# false.
config.remote_docs = false
# If the remote_docs is set to true, this URL is used as the base for
# the doc location. This should be the root of the doc location, where
# the readme is located. It uses the doc_path setting to build the
# URLs for the API documentation. This defaults to nil.
config.remote_url = nil
# If you would like to precompile your own assets, you can disable auto-compilation.
# This defaults to true
config.precompile_assets = true
end
RspecApiDocumentation.configure do |config|
# Output folder
config.docs_dir = Rails.root.join("doc", "api")
# An array of output format(s).
# Possible values are :json, :html, :combined_text, :combined_json,
# :json_iodocs, :textile, :markdown, :append_json
config.format = :JSON
config.request_headers_to_include = []
config.response_headers_to_include = []
end
...@@ -6,5 +6,6 @@ Rails.application.routes.draw do ...@@ -6,5 +6,6 @@ Rails.application.routes.draw do
resources :schedules, only: [:index] resources :schedules, only: [:index]
end end
get '/', to: redirect('/api') apipie # sets up API docs
get '/', to: redirect('/api') # redirect the root url to API docs
end end
Schedules API
=====================
Welcome to the SRCT Schedules API documentation. Here you can find descriptions and examples of all of the endpoints served.
{
"resource": "Course Sections",
"resource_explanation": "A way to search across the different course sections (i.e. CS 112 001, ECON 103 104) for each course",
"http_method": "GET",
"route": "/api/course_sections",
"description": "Search by course",
"explanation": null,
"parameters": [
{
"type": "number",
"name": "course_id",
"description": " course"
},
{
"type": "string",
"name": "crn",
"description": " crn"
}
],
"response_fields": [
],
"requests": [
{
"request_method": "GET",
"request_path": "/api/course_sections?course_id=169421928",
"request_body": null,
"request_headers": {
},
"request_query_parameters": {
"course_id": "169421928"
},
"request_content_type": null,
"response_status": 200,
"response_status_text": "OK",
"response_body": "[\n {\n \"id\": 91231435,\n \"name\": \"MyString\",\n \"crn\": \"MyString\",\n \"section_type\": \"MyString\",\n \"title\": \"MyString\",\n \"instructor\": \"MyString\",\n \"start_date\": \"2018-05-21\",\n \"end_date\": \"2018-06-04\",\n \"days\": \"MWF\",\n \"start_time\": \"12:00 pm\",\n \"end_time\": \"1:00 pm\",\n \"location\": \"MyString\",\n \"status\": \"MyString\",\n \"campus\": \"MyString\",\n \"notes\": \"MyString\",\n \"size_limit\": 1,\n \"course_id\": 169421928,\n \"created_at\": \"2018-09-02T18:29:10.904Z\",\n \"updated_at\": \"2018-09-02T18:29:10.904Z\"\n },\n {\n \"id\": 477709683,\n \"name\": \"MyString2\",\n \"crn\": \"MyString2\",\n \"section_type\": \"MyString\",\n \"title\": \"MyString\",\n \"instructor\": \"MyString\",\n \"start_date\": \"2018-05-21\",\n \"end_date\": \"2018-06-04\",\n \"days\": \"TR\",\n \"start_time\": \"11:00 am\",\n \"end_time\": \"2:00 pm\",\n \"location\": \"MyString\",\n \"status\": \"MyString\",\n \"campus\": \"MyString\",\n \"notes\": \"MyString\",\n \"size_limit\": 1,\n \"course_id\": 169421928,\n \"created_at\": \"2018-09-02T18:29:10.904Z\",\n \"updated_at\": \"2018-09-02T18:29:10.904Z\"\n }\n]",
"response_headers": {
},
"response_content_type": "application/json; charset=utf-8",
"curl": null
}
]
}
\ No newline at end of file
{
"resource": "Course Sections",
"resource_explanation": "A way to search across the different course sections (i.e. CS 112 001, ECON 103 104) for each course",
"http_method": "GET",
"route": "/api/course_sections",
"description": "Search by CRN",
"explanation": null,
"parameters": [
{
"type": "number",
"name": "course_id",
"description": " course"
},
{
"type": "string",
"name": "crn",
"description": " crn"
}
],
"response_fields": [
],
"requests": [
{
"request_method": "GET",
"request_path": "/api/course_sections?course_id=169421928&crn=70125",
"request_body": null,
"request_headers": {
},
"request_query_parameters": {
"course_id": "169421928",
"crn": "70125"
},
"request_content_type": null,
"response_status": 200,
"response_status_text": "OK",
"response_body": "[\n\n]",
"response_headers": {
},
"response_content_type": "application/json; charset=utf-8",
"curl": null
}
]
}
\ No newline at end of file
{
"resource": "Courses",
"resource_explanation": "A way to search across the different courses (i.e. CS 112, ECON 103) offered at GMU.",
"http_method": "GET",
"route": "/api/courses",
"description": "Filtered list of courses",
"explanation": null,
"parameters": [
{
"type": "string",
"name": "subject",
"description": " subject"
},
{
"type": "number",
"name": "course_number",
"description": " course number"
}
],
"response_fields": [
],
"requests": [
{
"request_method": "GET",
"request_path": "/api/courses?subject=CS&course_number=112",
"request_body": null,
"request_headers": {
},
"request_query_parameters": {
"subject": "CS",
"course_number": "112"
},
"request_content_type": null,
"response_status": 200,
"response_status_text": "OK",
"response_body": "[\n {\n \"id\": 169421928,\n \"subject\": \"CS\",\n \"course_number\": \"112\",\n \"semester_id\": 763694850,\n \"created_at\": \"2018-09-02T18:29:10.916Z\",\n \"updated_at\": \"2018-09-02T18:29:10.916Z\"\n }\n]",
"response_headers": {
},
"response_content_type": "application/json; charset=utf-8",
"curl": null
}
]
}
\ No newline at end of file
{
"resource": "Courses",
"resource_explanation": "A way to search across the different courses (i.e. CS 112, ECON 103) offered at GMU.",
"http_method": "GET",
"route": "/api/courses",
"description": "Listing all courses",
"explanation": null,
"parameters": [
],
"response_fields": [
],
"requests": [
{
"request_method": "GET",
"request_path": "/api/courses",
"request_body": null,
"request_headers": {
},
"request_query_parameters": {
},
"request_content_type": null,
"response_status": 200,
"response_status_text": "OK",
"response_body": "[\n {\n \"id\": 19883831,\n \"subject\": \"ACCT\",\n \"course_number\": \"110\",\n \"semester_id\": 938910979,\n \"created_at\": \"2018-09-02T18:29:10.916Z\",\n \"updated_at\": \"2018-09-02T18:29:10.916Z\"\n },\n {\n \"id\": 169421928,\n \"subject\": \"CS\",\n \"course_number\": \"112\",\n \"semester_id\": 763694850,\n \"created_at\": \"2018-09-02T18:29:10.916Z\",\n \"updated_at\": \"2018-09-02T18:29:10.916Z\"\n },\n {\n \"id\": 290898823,\n \"subject\": \"CS\",\n \"course_number\": \"211\",\n \"semester_id\": 763694850,\n \"created_at\": \"2018-09-02T18:29:10.916Z\",\n \"updated_at\": \"2018-09-02T18:29:10.916Z\"\n },\n {\n \"id\": 605506893,\n \"subject\": \"CS\",\n \"course_number\": \"110\",\n \"semester_id\": 938910979,\n \"created_at\": \"2018-09-02T18:29:10.916Z\",\n \"updated_at\": \"2018-09-02T18:29:10.916Z\"\n }\n]",
"response_headers": {
},
"response_content_type": "application/json; charset=utf-8",
"curl": null
}
]
}
\ No newline at end of file
{
"resources": [
{
"name": "Course Sections",
"explanation": "A way to search across the different course sections (i.e. CS 112 001, ECON 103 104) for each course",
"examples": [
{
"description": "Search by CRN",
"link": "course_sections/search_by_crn.json",
"groups": "all",
"route": "/api/course_sections",
"method": "get"
},
{
"description": "Search by course",
"link": "course_sections/search_by_course.json",
"groups": "all",
"route": "/api/course_sections",
"method": "get"
}
]
},
{
"name": "Courses",
"explanation": "A way to search across the different courses (i.e. CS 112, ECON 103) offered at GMU.",
"examples": [
{
"description": "Filtered list of courses",
"link": "courses/filtered_list_of_courses.json",
"groups": "all",
"route": "/api/courses",
"method": "get"
},
{
"description": "Listing all courses",
"link": "courses/listing_all_courses.json",
"groups": "all",
"route": "/api/courses",
"method": "get"
}
]
}
]
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
require 'rails_helper'
require 'rspec_api_documentation/dsl'
resource "Course Sections" do
explanation "A way to search across the different course sections (i.e. CS 112 001, ECON 103 104) for each course"
get "/api/course_sections" do
parameter :course_id, type: :number
parameter :crn, type: :string
context '200' do
let(:course_id) { 169421928 }
let(:crn) { "70125" }
example_request 'Search by CRN' do
expect(status).to eq(200)
end
end
context '200' do
let(:course_id) { 169421928 }
example_request 'Search by course' do
expect(status).to eq(200)
end
end
end
end
require 'rails_helper'
require 'rspec_api_documentation/dsl'
resource "Courses" do
explanation "A way to search across the different courses (i.e. CS 112, ECON 103) offered at GMU."
get "/api/courses" do
context '200' do
parameter :subject, type: :string
parameter :course_number, type: :number
let(:subject) { 'CS' }
let(:course_number) { 112 }
example_request 'Filtered list of courses' do
expect(status).to eq(200)
end
end
context '200' do
example_request 'Listing all courses' do
expect(status).to eq(200)
end
end
end
end
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
# Checks for pending migrations and applies them before tests are run.