新手问题 Rails API 多条插入数据的设计规范

thxagain · 2016年01月06日 · 最后由 vkill 回复于 2016年01月10日 · 2987 次阅读

假设我有一张 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 管理界面,批量删除和更改都是一个个的请求发的,看起来又慢又笨,但其实他们还是有绝对的理由这么做的。

#1 楼 @hging { "books" =>[{ "name" => "aaa", "author" => "bbb" }, { "name" => "ccc", "author" => "ddd" }] } 会不会好一点?

#6 楼 @qinfanpeng 恩。我就粘出来格式。没注意复数 多谢提醒

@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" }] } ,接口内使用事务,要么全部成功,要么全部失败这样处理起来比较好,好像没有见过返回成功几个失败几个的接口。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号