mirror of
https://github.com/ditkrg/rswag.git
synced 2026-01-25 15:22:56 +00:00
add formData support
This commit is contained in:
@@ -27,6 +27,7 @@ module Rswag
|
|||||||
end
|
end
|
||||||
|
|
||||||
def build_body(example)
|
def build_body(example)
|
||||||
|
return build_form_data(example) if parameters_in(:formData).present?
|
||||||
body_parameter = parameters_in(:body).first
|
body_parameter = parameters_in(:body).first
|
||||||
body_parameter.nil? ? '' : example.send(body_parameter[:name]).to_json
|
body_parameter.nil? ? '' : example.send(body_parameter[:name]).to_json
|
||||||
end
|
end
|
||||||
@@ -93,6 +94,10 @@ module Rswag
|
|||||||
"#{name}=#{value.join(',')}" # csv is default
|
"#{name}=#{value.join(',')}" # csv is default
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_form_data(example)
|
||||||
|
Hash[parameters_in(:formData).map { |p| [p[:name][/^\w+[^\[]/, 0], example.send(p[:name][/^\w+[^\[]/, 0])] }]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -158,6 +158,17 @@ module Rswag
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "'formData' parameter" do
|
||||||
|
before do
|
||||||
|
api_metadata[:operation][:parameters] << { name: 'comment', in: :formData, type: 'string' }
|
||||||
|
allow(example).to receive(:comment).and_return('Some comment')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the example value as a hash' do
|
||||||
|
expect(body).to eq({"comment" => "Some comment"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "referenced 'body' parameter" do
|
context "referenced 'body' parameter" do
|
||||||
before do
|
before do
|
||||||
api_metadata[:operation][:parameters] << { '$ref' => '#/parameters/comment' }
|
api_metadata[:operation][:parameters] << { '$ref' => '#/parameters/comment' }
|
||||||
@@ -171,6 +182,20 @@ module Rswag
|
|||||||
expect(body).to eq("{\"text\":\"Some comment\"}")
|
expect(body).to eq("{\"text\":\"Some comment\"}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "referenced 'formData' parameter" do
|
||||||
|
before do
|
||||||
|
api_metadata[:operation][:parameters] << { '$ref' => '#/parameters/comment' }
|
||||||
|
global_metadata[:parameters] = {
|
||||||
|
'comment' => { name: 'comment', in: :formData, type: 'string' }
|
||||||
|
}
|
||||||
|
allow(example).to receive(:comment).and_return('Some comment')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the example value as a json string' do
|
||||||
|
expect(body).to eq({"comment" => "Some comment"})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#build_headers' do
|
describe '#build_headers' do
|
||||||
|
|||||||
@@ -4,10 +4,19 @@ class BlogsController < ApplicationController
|
|||||||
|
|
||||||
# POST /blogs
|
# POST /blogs
|
||||||
def create
|
def create
|
||||||
@blog = Blog.create(params.require(:blog).permit(:title, :content))
|
thumbnail = save_uploaded_file(params[:blog][:thumbnail])
|
||||||
|
@blog = Blog.create(params.require(:blog).permit(:title, :content).merge(:thumbnail => thumbnail))
|
||||||
respond_with @blog
|
respond_with @blog
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Put /blogs/1
|
||||||
|
def upload
|
||||||
|
@blog = Blog.find_by_id(params[:id])
|
||||||
|
return head :not_found if @blog.nil?
|
||||||
|
@blog.thumbnail = save_uploaded_file params[:file]
|
||||||
|
head @blog.save ? :ok : :unprocsessible_entity
|
||||||
|
end
|
||||||
|
|
||||||
# GET /blogs
|
# GET /blogs
|
||||||
def index
|
def index
|
||||||
@blogs = Blog.all
|
@blogs = Blog.all
|
||||||
@@ -24,4 +33,14 @@ class BlogsController < ApplicationController
|
|||||||
respond_with @blog, status: :not_found and return unless @blog
|
respond_with @blog, status: :not_found and return unless @blog
|
||||||
respond_with @blog
|
respond_with @blog
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def save_uploaded_file(field)
|
||||||
|
return if field.nil?
|
||||||
|
require 'fileutils'
|
||||||
|
file = File.join('tmp', field.original_filename)
|
||||||
|
FileUtils.cp field.tempfile.path, file
|
||||||
|
field.original_filename
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ class Blog < ActiveRecord::Base
|
|||||||
{
|
{
|
||||||
id: id,
|
id: id,
|
||||||
title: title,
|
title: title,
|
||||||
content: content
|
content: content,
|
||||||
|
thumbnail: thumbnail
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
TestApp::Application.routes.draw do
|
TestApp::Application.routes.draw do
|
||||||
resources :blogs, defaults: { :format => :json }
|
resources :blogs, defaults: { :format => :json }
|
||||||
|
put '/blogs/:id/upload', to: 'blogs#upload'
|
||||||
|
|
||||||
mount Rswag::Api::Engine => 'api-docs'
|
mount Rswag::Api::Engine => 'api-docs'
|
||||||
mount Rswag::Ui::Engine => 'api-docs'
|
mount Rswag::Ui::Engine => 'api-docs'
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class CreateBlogs < ActiveRecord::Migration
|
|||||||
create_table :blogs do |t|
|
create_table :blogs do |t|
|
||||||
t.string :title
|
t.string :title
|
||||||
t.text :content
|
t.text :content
|
||||||
|
t.string :thumbnail
|
||||||
|
|
||||||
t.timestamps
|
t.timestamps
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ ActiveRecord::Schema.define(:version => 20160218212104) do
|
|||||||
create_table "blogs", :force => true do |t|
|
create_table "blogs", :force => true do |t|
|
||||||
t.string "title"
|
t.string "title"
|
||||||
t.text "content"
|
t.text "content"
|
||||||
|
t.string "thumbnail"
|
||||||
t.datetime "created_at", :null => false
|
t.datetime "created_at", :null => false
|
||||||
t.datetime "updated_at", :null => false
|
t.datetime "updated_at", :null => false
|
||||||
end
|
end
|
||||||
|
|||||||
BIN
test-app/spec/fixtures/thumbnail.png
vendored
Normal file
BIN
test-app/spec/fixtures/thumbnail.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -8,11 +8,13 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
|||||||
tags 'Blogs'
|
tags 'Blogs'
|
||||||
description 'Creates a new blog from provided data'
|
description 'Creates a new blog from provided data'
|
||||||
operationId 'createBlog'
|
operationId 'createBlog'
|
||||||
consumes 'application/json'
|
consumes 'application/x-www-form-urlencoded'
|
||||||
parameter name: :blog, :in => :body, schema: { '$ref' => '#/definitions/blog' }
|
parameter name: 'blog[title]', :in => :formData, type: 'string'
|
||||||
|
parameter name: 'blog[content]', :in => :formData, type: 'string'
|
||||||
|
parameter name: 'blog[thumbnail]', :in => :formData, type: 'file'
|
||||||
|
|
||||||
response '201', 'blog created' do
|
response '201', 'blog created' do
|
||||||
let(:blog) { { title: 'foo', content: 'bar' } }
|
let(:blog) { { title: 'foo', content: 'bar', thumbnail: Rack::Test::UploadedFile.new(Rails.root.join("spec/fixtures/thumbnail.png")) } }
|
||||||
run_test!
|
run_test!
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -34,7 +36,7 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
|||||||
response '200', 'success' do
|
response '200', 'success' do
|
||||||
schema type: 'array', items: { '$ref' => '#/definitions/blog' }
|
schema type: 'array', items: { '$ref' => '#/definitions/blog' }
|
||||||
|
|
||||||
let(:keywords) { 'foo bar' }
|
let(:keywords) { 'foo+bar' }
|
||||||
run_test!
|
run_test!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -59,10 +61,11 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
|||||||
examples 'application/json' => {
|
examples 'application/json' => {
|
||||||
id: 1,
|
id: 1,
|
||||||
title: 'Hello world!',
|
title: 'Hello world!',
|
||||||
content: 'Hello world and hello universe. Thank you all very much!!!'
|
content: 'Hello world and hello universe. Thank you all very much!!!',
|
||||||
|
thumbnail: "thumbnail.png"
|
||||||
}
|
}
|
||||||
|
|
||||||
let(:blog) { Blog.create(title: 'foo', content: 'bar') }
|
let(:blog) { Blog.create(title: 'foo', content: 'bar', thumbnail: 'thumbnail.png') }
|
||||||
let(:id) { blog.id }
|
let(:id) { blog.id }
|
||||||
run_test!
|
run_test!
|
||||||
end
|
end
|
||||||
@@ -73,4 +76,29 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
path '/blogs/{id}/upload' do
|
||||||
|
parameter name: :id, :in => :path, :type => :string
|
||||||
|
|
||||||
|
put 'upload a blog thumbnail' do
|
||||||
|
tags 'Blogs'
|
||||||
|
description 'Upload a thumbnail for specific blog by id'
|
||||||
|
operationId 'uploadThumbnailBlog'
|
||||||
|
consumes 'application/x-www-form-urlencoded'
|
||||||
|
parameter name: :file, :in => :formData, :type => 'file', required: true
|
||||||
|
|
||||||
|
response '200', 'blog updated' do
|
||||||
|
let(:blog) { Blog.create(title: 'foo', content: 'bar') }
|
||||||
|
let(:id) { blog.id }
|
||||||
|
let(:file) { Rack::Test::UploadedFile.new(Rails.root.join("spec/fixtures/thumbnail.png")) }
|
||||||
|
run_test!
|
||||||
|
end
|
||||||
|
|
||||||
|
response '404', 'blog not found' do
|
||||||
|
let(:id) { 'invalid' }
|
||||||
|
let(:file) { Rack::Test::UploadedFile.new(Rails.root.join("spec/fixtures/thumbnail.png")) }
|
||||||
|
run_test!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ RSpec.configure do |config|
|
|||||||
# triggering implicit auto-inclusion in groups with matching metadata.
|
# triggering implicit auto-inclusion in groups with matching metadata.
|
||||||
config.shared_context_metadata_behavior = :apply_to_host_groups
|
config.shared_context_metadata_behavior = :apply_to_host_groups
|
||||||
|
|
||||||
|
config.after(:suite) do
|
||||||
|
File.delete("#{Rails.root}/tmp/thumbnail.png") if File.file?("#{Rails.root}/tmp/thumbnail.png")
|
||||||
|
end
|
||||||
|
|
||||||
# The settings below are suggested to provide a good initial experience
|
# The settings below are suggested to provide a good initial experience
|
||||||
# with RSpec, but feel free to customize to your heart's content.
|
# with RSpec, but feel free to customize to your heart's content.
|
||||||
=begin
|
=begin
|
||||||
|
|||||||
@@ -39,9 +39,10 @@ RSpec.configure do |config|
|
|||||||
properties: {
|
properties: {
|
||||||
id: { type: 'integer' },
|
id: { type: 'integer' },
|
||||||
title: { type: 'string' },
|
title: { type: 'string' },
|
||||||
content: { type: 'string' }
|
content: { type: 'string' },
|
||||||
|
thumbnail: { type: 'string'}
|
||||||
},
|
},
|
||||||
required: [ 'id', 'title', 'content' ]
|
required: [ 'id', 'title', 'content', 'thumbnail' ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
securityDefinitions: {
|
securityDefinitions: {
|
||||||
|
|||||||
@@ -14,15 +14,23 @@
|
|||||||
"description": "Creates a new blog from provided data",
|
"description": "Creates a new blog from provided data",
|
||||||
"operationId": "createBlog",
|
"operationId": "createBlog",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/x-www-form-urlencoded"
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "blog",
|
"name": "blog[title]",
|
||||||
"in": "body",
|
"in": "formData",
|
||||||
"schema": {
|
"type": "string"
|
||||||
"$ref": "#/definitions/blog"
|
},
|
||||||
}
|
{
|
||||||
|
"name": "blog[content]",
|
||||||
|
"in": "formData",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "blog[thumbnail]",
|
||||||
|
"in": "formData",
|
||||||
|
"type": "file"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -107,7 +115,8 @@
|
|||||||
"application/json": {
|
"application/json": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"title": "Hello world!",
|
"title": "Hello world!",
|
||||||
"content": "Hello world and hello universe. Thank you all very much!!!"
|
"content": "Hello world and hello universe. Thank you all very much!!!",
|
||||||
|
"thumbnail": "thumbnail.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -116,6 +125,43 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/blogs/{id}/upload": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"put": {
|
||||||
|
"summary": "upload a blog thumbnail",
|
||||||
|
"tags": [
|
||||||
|
"Blogs"
|
||||||
|
],
|
||||||
|
"description": "Upload a thumbnail for specific blog by id",
|
||||||
|
"operationId": "uploadThumbnailBlog",
|
||||||
|
"consumes": [
|
||||||
|
"application/x-www-form-urlencoded"
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "file",
|
||||||
|
"in": "formData",
|
||||||
|
"type": "file",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "blog updated"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "blog not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
@@ -147,12 +193,16 @@
|
|||||||
},
|
},
|
||||||
"content": {
|
"content": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"thumbnail": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"title",
|
"title",
|
||||||
"content"
|
"content",
|
||||||
|
"thumbnail"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user