reqcord 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/Gemfile +5 -0
- data/README.md +13 -0
- data/gemfiles/rails_7.1.gemfile +13 -0
- data/gemfiles/rails_7.2.gemfile +13 -0
- data/gemfiles/rails_8.0.gemfile +13 -0
- data/gemfiles/rails_8.1.gemfile +13 -0
- data/lib/reqcord/version.rb +1 -1
- data/reqcord.gemspec +18 -4
- metadata +65 -217
- data/.gitignore +0 -8
- data/Gemfile.lock +0 -171
- data/examples/complex-spec-app/.rspec +0 -1
- data/examples/complex-spec-app/README.md +0 -21
- data/examples/complex-spec-app/app.rb +0 -363
- data/examples/complex-spec-app/docs/api/README.md +0 -104
- data/examples/complex-spec-app/docs/api/api/v1/admin/products/create.md +0 -117
- data/examples/complex-spec-app/docs/api/api/v1/admin/products/destroy.md +0 -51
- data/examples/complex-spec-app/docs/api/api/v1/admin/products/index.md +0 -11
- data/examples/complex-spec-app/docs/api/api/v1/admin/products/list.md +0 -106
- data/examples/complex-spec-app/docs/api/api/v1/auth/index.md +0 -9
- data/examples/complex-spec-app/docs/api/api/v1/auth/login.md +0 -76
- data/examples/complex-spec-app/docs/api/api/v1/cart-items/create.md +0 -91
- data/examples/complex-spec-app/docs/api/api/v1/cart-items/destroy.md +0 -51
- data/examples/complex-spec-app/docs/api/api/v1/cart-items/index.md +0 -10
- data/examples/complex-spec-app/docs/api/api/v1/carts/checkout.md +0 -102
- data/examples/complex-spec-app/docs/api/api/v1/carts/index.md +0 -10
- data/examples/complex-spec-app/docs/api/api/v1/carts/show.md +0 -73
- data/examples/complex-spec-app/docs/api/api/v1/home/index.md +0 -9
- data/examples/complex-spec-app/docs/api/api/v1/home/list.md +0 -47
- data/examples/complex-spec-app/docs/api/api/v1/notes/create.md +0 -94
- data/examples/complex-spec-app/docs/api/api/v1/notes/index.md +0 -10
- data/examples/complex-spec-app/docs/api/api/v1/notes/list.md +0 -61
- data/examples/complex-spec-app/docs/api/api/v1/orders/cancel.md +0 -69
- data/examples/complex-spec-app/docs/api/api/v1/orders/create.md +0 -150
- data/examples/complex-spec-app/docs/api/api/v1/orders/destroy.md +0 -37
- data/examples/complex-spec-app/docs/api/api/v1/orders/index.md +0 -13
- data/examples/complex-spec-app/docs/api/api/v1/orders/list.md +0 -78
- data/examples/complex-spec-app/docs/api/api/v1/orders/show.md +0 -83
- data/examples/complex-spec-app/docs/api/api/v1/products/index.md +0 -11
- data/examples/complex-spec-app/docs/api/api/v1/products/list.md +0 -83
- data/examples/complex-spec-app/docs/api/api/v1/products/search.md +0 -88
- data/examples/complex-spec-app/docs/api/api/v1/products/show.md +0 -71
- data/examples/complex-spec-app/docs/api/api/v1/profiles/index.md +0 -10
- data/examples/complex-spec-app/docs/api/api/v1/profiles/show.md +0 -61
- data/examples/complex-spec-app/docs/api/api/v1/profiles/update.md +0 -91
- data/examples/complex-spec-app/docs/api/api/v2/products/index.md +0 -9
- data/examples/complex-spec-app/docs/api/api/v2/products/list.md +0 -77
- data/examples/complex-spec-app/docs/api/curl/api/v1/admin/products/create.sh +0 -18
- data/examples/complex-spec-app/docs/api/curl/api/v1/admin/products/destroy.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/admin/products/list.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/auth/login.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/cart-items/create.sh +0 -16
- data/examples/complex-spec-app/docs/api/curl/api/v1/cart-items/destroy.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/carts/checkout.sh +0 -13
- data/examples/complex-spec-app/docs/api/curl/api/v1/carts/show.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/home/list.sh +0 -8
- data/examples/complex-spec-app/docs/api/curl/api/v1/notes/create.sh +0 -15
- data/examples/complex-spec-app/docs/api/curl/api/v1/notes/list.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/orders/cancel.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/orders/create.sh +0 -29
- data/examples/complex-spec-app/docs/api/curl/api/v1/orders/destroy.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/orders/list.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/orders/show.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/products/list.sh +0 -8
- data/examples/complex-spec-app/docs/api/curl/api/v1/products/search.sh +0 -8
- data/examples/complex-spec-app/docs/api/curl/api/v1/products/show.sh +0 -8
- data/examples/complex-spec-app/docs/api/curl/api/v1/profiles/show.sh +0 -9
- data/examples/complex-spec-app/docs/api/curl/api/v1/profiles/update.sh +0 -16
- data/examples/complex-spec-app/docs/api/curl/api/v2/products/list.sh +0 -8
- data/examples/complex-spec-app/docs/api/dataset.json +0 -5116
- data/examples/complex-spec-app/docs/api/postman/collection.json +0 -2519
- data/examples/complex-spec-app/generate.rb +0 -14
- data/examples/complex-spec-app/reqcord.yml +0 -28
- data/examples/complex-spec-app/spec/requests/admin_spec.rb +0 -67
- data/examples/complex-spec-app/spec/requests/cart_spec.rb +0 -61
- data/examples/complex-spec-app/spec/requests/home_and_auth_spec.rb +0 -49
- data/examples/complex-spec-app/spec/requests/orders_spec.rb +0 -124
- data/examples/complex-spec-app/spec/requests/products_spec.rb +0 -65
- data/examples/complex-spec-app/spec/spec_helper.rb +0 -17
- data/examples/complex-test-app/README.md +0 -40
- data/examples/complex-test-app/app.rb +0 -384
- data/examples/complex-test-app/docs/api/README.md +0 -104
- data/examples/complex-test-app/docs/api/api/v1/admin/products/create.md +0 -117
- data/examples/complex-test-app/docs/api/api/v1/admin/products/destroy.md +0 -51
- data/examples/complex-test-app/docs/api/api/v1/admin/products/index.md +0 -11
- data/examples/complex-test-app/docs/api/api/v1/admin/products/list.md +0 -106
- data/examples/complex-test-app/docs/api/api/v1/auth/index.md +0 -9
- data/examples/complex-test-app/docs/api/api/v1/auth/login.md +0 -76
- data/examples/complex-test-app/docs/api/api/v1/cart-items/create.md +0 -91
- data/examples/complex-test-app/docs/api/api/v1/cart-items/destroy.md +0 -51
- data/examples/complex-test-app/docs/api/api/v1/cart-items/index.md +0 -10
- data/examples/complex-test-app/docs/api/api/v1/carts/checkout.md +0 -102
- data/examples/complex-test-app/docs/api/api/v1/carts/index.md +0 -10
- data/examples/complex-test-app/docs/api/api/v1/carts/show.md +0 -73
- data/examples/complex-test-app/docs/api/api/v1/home/index.md +0 -9
- data/examples/complex-test-app/docs/api/api/v1/home/list.md +0 -47
- data/examples/complex-test-app/docs/api/api/v1/notes/create.md +0 -94
- data/examples/complex-test-app/docs/api/api/v1/notes/index.md +0 -10
- data/examples/complex-test-app/docs/api/api/v1/notes/list.md +0 -61
- data/examples/complex-test-app/docs/api/api/v1/orders/cancel.md +0 -69
- data/examples/complex-test-app/docs/api/api/v1/orders/create.md +0 -150
- data/examples/complex-test-app/docs/api/api/v1/orders/destroy.md +0 -37
- data/examples/complex-test-app/docs/api/api/v1/orders/index.md +0 -13
- data/examples/complex-test-app/docs/api/api/v1/orders/list.md +0 -71
- data/examples/complex-test-app/docs/api/api/v1/orders/show.md +0 -83
- data/examples/complex-test-app/docs/api/api/v1/products/index.md +0 -11
- data/examples/complex-test-app/docs/api/api/v1/products/list.md +0 -83
- data/examples/complex-test-app/docs/api/api/v1/products/search.md +0 -88
- data/examples/complex-test-app/docs/api/api/v1/products/show.md +0 -71
- data/examples/complex-test-app/docs/api/api/v1/profiles/index.md +0 -10
- data/examples/complex-test-app/docs/api/api/v1/profiles/show.md +0 -61
- data/examples/complex-test-app/docs/api/api/v1/profiles/update.md +0 -91
- data/examples/complex-test-app/docs/api/api/v2/products/index.md +0 -9
- data/examples/complex-test-app/docs/api/api/v2/products/list.md +0 -77
- data/examples/complex-test-app/docs/api/curl/api/v1/admin/products/create.sh +0 -18
- data/examples/complex-test-app/docs/api/curl/api/v1/admin/products/destroy.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/admin/products/list.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/auth/login.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/cart-items/create.sh +0 -16
- data/examples/complex-test-app/docs/api/curl/api/v1/cart-items/destroy.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/carts/checkout.sh +0 -13
- data/examples/complex-test-app/docs/api/curl/api/v1/carts/show.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/home/list.sh +0 -8
- data/examples/complex-test-app/docs/api/curl/api/v1/notes/create.sh +0 -15
- data/examples/complex-test-app/docs/api/curl/api/v1/notes/list.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/orders/cancel.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/orders/create.sh +0 -29
- data/examples/complex-test-app/docs/api/curl/api/v1/orders/destroy.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/orders/list.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/orders/show.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/products/list.sh +0 -8
- data/examples/complex-test-app/docs/api/curl/api/v1/products/search.sh +0 -8
- data/examples/complex-test-app/docs/api/curl/api/v1/products/show.sh +0 -8
- data/examples/complex-test-app/docs/api/curl/api/v1/profiles/show.sh +0 -9
- data/examples/complex-test-app/docs/api/curl/api/v1/profiles/update.sh +0 -16
- data/examples/complex-test-app/docs/api/curl/api/v2/products/list.sh +0 -8
- data/examples/complex-test-app/docs/api/dataset.json +0 -5109
- data/examples/complex-test-app/docs/api/postman/collection.json +0 -2568
- data/examples/complex-test-app/generate.rb +0 -14
- data/examples/complex-test-app/reqcord.yml +0 -28
- data/examples/complex-test-app/test/integration/admin_test.rb +0 -70
- data/examples/complex-test-app/test/integration/cart_test.rb +0 -64
- data/examples/complex-test-app/test/integration/home_and_auth_test.rb +0 -53
- data/examples/complex-test-app/test/integration/orders_test.rb +0 -127
- data/examples/complex-test-app/test/integration/products_test.rb +0 -66
- data/examples/spec-app/.rspec +0 -1
- data/examples/spec-app/README.md +0 -36
- data/examples/spec-app/app.rb +0 -209
- data/examples/spec-app/docs/api/README.md +0 -45
- data/examples/spec-app/docs/api/api/v1/customers/create.md +0 -95
- data/examples/spec-app/docs/api/api/v1/customers/index.md +0 -11
- data/examples/spec-app/docs/api/api/v1/customers/list.md +0 -67
- data/examples/spec-app/docs/api/api/v1/customers/show.md +0 -65
- data/examples/spec-app/docs/api/api/v1/tasks/complete.md +0 -51
- data/examples/spec-app/docs/api/api/v1/tasks/create.md +0 -90
- data/examples/spec-app/docs/api/api/v1/tasks/destroy.md +0 -35
- data/examples/spec-app/docs/api/api/v1/tasks/index.md +0 -14
- data/examples/spec-app/docs/api/api/v1/tasks/list.md +0 -65
- data/examples/spec-app/docs/api/api/v1/tasks/show.md +0 -65
- data/examples/spec-app/docs/api/api/v1/tasks/update.md +0 -74
- data/examples/spec-app/docs/api/api/v1/users/create.md +0 -95
- data/examples/spec-app/docs/api/api/v1/users/index.md +0 -11
- data/examples/spec-app/docs/api/api/v1/users/list.md +0 -67
- data/examples/spec-app/docs/api/api/v1/users/show.md +0 -65
- data/examples/spec-app/docs/api/curl/api/v1/customers/create.sh +0 -17
- data/examples/spec-app/docs/api/curl/api/v1/customers/list.sh +0 -9
- data/examples/spec-app/docs/api/curl/api/v1/customers/show.sh +0 -9
- data/examples/spec-app/docs/api/curl/api/v1/tasks/complete.sh +0 -8
- data/examples/spec-app/docs/api/curl/api/v1/tasks/create.sh +0 -15
- data/examples/spec-app/docs/api/curl/api/v1/tasks/destroy.sh +0 -8
- data/examples/spec-app/docs/api/curl/api/v1/tasks/list.sh +0 -8
- data/examples/spec-app/docs/api/curl/api/v1/tasks/show.sh +0 -8
- data/examples/spec-app/docs/api/curl/api/v1/tasks/update.sh +0 -14
- data/examples/spec-app/docs/api/curl/api/v1/users/create.sh +0 -17
- data/examples/spec-app/docs/api/curl/api/v1/users/list.sh +0 -9
- data/examples/spec-app/docs/api/curl/api/v1/users/show.sh +0 -9
- data/examples/spec-app/docs/api/dataset.json +0 -2402
- data/examples/spec-app/docs/api/postman/collection.json +0 -1290
- data/examples/spec-app/generate.rb +0 -14
- data/examples/spec-app/reqcord.yml +0 -27
- data/examples/spec-app/spec/requests/customers_spec.rb +0 -71
- data/examples/spec-app/spec/requests/tasks_spec.rb +0 -78
- data/examples/spec-app/spec/requests/users_spec.rb +0 -68
- data/examples/spec-app/spec/spec_helper.rb +0 -17
- data/examples/test-app/README.md +0 -57
- data/examples/test-app/app.rb +0 -212
- data/examples/test-app/docs/api/README.md +0 -45
- data/examples/test-app/docs/api/api/v1/customers/create.md +0 -95
- data/examples/test-app/docs/api/api/v1/customers/index.md +0 -11
- data/examples/test-app/docs/api/api/v1/customers/list.md +0 -67
- data/examples/test-app/docs/api/api/v1/customers/show.md +0 -65
- data/examples/test-app/docs/api/api/v1/tasks/complete.md +0 -51
- data/examples/test-app/docs/api/api/v1/tasks/create.md +0 -90
- data/examples/test-app/docs/api/api/v1/tasks/destroy.md +0 -35
- data/examples/test-app/docs/api/api/v1/tasks/index.md +0 -14
- data/examples/test-app/docs/api/api/v1/tasks/list.md +0 -65
- data/examples/test-app/docs/api/api/v1/tasks/show.md +0 -65
- data/examples/test-app/docs/api/api/v1/tasks/update.md +0 -74
- data/examples/test-app/docs/api/api/v1/users/create.md +0 -95
- data/examples/test-app/docs/api/api/v1/users/index.md +0 -11
- data/examples/test-app/docs/api/api/v1/users/list.md +0 -67
- data/examples/test-app/docs/api/api/v1/users/show.md +0 -65
- data/examples/test-app/docs/api/curl/api/v1/customers/create.sh +0 -17
- data/examples/test-app/docs/api/curl/api/v1/customers/list.sh +0 -9
- data/examples/test-app/docs/api/curl/api/v1/customers/show.sh +0 -9
- data/examples/test-app/docs/api/curl/api/v1/tasks/complete.sh +0 -8
- data/examples/test-app/docs/api/curl/api/v1/tasks/create.sh +0 -15
- data/examples/test-app/docs/api/curl/api/v1/tasks/destroy.sh +0 -8
- data/examples/test-app/docs/api/curl/api/v1/tasks/list.sh +0 -8
- data/examples/test-app/docs/api/curl/api/v1/tasks/show.sh +0 -8
- data/examples/test-app/docs/api/curl/api/v1/tasks/update.sh +0 -14
- data/examples/test-app/docs/api/curl/api/v1/users/create.sh +0 -17
- data/examples/test-app/docs/api/curl/api/v1/users/list.sh +0 -9
- data/examples/test-app/docs/api/curl/api/v1/users/show.sh +0 -9
- data/examples/test-app/docs/api/dataset.json +0 -2402
- data/examples/test-app/docs/api/postman/collection.json +0 -1290
- data/examples/test-app/generate.rb +0 -14
- data/examples/test-app/reqcord.yml +0 -28
- data/examples/test-app/test/integration/customers_test.rb +0 -72
- data/examples/test-app/test/integration/tasks_test.rb +0 -80
- data/examples/test-app/test/integration/users_test.rb +0 -72
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# A store API in one file: closer to a real application than test-app, so the
|
|
4
|
-
# generated documentation shows the harder cases.
|
|
5
|
-
#
|
|
6
|
-
# GET /api/v1 root inside a namespace ("Home")
|
|
7
|
-
# POST /api/v1/auth/login form-encoded, token in the response body
|
|
8
|
-
# GET|PATCH /api/v1/profile singular resource, PATCH and PUT folded
|
|
9
|
-
# GET /api/v1/products filter[category], sort, page, per_page
|
|
10
|
-
# GET /api/v1/products/search collection action, 400 without q
|
|
11
|
-
# GET /api/v1/orders/:id 403 for someone else's order
|
|
12
|
-
# POST /api/v1/orders line_items[] and a nested address
|
|
13
|
-
# POST /api/v1/orders/:id/cancel 409 once shipped
|
|
14
|
-
# GET /api/v1/orders/:order_id/notes nested resource
|
|
15
|
-
# GET /api/v1/cart singular resource with nested items
|
|
16
|
-
# POST /api/v1/cart/items add by sku, DELETE /cart/items/:sku
|
|
17
|
-
# POST /api/v1/cart/checkout payment_method: "card" | "bank_transfer"
|
|
18
|
-
# */api/v1/admin/products X-Api-Key, 409 on a duplicate sku
|
|
19
|
-
# GET /api/v2/products a second API version, cursor paging
|
|
20
|
-
ENV["RAILS_ENV"] ||= "test"
|
|
21
|
-
|
|
22
|
-
# Only needed because this example lives inside the Reqcord repository.
|
|
23
|
-
# In your own application, `gem "reqcord"` in the Gemfile is enough.
|
|
24
|
-
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
25
|
-
|
|
26
|
-
require "rails"
|
|
27
|
-
require "action_controller/railtie"
|
|
28
|
-
require "reqcord"
|
|
29
|
-
|
|
30
|
-
class ComplexApp < Rails::Application
|
|
31
|
-
config.root = __dir__
|
|
32
|
-
config.eager_load = false
|
|
33
|
-
config.logger = Logger.new(IO::NULL)
|
|
34
|
-
config.secret_key_base = "a" * 64
|
|
35
|
-
config.hosts.clear
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
Rails.application.initialize!
|
|
39
|
-
|
|
40
|
-
module Store
|
|
41
|
-
PRODUCTS = [
|
|
42
|
-
{ id: 1, sku: "TEA-001", name: "Earl Grey", category: "tea", price_cents: 1200, cost_cents: 500, tags: %w[black bergamot] },
|
|
43
|
-
{ id: 2, sku: "TEA-002", name: "Sencha", category: "tea", price_cents: 1500, cost_cents: 700, tags: %w[green] },
|
|
44
|
-
{ id: 3, sku: "MUG-001", name: "Stoneware Mug", category: "mugs", price_cents: 2400, cost_cents: 900, tags: %w[ceramic] },
|
|
45
|
-
{ id: 4, sku: "MUG-002", name: "Travel Mug", category: "mugs", price_cents: 3200, cost_cents: 1400, tags: %w[steel insulated] }
|
|
46
|
-
].freeze
|
|
47
|
-
|
|
48
|
-
PUBLIC_PRODUCT = %i[id sku name category price_cents tags].freeze
|
|
49
|
-
|
|
50
|
-
ORDERS = [
|
|
51
|
-
{ id: 1, user_id: 1, status: "pending", currency: "USD", total_cents: 2700 },
|
|
52
|
-
{ id: 2, user_id: 1, status: "shipped", currency: "USD", total_cents: 3200 },
|
|
53
|
-
{ id: 3, user_id: 2, status: "pending", currency: "EUR", total_cents: 1500 }
|
|
54
|
-
].freeze
|
|
55
|
-
|
|
56
|
-
NOTES = [
|
|
57
|
-
{ id: 1, order_id: 1, body: "Leave at the door", author: "ada" },
|
|
58
|
-
{ id: 2, order_id: 1, body: "Gift wrap please", author: "ada" }
|
|
59
|
-
].freeze
|
|
60
|
-
|
|
61
|
-
PROFILE = { id: 1, name: "Ada Lovelace", email: "ada@example.com", locale: "en" }.freeze
|
|
62
|
-
LOCALES = %w[en tr].freeze
|
|
63
|
-
|
|
64
|
-
CART_ITEMS = [
|
|
65
|
-
{ sku: "TEA-001", name: "Earl Grey", quantity: 2, unit_price_cents: 1200 },
|
|
66
|
-
{ sku: "MUG-001", name: "Stoneware Mug", quantity: 1, unit_price_cents: 2400 }
|
|
67
|
-
].freeze
|
|
68
|
-
PAYMENT_METHODS = %w[card bank_transfer].freeze
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
module Api
|
|
72
|
-
module V1
|
|
73
|
-
class BaseController < ActionController::API
|
|
74
|
-
private
|
|
75
|
-
|
|
76
|
-
def authenticate!
|
|
77
|
-
return if request.headers["Authorization"].present?
|
|
78
|
-
|
|
79
|
-
render json: { error: "Unauthorized" }, status: :unauthorized
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def not_found
|
|
83
|
-
render json: { error: "Not Found" }, status: :not_found
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
class HomeController < BaseController
|
|
88
|
-
def index
|
|
89
|
-
render json: { name: "Store API", version: "v1", links: { products: "/api/v1/products", orders: "/api/v1/orders" } }
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
class AuthController < BaseController
|
|
94
|
-
# A classic form login: the test posts a form, not JSON.
|
|
95
|
-
def login
|
|
96
|
-
if params[:email] == "ada@example.com" && params[:password] == "correct-horse-battery"
|
|
97
|
-
render json: { token: "tok_live_9f8e7d6c", token_type: "Bearer", expires_in: 3600 }
|
|
98
|
-
else
|
|
99
|
-
render json: { error: "Invalid email or password" }, status: :unauthorized
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
class ProfilesController < BaseController
|
|
105
|
-
before_action :authenticate!
|
|
106
|
-
|
|
107
|
-
def show
|
|
108
|
-
render json: Store::PROFILE
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def update
|
|
112
|
-
attributes = params.require(:profile).permit(:name, :locale).to_h.symbolize_keys
|
|
113
|
-
|
|
114
|
-
if attributes.key?(:locale) && !Store::LOCALES.include?(attributes[:locale])
|
|
115
|
-
return render(json: { errors: { locale: ["is not included in the list"] } }, status: :unprocessable_entity)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
render json: Store::PROFILE.merge(attributes)
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
class ProductsController < BaseController
|
|
123
|
-
def index
|
|
124
|
-
products = Store::PRODUCTS
|
|
125
|
-
category = params.dig(:filter, :category)
|
|
126
|
-
products = products.select { |product| product[:category] == category } if category.present?
|
|
127
|
-
products = products.sort_by { |product| product[:price_cents] } if params[:sort] == "price_asc"
|
|
128
|
-
products = products.sort_by { |product| -product[:price_cents] } if params[:sort] == "price_desc"
|
|
129
|
-
|
|
130
|
-
page = params.fetch(:page, 1).to_i
|
|
131
|
-
per_page = params.fetch(:per_page, 2).to_i
|
|
132
|
-
slice = products.each_slice(per_page).to_a[page - 1] || []
|
|
133
|
-
|
|
134
|
-
render json: {
|
|
135
|
-
data: slice.map { |product| product.slice(*Store::PUBLIC_PRODUCT) },
|
|
136
|
-
meta: { page: page, per_page: per_page, total: products.size }
|
|
137
|
-
}
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def show
|
|
141
|
-
product = Store::PRODUCTS.find { |candidate| candidate[:id] == params[:id].to_i }
|
|
142
|
-
|
|
143
|
-
return not_found unless product
|
|
144
|
-
|
|
145
|
-
render json: product.slice(*Store::PUBLIC_PRODUCT)
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def search
|
|
149
|
-
query = params[:q].to_s.strip
|
|
150
|
-
|
|
151
|
-
return render(json: { error: "q is required" }, status: :bad_request) if query.empty?
|
|
152
|
-
|
|
153
|
-
matches = Store::PRODUCTS.select { |product| product[:name].downcase.include?(query.downcase) }
|
|
154
|
-
|
|
155
|
-
render json: { query: query, results: matches.map { |product| product.slice(*Store::PUBLIC_PRODUCT) } }
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
class OrdersController < BaseController
|
|
160
|
-
before_action :authenticate!
|
|
161
|
-
before_action :find_order, only: %i[show cancel destroy]
|
|
162
|
-
|
|
163
|
-
def index
|
|
164
|
-
orders = Store::ORDERS.select { |order| order[:user_id] == 1 }
|
|
165
|
-
orders = orders.select { |order| order[:status] == params[:status] } if params[:status].present?
|
|
166
|
-
|
|
167
|
-
render json: orders
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def show
|
|
171
|
-
return render(json: { error: "Forbidden" }, status: :forbidden) unless @order[:user_id] == 1
|
|
172
|
-
|
|
173
|
-
render json: @order
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
def create
|
|
177
|
-
attributes = params.require(:order)
|
|
178
|
-
.permit(line_items: %i[sku quantity], shipping_address: %i[line1 city country])
|
|
179
|
-
.to_h.deep_symbolize_keys
|
|
180
|
-
items = Array(attributes[:line_items])
|
|
181
|
-
|
|
182
|
-
return render(json: { errors: { line_items: ["can't be blank"] } }, status: :unprocessable_entity) if items.empty?
|
|
183
|
-
|
|
184
|
-
lines = items.map do |item|
|
|
185
|
-
product = Store::PRODUCTS.find { |candidate| candidate[:sku] == item[:sku] }
|
|
186
|
-
|
|
187
|
-
return render(json: { errors: { sku: ["#{item[:sku]} is not a known product"] } }, status: :unprocessable_entity) unless product
|
|
188
|
-
|
|
189
|
-
quantity = item[:quantity].to_i
|
|
190
|
-
{
|
|
191
|
-
sku: product[:sku], name: product[:name], quantity: quantity,
|
|
192
|
-
unit_price_cents: product[:price_cents], subtotal_cents: product[:price_cents] * quantity
|
|
193
|
-
}
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
render json: {
|
|
197
|
-
id: 4, status: "pending", currency: "USD",
|
|
198
|
-
total_cents: lines.sum { |line| line[:subtotal_cents] },
|
|
199
|
-
line_items: lines,
|
|
200
|
-
shipping_address: attributes[:shipping_address]
|
|
201
|
-
}, status: :created
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def cancel
|
|
205
|
-
if @order[:status] == "shipped"
|
|
206
|
-
return render(json: { error: "Shipped orders cannot be cancelled" }, status: :conflict)
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
render json: @order.merge(status: "cancelled")
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
def destroy
|
|
213
|
-
head :no_content
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
private
|
|
217
|
-
|
|
218
|
-
def find_order
|
|
219
|
-
@order = Store::ORDERS.find { |order| order[:id] == params[:id].to_i }
|
|
220
|
-
|
|
221
|
-
not_found unless @order
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
# Nested under an order: /api/v1/orders/:order_id/notes
|
|
226
|
-
class NotesController < BaseController
|
|
227
|
-
before_action :authenticate!
|
|
228
|
-
before_action :find_order
|
|
229
|
-
|
|
230
|
-
def index
|
|
231
|
-
render json: Store::NOTES.select { |note| note[:order_id] == @order[:id] }
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
def create
|
|
235
|
-
body = params.dig(:note, :body).to_s
|
|
236
|
-
|
|
237
|
-
return render(json: { errors: { body: ["can't be blank"] } }, status: :unprocessable_entity) if body.empty?
|
|
238
|
-
|
|
239
|
-
render json: { id: 3, order_id: @order[:id], body: body, author: "ada" }, status: :created
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
private
|
|
243
|
-
|
|
244
|
-
def find_order
|
|
245
|
-
@order = Store::ORDERS.find { |order| order[:id] == params[:order_id].to_i }
|
|
246
|
-
|
|
247
|
-
not_found unless @order
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
# `resource :cart`: one cart per customer, no id in the path.
|
|
252
|
-
class CartsController < BaseController
|
|
253
|
-
before_action :authenticate!
|
|
254
|
-
|
|
255
|
-
def show
|
|
256
|
-
render json: cart
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
# Turns the cart into an order.
|
|
260
|
-
def checkout
|
|
261
|
-
method = params[:payment_method].to_s
|
|
262
|
-
|
|
263
|
-
unless Store::PAYMENT_METHODS.include?(method)
|
|
264
|
-
return render(json: { errors: { payment_method: ["is not included in the list"] } }, status: :unprocessable_entity)
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
render json: { id: 5, status: "pending", payment_method: method, total_cents: cart[:total_cents], line_items: cart[:items] },
|
|
268
|
-
status: :created
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
private
|
|
272
|
-
|
|
273
|
-
def cart
|
|
274
|
-
{ items: Store::CART_ITEMS, total_cents: Store::CART_ITEMS.sum { |item| item[:quantity] * item[:unit_price_cents] } }
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
# Nested under the cart and addressed by sku: /api/v1/cart/items/:sku
|
|
279
|
-
class CartItemsController < BaseController
|
|
280
|
-
before_action :authenticate!
|
|
281
|
-
|
|
282
|
-
def create
|
|
283
|
-
attributes = params.require(:item).permit(:sku, :quantity).to_h.symbolize_keys
|
|
284
|
-
product = Store::PRODUCTS.find { |candidate| candidate[:sku] == attributes[:sku] }
|
|
285
|
-
|
|
286
|
-
return render(json: { errors: { sku: ["#{attributes[:sku]} is not a known product"] } }, status: :unprocessable_entity) unless product
|
|
287
|
-
|
|
288
|
-
render json: { sku: product[:sku], name: product[:name], quantity: attributes[:quantity].to_i, unit_price_cents: product[:price_cents] },
|
|
289
|
-
status: :created
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
def destroy
|
|
293
|
-
return not_found unless Store::CART_ITEMS.any? { |item| item[:sku] == params[:sku] }
|
|
294
|
-
|
|
295
|
-
head :no_content
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
module Admin
|
|
300
|
-
# A different credential (X-Api-Key) and a fuller view of the same data.
|
|
301
|
-
class ProductsController < BaseController
|
|
302
|
-
before_action :require_api_key
|
|
303
|
-
|
|
304
|
-
def index
|
|
305
|
-
render json: Store::PRODUCTS
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
def create
|
|
309
|
-
attributes = params.require(:product).permit(:sku, :name, :category, :price_cents).to_h.symbolize_keys
|
|
310
|
-
|
|
311
|
-
if attributes[:sku].to_s.empty? || attributes[:name].to_s.empty?
|
|
312
|
-
return render(json: { errors: { sku: ["can't be blank"] } }, status: :unprocessable_entity)
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
if Store::PRODUCTS.any? { |product| product[:sku] == attributes[:sku] }
|
|
316
|
-
return render(json: { error: "sku #{attributes[:sku]} already exists" }, status: :conflict)
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
render json: { id: 5, cost_cents: 0, tags: [], **attributes }, status: :created
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
def destroy
|
|
323
|
-
return not_found unless Store::PRODUCTS.any? { |product| product[:id] == params[:id].to_i }
|
|
324
|
-
|
|
325
|
-
head :no_content
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
private
|
|
329
|
-
|
|
330
|
-
def require_api_key
|
|
331
|
-
return if request.headers["X-Api-Key"].present?
|
|
332
|
-
|
|
333
|
-
render json: { error: "API key required" }, status: :unauthorized
|
|
334
|
-
end
|
|
335
|
-
end
|
|
336
|
-
end
|
|
337
|
-
end
|
|
338
|
-
|
|
339
|
-
module V2
|
|
340
|
-
class ProductsController < ActionController::API
|
|
341
|
-
# v2 pages by cursor instead of page numbers.
|
|
342
|
-
def index
|
|
343
|
-
start = params[:cursor].present? ? 2 : 0
|
|
344
|
-
items = Store::PRODUCTS[start, 2].map { |product| product.slice(*Store::PUBLIC_PRODUCT).merge(price: format("%.2f", product[:price_cents] / 100.0)) }
|
|
345
|
-
|
|
346
|
-
render json: { items: items, next_cursor: start.zero? ? "eyJpZCI6Mn0" : nil }
|
|
347
|
-
end
|
|
348
|
-
end
|
|
349
|
-
end
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
Rails.application.routes.draw do
|
|
353
|
-
namespace :api do
|
|
354
|
-
namespace :v1 do
|
|
355
|
-
root to: "home#index"
|
|
356
|
-
|
|
357
|
-
post "auth/login", to: "auth#login"
|
|
358
|
-
|
|
359
|
-
resource :profile, only: %i[show update]
|
|
360
|
-
|
|
361
|
-
resources :products, only: %i[index show] do
|
|
362
|
-
get :search, on: :collection
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
resources :orders, only: %i[index show create destroy] do
|
|
366
|
-
post :cancel, on: :member
|
|
367
|
-
resources :notes, only: %i[index create]
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
resource :cart, only: :show do
|
|
371
|
-
post :checkout
|
|
372
|
-
resources :items, only: %i[create destroy], controller: "cart_items", param: :sku
|
|
373
|
-
end
|
|
374
|
-
|
|
375
|
-
namespace :admin do
|
|
376
|
-
resources :products, only: %i[index create destroy]
|
|
377
|
-
end
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
namespace :v2 do
|
|
381
|
-
resources :products, only: :index
|
|
382
|
-
end
|
|
383
|
-
end
|
|
384
|
-
end
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# API Documentation
|
|
2
|
-
|
|
3
|
-
Generated by Reqcord from the application's integration tests.
|
|
4
|
-
|
|
5
|
-
Base URL: `http://localhost:3000`
|
|
6
|
-
|
|
7
|
-
## Placeholders
|
|
8
|
-
|
|
9
|
-
| Header | Replace with |
|
|
10
|
-
| --- | --- |
|
|
11
|
-
| Authorization | `Bearer {{token}}` |
|
|
12
|
-
| X-Api-Key | `{{api_key}}` |
|
|
13
|
-
|
|
14
|
-
## Products
|
|
15
|
-
|
|
16
|
-
Namespace: `api/v1/admin`
|
|
17
|
-
|
|
18
|
-
| Method | Path | Description |
|
|
19
|
-
| --- | --- | --- |
|
|
20
|
-
| `GET` | [`/api/v1/admin/products`](api/v1/admin/products/list.md) | List Products |
|
|
21
|
-
| `POST` | [`/api/v1/admin/products`](api/v1/admin/products/create.md) | Create Product |
|
|
22
|
-
| `DELETE` | [`/api/v1/admin/products/:id`](api/v1/admin/products/destroy.md) | Delete Product |
|
|
23
|
-
|
|
24
|
-
## Auth
|
|
25
|
-
|
|
26
|
-
Namespace: `api/v1`
|
|
27
|
-
|
|
28
|
-
| Method | Path | Description |
|
|
29
|
-
| --- | --- | --- |
|
|
30
|
-
| `POST` | [`/api/v1/auth/login`](api/v1/auth/login.md) | Login |
|
|
31
|
-
|
|
32
|
-
## Cart Items
|
|
33
|
-
|
|
34
|
-
Namespace: `api/v1`
|
|
35
|
-
|
|
36
|
-
| Method | Path | Description |
|
|
37
|
-
| --- | --- | --- |
|
|
38
|
-
| `POST` | [`/api/v1/cart/items`](api/v1/cart-items/create.md) | Create Cart Item |
|
|
39
|
-
| `DELETE` | [`/api/v1/cart/items/:sku`](api/v1/cart-items/destroy.md) | Delete Cart Item |
|
|
40
|
-
|
|
41
|
-
## Carts
|
|
42
|
-
|
|
43
|
-
Namespace: `api/v1`
|
|
44
|
-
|
|
45
|
-
| Method | Path | Description |
|
|
46
|
-
| --- | --- | --- |
|
|
47
|
-
| `GET` | [`/api/v1/cart`](api/v1/carts/show.md) | Get Cart |
|
|
48
|
-
| `POST` | [`/api/v1/cart/checkout`](api/v1/carts/checkout.md) | Checkout Cart |
|
|
49
|
-
|
|
50
|
-
## Home
|
|
51
|
-
|
|
52
|
-
Namespace: `api/v1`
|
|
53
|
-
|
|
54
|
-
| Method | Path | Description |
|
|
55
|
-
| --- | --- | --- |
|
|
56
|
-
| `GET` | [`/api/v1`](api/v1/home/list.md) | Home |
|
|
57
|
-
|
|
58
|
-
## Notes
|
|
59
|
-
|
|
60
|
-
Namespace: `api/v1`
|
|
61
|
-
|
|
62
|
-
| Method | Path | Description |
|
|
63
|
-
| --- | --- | --- |
|
|
64
|
-
| `GET` | [`/api/v1/orders/:order_id/notes`](api/v1/notes/list.md) | List Notes |
|
|
65
|
-
| `POST` | [`/api/v1/orders/:order_id/notes`](api/v1/notes/create.md) | Create Note |
|
|
66
|
-
|
|
67
|
-
## Orders
|
|
68
|
-
|
|
69
|
-
Namespace: `api/v1`
|
|
70
|
-
|
|
71
|
-
| Method | Path | Description |
|
|
72
|
-
| --- | --- | --- |
|
|
73
|
-
| `GET` | [`/api/v1/orders`](api/v1/orders/list.md) | List Orders |
|
|
74
|
-
| `POST` | [`/api/v1/orders`](api/v1/orders/create.md) | Create Order |
|
|
75
|
-
| `DELETE` | [`/api/v1/orders/:id`](api/v1/orders/destroy.md) | Delete Order |
|
|
76
|
-
| `GET` | [`/api/v1/orders/:id`](api/v1/orders/show.md) | Get Order |
|
|
77
|
-
| `POST` | [`/api/v1/orders/:id/cancel`](api/v1/orders/cancel.md) | Cancel Order |
|
|
78
|
-
|
|
79
|
-
## Products
|
|
80
|
-
|
|
81
|
-
Namespace: `api/v1`
|
|
82
|
-
|
|
83
|
-
| Method | Path | Description |
|
|
84
|
-
| --- | --- | --- |
|
|
85
|
-
| `GET` | [`/api/v1/products`](api/v1/products/list.md) | List Products |
|
|
86
|
-
| `GET` | [`/api/v1/products/:id`](api/v1/products/show.md) | Get Product |
|
|
87
|
-
| `GET` | [`/api/v1/products/search`](api/v1/products/search.md) | Search Products |
|
|
88
|
-
|
|
89
|
-
## Profiles
|
|
90
|
-
|
|
91
|
-
Namespace: `api/v1`
|
|
92
|
-
|
|
93
|
-
| Method | Path | Description |
|
|
94
|
-
| --- | --- | --- |
|
|
95
|
-
| `GET` | [`/api/v1/profile`](api/v1/profiles/show.md) | Get Profile |
|
|
96
|
-
| `PATCH` | [`/api/v1/profile`](api/v1/profiles/update.md) | Update Profile |
|
|
97
|
-
|
|
98
|
-
## Products
|
|
99
|
-
|
|
100
|
-
Namespace: `api/v2`
|
|
101
|
-
|
|
102
|
-
| Method | Path | Description |
|
|
103
|
-
| --- | --- | --- |
|
|
104
|
-
| `GET` | [`/api/v2/products`](api/v2/products/list.md) | List Products |
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# Create Product
|
|
2
|
-
|
|
3
|
-
`POST /api/v1/admin/products`
|
|
4
|
-
|
|
5
|
-
Namespace: `api/v1/admin`
|
|
6
|
-
|
|
7
|
-
## Headers
|
|
8
|
-
|
|
9
|
-
| Header | Value |
|
|
10
|
-
| --- | --- |
|
|
11
|
-
| X-Api-Key | `{{api_key}}` |
|
|
12
|
-
| Content-Type | `application/json` |
|
|
13
|
-
| Accept | `application/json` |
|
|
14
|
-
|
|
15
|
-
## Body Parameters
|
|
16
|
-
|
|
17
|
-
| Field | Type | Required | Values |
|
|
18
|
-
| --- | --- | --- | --- |
|
|
19
|
-
| `product.sku` | string | yes | `"TEA-003"` |
|
|
20
|
-
| `product.name` | string | yes | `"Jasmine"` |
|
|
21
|
-
| `product.category` | string | yes | `"tea"` |
|
|
22
|
-
| `product.price_cents` | integer | yes | `1400` |
|
|
23
|
-
|
|
24
|
-
## Example Request
|
|
25
|
-
|
|
26
|
-
```json
|
|
27
|
-
{
|
|
28
|
-
"product": {
|
|
29
|
-
"sku": "TEA-003",
|
|
30
|
-
"name": "Jasmine",
|
|
31
|
-
"category": "tea",
|
|
32
|
-
"price_cents": 1400
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## cURL
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
curl --request POST \
|
|
41
|
-
--url "http://localhost:3000/api/v1/admin/products" \
|
|
42
|
-
--header "X-Api-Key: {{api_key}}" \
|
|
43
|
-
--header "Content-Type: application/json" \
|
|
44
|
-
--header "Accept: application/json" \
|
|
45
|
-
--data '{
|
|
46
|
-
"product": {
|
|
47
|
-
"sku": "TEA-003",
|
|
48
|
-
"name": "Jasmine",
|
|
49
|
-
"category": "tea",
|
|
50
|
-
"price_cents": 1400
|
|
51
|
-
}
|
|
52
|
-
}'
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Responses
|
|
56
|
-
|
|
57
|
-
### 201 Created
|
|
58
|
-
|
|
59
|
-
#### Fields
|
|
60
|
-
|
|
61
|
-
| Field | Type | Required | Values |
|
|
62
|
-
| --- | --- | --- | --- |
|
|
63
|
-
| `id` | integer | yes | `5` |
|
|
64
|
-
| `cost_cents` | integer | yes | `0` |
|
|
65
|
-
| `tags` | array | yes | - |
|
|
66
|
-
| `sku` | string | yes | `"TEA-003"` |
|
|
67
|
-
| `name` | string | yes | `"Jasmine"` |
|
|
68
|
-
| `category` | string | yes | `"tea"` |
|
|
69
|
-
| `price_cents` | integer | yes | `1400` |
|
|
70
|
-
|
|
71
|
-
```json
|
|
72
|
-
{
|
|
73
|
-
"id": 5,
|
|
74
|
-
"cost_cents": 0,
|
|
75
|
-
"tags": [],
|
|
76
|
-
"sku": "TEA-003",
|
|
77
|
-
"name": "Jasmine",
|
|
78
|
-
"category": "tea",
|
|
79
|
-
"price_cents": 1400
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### 409 Conflict
|
|
84
|
-
|
|
85
|
-
#### Fields
|
|
86
|
-
|
|
87
|
-
| Field | Type | Required | Values |
|
|
88
|
-
| --- | --- | --- | --- |
|
|
89
|
-
| `error` | string | yes | `"sku TEA-001 already exists"` |
|
|
90
|
-
|
|
91
|
-
```json
|
|
92
|
-
{
|
|
93
|
-
"error": "sku TEA-001 already exists"
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### 422 Unprocessable Content
|
|
98
|
-
|
|
99
|
-
#### Fields
|
|
100
|
-
|
|
101
|
-
| Field | Type | Required | Values |
|
|
102
|
-
| --- | --- | --- | --- |
|
|
103
|
-
| `errors.sku[]` | string | yes | `"can't be blank"` |
|
|
104
|
-
|
|
105
|
-
```json
|
|
106
|
-
{
|
|
107
|
-
"errors": {
|
|
108
|
-
"sku": [
|
|
109
|
-
"can't be blank"
|
|
110
|
-
]
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
Resource: [Products](index.md)
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# Delete Product
|
|
2
|
-
|
|
3
|
-
`DELETE /api/v1/admin/products/:id`
|
|
4
|
-
|
|
5
|
-
Namespace: `api/v1/admin`
|
|
6
|
-
|
|
7
|
-
## Headers
|
|
8
|
-
|
|
9
|
-
| Header | Value |
|
|
10
|
-
| --- | --- |
|
|
11
|
-
| X-Api-Key | `{{api_key}}` |
|
|
12
|
-
| Accept | `application/json` |
|
|
13
|
-
|
|
14
|
-
## Path Parameters
|
|
15
|
-
|
|
16
|
-
| Field | Type | Required | Values |
|
|
17
|
-
| --- | --- | --- | --- |
|
|
18
|
-
| `id` | string | yes | `"4"` |
|
|
19
|
-
|
|
20
|
-
## cURL
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
curl --request DELETE \
|
|
24
|
-
--url "http://localhost:3000/api/v1/admin/products/4" \
|
|
25
|
-
--header "X-Api-Key: {{api_key}}" \
|
|
26
|
-
--header "Accept: application/json"
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Responses
|
|
30
|
-
|
|
31
|
-
### 204 No Content
|
|
32
|
-
|
|
33
|
-
_No response body._
|
|
34
|
-
|
|
35
|
-
### 404 Not Found
|
|
36
|
-
|
|
37
|
-
#### Fields
|
|
38
|
-
|
|
39
|
-
| Field | Type | Required | Values |
|
|
40
|
-
| --- | --- | --- | --- |
|
|
41
|
-
| `error` | string | yes | `"Not Found"` |
|
|
42
|
-
|
|
43
|
-
```json
|
|
44
|
-
{
|
|
45
|
-
"error": "Not Found"
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
Resource: [Products](index.md)
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Products
|
|
2
|
-
|
|
3
|
-
Namespace: `api/v1/admin`
|
|
4
|
-
|
|
5
|
-
API version: `v1`
|
|
6
|
-
|
|
7
|
-
| Method | Path | Description |
|
|
8
|
-
| --- | --- | --- |
|
|
9
|
-
| `GET` | [`/api/v1/admin/products`](list.md) | List Products |
|
|
10
|
-
| `POST` | [`/api/v1/admin/products`](create.md) | Create Product |
|
|
11
|
-
| `DELETE` | [`/api/v1/admin/products/:id`](destroy.md) | Delete Product |
|