Sunday, 21 December 2014

12 Tips of Christmas - 11 Restricting your API

12 Tips of Christmas - 11 Restricting your API

Yesterday we ended up with the following API. The one issue we have is that we've exposed all of our Post model regardless if we want to or not. 
module API
  module V1
    class Posts < Grape::API
      version 'v1'
      format :json

      resource :posts do
        desc "Return 10 most recent posts"

        get do
          Post.most_recent.limit(10)
        end

        desc 'Find a specific post'
        params do
          requires :id, type: Integer, desc: "The ID of the post"
        end
        get ':id' do
          Post.find(params[:id)
        end
      end

    end
  end
end
Grape provides an easy way to deal with this in the form of entities.
Under our V1 API directory, we're going to create a Post entity, that will restrict the information that comes out of our API
# app/controllers/api/v1/entities/post.rb
module API
  module V1
    module Entities
      class Post < Grape::Entity
        expose :content, documentation: { type: "String", desc: "The Post content"}
        expose :title, documentation: { type: "String", desc: "The Post title"}

        expose :description, documentation: { type: "String", desc: "The Post description" }

        format_with(:iso_timestamp) { |dt| dt.iso8601 }

        with_options(format_with: :iso_timestamp) do
          expose :created_at, documentation: { type: "DateTime", desc: "When the Post was posted"}
        end

        expose :comments, using: API::V1::Entities::Comments
      end
    end
  end
end
With use of the expose method, we can dictate what we do and don't return from our API, as well as provide documentation for users consuming our API. 
When working with building an API initially, I ran into an issue where the datetime returned by my API was different to what was initially coming into the database, the format_with method alleviates this by providing an easy way to declare a format to utilise on a particular attribute, which is picked up in the with_options block.
Finally as our post has many comments we can also expose those to an API request and utilise another entity again to control what of the comment data we return.

No comments:

Post a comment