假设我有一张 books 表,表中有 id、name、author 3 个字段。 正常的话,我发一个 post 请求:
POST /api/books
# request的body中可以这么写:
book[name]: aaa
book[author]: bbb
# rails 会自动解析成:
params: { "book" => { "name" => "aaa", "author" => "bbb" } }
那现在,我希望做一个批量插入的 API 接口,可以批量插入 books,
我就是想知道大家遇到这种情况是怎么设计的,看起来比较规范的 API 接口。
params: { "book" =>[{ "name" => "aaa", "author" => "bbb" }, { "name" => "ccc", "author" => "ddd" }] }
@hging 那请问在 request 的 body 中该怎么样写,rails 才能把参数转变成这样呢?
book[][name]: aaa
book[][author]: bbb
这样么?
我在定义接口文档,需要告诉别人要怎么样调用。
require 'net/http'
require 'json'
def send_request
# My API (2) (POST )
begin
uri = URI('http://localhost:3000/api/users')
# Create client
http = Net::HTTP.new(uri.host, uri.port)
dict = {
"book" => [
{
"name" => "aaa",
"author" => "bbb"
},
{
"name" => "ccc",
"author" => "ddd"
}
]
}
body = JSON.dump(dict)
# Create Request
req = Net::HTTP::Post.new(uri)
# Add headers
req.add_field "Content-Type", "application/json"
# Set header and body
req.add_field "Content-Type", "application/json"
req.body = body
# Fetch Request
res = http.request(req)
puts "Response HTTP Status Code: #{res.code}"
puts "Response HTTP Response Body: #{res.body}"
rescue StandardError => e
puts "HTTP Request failed (#{e.message})"
end
end
据我有限的见识,RESTful 是没有批量创建这个说法的,创建和更新都是基于单个的资源。
在实践上来说这种做法也需要特别的处理,比如说批量插入 10 个,其中一个失败,那么返回什么信息,其余成功的怎么处理,要不要回滚等等。
我建议如果可能,不要做批量的插入,而是做单个资源的更新。假设 user has many books, 你可以 PATCH user, 然后用 accept_nested_attributes_for 更新。如果 user 不适合的话,你甚至还可以创建一个简单的 upload model, 对应每一次的操作。如果都不适合,还是多发些请求,一个个地更新比较好。
我曾经用过 Amazon S3 的 web 管理界面,批量删除和更改都是一个个的请求发的,看起来又慢又笨,但其实他们还是有绝对的理由这么做的。
@billy 那如果遇到需求方提出确实需要这种批量插入的 API 呢? 我觉得批量插入 10 个,失败其中 1 个,这种情况似乎和接口设计得 RESTful / non-RESTful 并没有什么大的关系?...
如果要提供批量 API 接口,那么就不要用 POST /api/books,写个 POST /api/books/batch 也行。
request body { "books" =>[{ "name" => "aaa", "author" => "bbb" }, { "name" => "ccc", "author" => "ddd" }] }
,接口内使用事务,要么全部成功,要么全部失败这样处理起来比较好,好像没有见过返回成功几个失败几个的接口。