Jay
Jay

Reputation: 938

Creating an api endpoint with Grape that returns a nested hash

I'm having trouble trying to set up my first API. I have the API endpoint working with Grape, but I'm not sure how to get the correct data hash that I want.

Right now the API is very simple and looks like this:

    module CategoryTopic
      class API < Grape::API
        prefix "api/v1"
        format :json

        resource "categories" do
          get do
            Category.all
          end
        end

      end
    end

And that returns this

[{"id":1,"category_name":"General Questions"}]

But inside of my app, a category has_many topics, and I want to return a hash that looks like this:

{categories: 
  {"Numbers": "1", "2"},
  {"Colors": "Red", "Blue"}
}

Is something like this possible?

Upvotes: 0

Views: 1828

Answers (1)

Marlon
Marlon

Reputation: 898

Yes, it's possible. I'm assuming that you want to return that JSON from the /api/v1/categories URL.

First off, I don't agree with your proposed JSON because it doesn't seem right. If a Category has a has_many association with Topics, the result JSON should return the Category attributes and all relevant associations inside it. In my opinion, it should be something like this:

[
    { "id":"1", "category_name": "General Questions", 
          topics: [ { "numbers":["1", "2"], "colors": ["Red", "Blue"] } ] }
]

In this case, you have to install the Grape Entity gem (https://github.com/intridea/grape-entity) and create two entities like these:

class CategoryEntity < Grape::Entity
    expose :id
    expose :category_name
    expose :topics, :using => TopicEntity
end

class TopicEntity < Grape::Entity
    expose :numbers
    expose :colors
end

It's always a good practice to not directly return your models from your API. You should use an Entity to shield your model representation from your API clients. Next, require this gem and use your brand new entities in your API class like this:

require 'grape-entity'

module CategoryTopic
  class API < Grape::API
    prefix "api/v1"
    format :json

    resource "categories" do
      get do
        present Category.all, :with => CategoryEntity
      end
    end

  end
end

Upvotes: 2

Related Questions