使用Grape和Grape-Entity构建一个简单的API——

2019-11-28  本文已影响0人  花前山谷

这是最后一部分,我们构建了两个API路由,我们可以返回一个book列表,还可以通过id返回特定book的信息。还用了entities获取我们想要的数据,但这还不够。
所以在最后的这一部分,我们将会看到如何使用entities的嵌套来获取想要的数据。
我们的API目录现在是这个样子滴:

.app
 .api
  .book_store 
   .entities
    - book.rb
   .v1
    - books.rb
  - base.rb   

添加flows资源

我们有两个模型,book和flow。一个book下有多个flows。所以我们需要在book资源中嵌套flows。
在 books.rb 文件中中,我们的最后一个API后添加如下代码:

resource :flows do
  desc 'Create a flow.'
  params do
    requires :flow, type: Hash do
      requires :newStock, type: Integer, desc: 'New Stock.'
      requires :previousStock, type: Integer, desc: 'Previous Stock.'
    end
  end
  post do
    @book = Book.find(params[:id])
    @flow = Flow.new(params[:flow])
    @flow = [@book](http://twitter.com/book).flows.create!(params[:flow])
    @book.update(stock: @flow.newStock)
  end
end

最后我们的book.rb会变成这个样子:

module BookStore
  module V1
    class Books < Grape::API
      version 'v1', using: :path
      format :json
      prefix :api
      resource :books do

        desc 'Return list of books'
        get do
          books = Book.all
          present books
        end

        desc 'Return a specific book'
        route_param :id do
          get do
            book = Book.find(params[:id])
            present book, with: BookStore::Entities::Book
          end
          resource :flows do
            desc 'Create a flow.'
            params do
              requires :flow, type: Hash do
                requires :newStock, type: Integer, desc: 'New Stock.'
                requires :previousStock, type: Integer, desc: 'Previous Stock.'
              end
            end
            post do
              @book = Book.find(params[:id])
              @flow = Flow.new(params[:flow])
              @flow = @book.flows.create!(params[:flow])
              @book.update(stock: @flow.newStock)
            end
          end
        end
      end
    end
  end
end

再检查一下我们的API路由:

rails grape:routes
GET  |  /api/:version/books(.json)  |  v1  |  Return list of books
GET  |  /api/:version/books/:id(.json) |  v1  |  Return a specific book
POST  |  /api/:version/books/:id/flows(.json) |  v1  |  Create a flow.

现在我们创建了一个新的路由,允许我们对某一特定book添加flow。


添加flow entity

如果现在尝试对某一book创建flow是可以成功的,但是我们通过地址http://localhost:3000/api/v1/books/1并不能访问book下的flow。因此实现这个功能我们需要添加一个flow entity。

touch app/api/book_store/entities/flow.rb

文件中加入如下代码:

module BookStore
  module Entities
    class Flow < Grape::Entity
      expose :newStock
      expose :previousStock
    end
  end
end

现在我们添加好了flow entity,接下来我们要在book entity中添加新的代码,打开app/api/book_store/entities/book.rb文件并且加入如下代码:

expose :flows, using: BookStore::Entities::Flow

现在我们在浏览器访问 http://localhost:3000/api/v1/books/1

{"isbn":8880548713,"title":"Telekinesis","stock":4234,"flows":[{"newStock":4314,"previousStock":234},{"newStock":1585,"previousStock":1762},{"newStock":2537,"previousStock":2913},{"newStock":626,"previousStock":1788},{"newStock":1435,"previousStock":2011}]}

现在我们来添加book列表的entity

touch app/api/book_store/entities/index.rb
module BookStore
  module Entities
    class Index < Grape::Entity
       expose :isbn
       expose :title
       expose :stock
    end
  end
end

并将entity应用到api当中:

present books, with: BookStore::Entities::Index

新建flow

我们构建了一个方法去新建flow,但是我们仍没有去添加它。我们需要在终端通过curl请求添加。

curl -i -X POST -H 'Content-Type: application/json' -d '{ "flow": { "newStock": 10, "previousStock": 12 } }' http://localhost:3000/api/v1/books/1/flows

如果不出意料的话在终端中会返回如下类似的结果:

HTTP/1.1 201 Created
Content-Type: application/json
ETag: W/"b5bea41b6c623f7c09f1bf24dcae58eb"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 152aafc8-5c74-4fdf-b12e-d2c6937ff20b
X-Runtime: 0.011693
Content-Length: 4

当然也可以使用postman来测试我们的api,这样你就创建了第一个flow啦😊~


END

上一篇下一篇

猜你喜欢

热点阅读