Skip to content

Commit fe68ace

Browse files
authored
Merge pull request #35 from rossme/develop
api v1 setup inc schema and specs (#34)
2 parents 51bb7e1 + f4cde3b commit fe68ace

13 files changed

+211
-0
lines changed
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
module Api::V1
4+
5+
# This controller is responsible for handling the json response of the API
6+
class BaseController < ActionController::API
7+
include Api::V1::Concerns::ResponseHandler
8+
9+
respond_to :json
10+
end
11+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
3+
module Api::V1
4+
module Concerns
5+
6+
module ResponseHandler
7+
extend ActiveSupport::Concern
8+
9+
def respond_with(resource:, status:)
10+
render json: response_serializer(resource), status: status
11+
end
12+
13+
def response_serializer(resource)
14+
serializer = constantized_serializer.new(resource)
15+
action_name == 'show' ? serializer.serialize_object : serializer.serialize_collection
16+
end
17+
18+
def constantized_serializer
19+
"Api::V1::#{controller_name.capitalize}Serializer".safe_constantize
20+
end
21+
end
22+
end
23+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# frozen_string_literal: true
2+
3+
module Api
4+
module V1
5+
class PromptsController < BaseController
6+
7+
def show
8+
prompt = Prompt.find(params[:id])
9+
respond_with(resource: prompt, status: :ok)
10+
end
11+
12+
def index
13+
prompts = Prompt.all
14+
respond_with(resource: prompts, status: :ok)
15+
end
16+
end
17+
end
18+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
module Api
4+
module V1
5+
class SchemaController < BaseController
6+
7+
def index
8+
if File.exist?(schema_path)
9+
send_file schema_path, type: 'application/x-yaml', disposition: 'inline'
10+
else
11+
render plain: 'API schema not found', status: :not_found
12+
end
13+
end
14+
15+
def schema_path
16+
Rails.root.join('config', 'openapi', 'api_v1_schema.yaml')
17+
end
18+
end
19+
end
20+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: true
2+
3+
module Api
4+
module V1
5+
class PromptsSerializer
6+
7+
def initialize(resource)
8+
@resource = resource
9+
end
10+
11+
attr_reader :resource
12+
13+
def serialize_object
14+
resource.serializable_hash
15+
end
16+
17+
def serialize_collection
18+
resource(&:serializable_hash)
19+
end
20+
end
21+
end
22+
end

config/openapi/api_v1_schema.yaml

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
openapi: 3.0.0
3+
info:
4+
title: Prompts API
5+
version: 1.0.0
6+
paths:
7+
/api/v1/prompts:
8+
get:
9+
summary: List all prompts
10+
responses:
11+
'200':
12+
description: Successful response
13+
content:
14+
application/json:
15+
schema:
16+
type: array
17+
items:
18+
$ref: '#/components/schemas/Prompt'
19+
20+
/api/v1/prompts/{id}:
21+
get:
22+
summary: Get a prompt by ID
23+
parameters:
24+
- name: id
25+
in: path
26+
required: true
27+
schema:
28+
type: integer
29+
description: ID of the prompt
30+
responses:
31+
'200':
32+
description: Successful response
33+
content:
34+
application/json:
35+
schema:
36+
$ref: '#/components/schemas/Prompt'
37+
38+
components:
39+
schemas:
40+
Prompt:
41+
type: object
42+
properties:
43+
id:
44+
type: integer
45+
user_id:
46+
type: integer
47+
description: The ID of the user who created the prompt.
48+
input:
49+
type: string
50+
description: The input content of the prompt.
51+
output:
52+
type: string
53+
description: The output content of the prompt.
54+
created_at:
55+
type: string
56+
updated_at:
57+
type: string
58+
actioned:
59+
type: boolean
60+
description: If the prompt has been actioned.
61+
action:
62+
type: string
63+
actionable_type:
64+
type: string
65+
description: Polymorphic object type of the actionable.
66+
actionable_id:
67+
type: integer
68+
required:
69+
- user_id
70+
- input

config/routes.rb

+9
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,17 @@
44
devise_for :users
55
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
66

7+
# Web routes
78
resources :prompts
89

10+
# API V1 routes
11+
namespace :api do
12+
namespace :v1 do
13+
resources :prompts, only: %i[index show]
14+
resources :schema, only: %i[index]
15+
end
16+
end
17+
918
# Application root path
1019
root to: 'prompts#index'
1120
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
require 'pry'
5+
6+
RSpec.describe Api::V1::Concerns::ResponseHandler do
7+
describe '#respond_with' do
8+
it 'responds with a collection' do
9+
collection = create_list(:prompt, 3)
10+
controller = double('controller', action_name: 'index', controller_name: 'prompts')
11+
allow(controller).to receive(:constantized_serializer).and_return(Api::V1::PromptsSerializer)
12+
allow(controller).to receive(:render).with(json: Api::V1::PromptsSerializer.new(collection).serialize_collection, status: :ok)
13+
controller.extend(Api::V1::Concerns::ResponseHandler)
14+
controller.respond_with(resource: collection, status: :ok)
15+
expect(controller).to have_received(:render).with(json: Api::V1::PromptsSerializer.new(collection).serialize_collection, status: :ok)
16+
end
17+
end
18+
end

spec/requests/api/v1/prompts_spec.rb

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
RSpec.describe 'Api::V1::Prompts', type: :request do
6+
describe 'GET /index' do
7+
it 'returns http success' do
8+
get '/api/v1/prompts'
9+
expect(response).to have_http_status(:success)
10+
end
11+
end
12+
13+
describe 'GET /show' do
14+
it 'returns http success' do
15+
prompt = create(:prompt)
16+
get "/api/v1/prompts/#{prompt.id}"
17+
expect(response).to have_http_status(:success)
18+
end
19+
end
20+
end

0 commit comments

Comments
 (0)