How to split things up in a grape api app?
Asked Answered
C

2

14

In every examples I see, people only implement one giant api.rb file. Ex:

While this approach works fine as is, it can quickly become crowded and difficult to maintain so I would like to split things up on my app.

For instance, I would like to split my entities from my resources, and then split up my resources between different files. For examples:

app
 - api
   api.rb
   - entities
     - weblog.rb
     - post.rb
     - comment.rb
   - resources
     - weblog.rb
     - post.rb
     - comment.rb

Now, api.rb would be something like:

require 'grape'
module Blog
  class API < Grape::API
    prefix "api"
  end
end

app/api/entities/post.rb would be something like:

module Blog
  module Entities
    class Post < Grape::Entity
      root 'posts', 'posts'
      expose :id
      expose :content
    end
  end
end

app/api/resources/post.rb would be something like:

module Blog
  class API < Grape::API
    resource :posts do
      get do
        present Post.all, with: Blog::Entities::Post
      end

      desc "returns the payment method corresponding to a certain id"
      params do
        requires :id, :type => Integer, :desc => "Post id."
      end
      get ':id' do
        present Post.find(params[:id]), with: Blog::Entities::Post
      end
    end
  end
end

When we do this, we encounter the following message:

Expected /blog-app/api/resources/post.rb to define Post


SOLUTION (thanks to dB. and my co-workers)

You have to change the structure to something like:

app
 - api
   api.rb
   - resources
     - post_api.rb

Then, in the post_api.rb

module Blog
  class Resources::PostAPI < Grape::API
    resource :posts do
      get do
        present Post.all
      end
    end
  end
end

Finally, the api.rb becomes:

require 'grape'
module Blog
  class API < Grape::API
    prefix 'api'
    version 'v1', :using => :path
    format :json

    mount Blog::Resources::PostAPI => '/'
  end
end

Now /api/v1/posts should work :)

Chatman answered 13/2, 2013 at 16:18 Comment(1)
What would happened if I had another version of API - v2 and I would want to expose different name of attribute content, so let's say I would have expose :body instead of expose :content meanwhile I will still have to have support for v1. I think I will start putting Entities into version folder, am I right? Or how would you handle that in this setup?Hanselka
M
7

The class in post.rb should be Post, not API. Then you can mount the Post API inside class API.

class API < Grape::API
  mount Blog::Post => '/'
end

To avoid confusion I would put Post in a Resources namespace, too or rename it to PostAPI.

Manvell answered 13/2, 2013 at 17:35 Comment(2)
Thanks a lot @Manvell In fact you have to namespace AND rename for rails to not get confused... works now!Chatman
Note that you should be able to omit the right hand side of mount, so just mount Blog::Resources::PostAPI should work, no need to mount on /.Manvell
S
1

I found it not working for path prefix:

mount Blog::Post => '/blog'

doesn't work if you want have prefix the path.

use

namespace :blog do
   mount Blog::Post
end

Hope it helps!

Suborder answered 23/12, 2013 at 16:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.