Grape mounted in rails VS Simple controllers + active_model_serializers

1,100 views
Skip to first unread message

Mathieu Allaire

unread,
Apr 3, 2013, 3:44:33 PM4/3/13
to ruby-...@googlegroups.com
I'm still unsure if I should go with Grape in my Rails app or simply create a namespace and use ActionController::Metal + active_model_serializers to present my JSON. Could you guys tell me the big benefits of Grape mounted in rails instead of my other option? Not trying to start a war here, only looking for opinions (biased or not :P).

Thanks!

Daniel Doubrovkine

unread,
Apr 3, 2013, 9:05:13 PM4/3/13
to ruby-...@googlegroups.com
First, let me prefix all of this by saying that many people have built very successful APIs with Rails controllers.

I did a talk about exactly this at NYC.rb a while ago, the slides are here: http://www.slideshare.net/dblockdotorg/building-restful-apis-w-grape. I have a somewhat updated view of things.

I believe that Rails is very poorly suited for RESTful APIs because it does not speak the language of RESTful APIs. It speaks the language of MVC, instead. Rails does support APIs, but that is because it tries to be all things to everybody in a prescribed manner. Grape, on the other hand, is a tiny framework that tries to be nothing else than an API DSL.
  1. The words "router", "action" or "controller" are unnecessary abstractions.
  2. It's not clear where the API starts and ends. You can't say app/api is my API and everything is in there.
  3. Version 1 is easy, but version 2 is hard. It's difficult to maintain the matrix of routes to controllers when you're trying to do vendor-based content negotiation (Accept header).
  4. Testing an API via controller testing is insufficient because you need to test routes. But testing via requests makes tests asymmetrical to the API implementation.
  5. Everything is optimized for separating view, including, say caching. IMO the JSON representation of a resource is "just another view". That's why active_model_serializers actually exists and you can (and should) totally use that with Grape.
  6. Controllers encourage logic via functions, private methods, etc. They couple resource-based logic through full blown classes with pre/post filters. It only works if you keep them thin, but in practice it becomes a mess. Thick logic is very hard with Grape, you cannot share implementation between endpoints unless you abstract it away, forcing better code.
Hope this helps. I am happy to answer any questions.

cheers
dB.


On Wed, Apr 3, 2013 at 3:44 PM, Mathieu Allaire <mathieu...@gmail.com> wrote:
I'm still unsure if I should go with Grape in my Rails app or simply create a namespace and use ActionController::Metal + active_model_serializers to present my JSON. Could you guys tell me the big benefits of Grape mounted in rails instead of my other option? Not trying to start a war here, only looking for opinions (biased or not :P).

Thanks!

--
You received this message because you are subscribed to the Google Groups "Grape Framework Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-grape+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--

dB. | Moscow - Geneva - Seattle - New York
dblock.org - @dblockdotorg

Mathieu Allaire

unread,
Apr 3, 2013, 9:40:08 PM4/3/13
to ruby-...@googlegroups.com
First thanks for your input! Bellow is my follow up:


On Wednesday, April 3, 2013 9:05:13 PM UTC-4, Daniel Doubrovkine wrote:
First, let me prefix all of this by saying that many people have built very successful APIs with Rails controllers.

I did a talk about exactly this at NYC.rb a while ago, the slides are here: http://www.slideshare.net/dblockdotorg/building-restful-apis-w-grape. I have a somewhat updated view of things.

I believe that Rails is very poorly suited for RESTful APIs because it does not speak the language of RESTful APIs. It speaks the language of MVC, instead. Rails does support APIs, but that is because it tries to be all things to everybody in a prescribed manner. Grape, on the other hand, is a tiny framework that tries to be nothing else than an API DSL.
  1. The words "router", "action" or "controller" are unnecessary abstractions.
Agreed 
  1. It's not clear where the API starts and ends. You can't say app/api is my API and everything is in there.
Agreed 
  1. Version 1 is easy, but version 2 is hard. It's difficult to maintain the matrix of routes to controllers when you're trying to do vendor-based content negotiation (Accept header).
Does not https://github.com/bploetz/versionist or https://github.com/filtersquad/rocket_pants provide some techniques to do versioning?   
  1. Testing an API via controller testing is insufficient because you need to test routes. But testing via requests makes tests asymmetrical to the API implementation.
What stop us from testing our api using controller tests using Rack::Test with get, post, put, delete methods? https://github.com/rubygems/rubygems.org/tree/master/test/functional/api/v1 does exactly this, you see something wrong with this technique? http://guides.rubyonrails.org/testing.html#functional-tests-for-your-controllers also use Rack::Test `get` in their own exemple. Requests specs in RSpec are the equivalent of integration tests, which rails define them as "Integration tests are used to test the interaction among any number of controllers".
  1. Everything is optimized for separating view, including, say caching. IMO the JSON representation of a resource is "just another view". That's why active_model_serializers actually exists and you can (and should) totally use that with Grape.
Oh I see, Entities are not part of grape by default now, and you're free to select what you want, good to know. 
  1. Controllers encourage logic via functions, private methods, etc. They couple resource-based logic through full blown classes with pre/post filters. It only works if you keep them thin, but in practice it becomes a mess. Thick logic is very hard with Grape, you cannot share implementation between endpoints unless you abstract it away, forcing better code.
Agreed! 

Daniel Doubrovkine

unread,
Apr 3, 2013, 10:56:49 PM4/3/13
to ruby-...@googlegroups.com
Below. 

On Wed, Apr 3, 2013 at 9:40 PM, Mathieu Allaire <mathieu...@gmail.com> wrote:
First thanks for your input! Bellow is my follow up:


On Wednesday, April 3, 2013 9:05:13 PM UTC-4, Daniel Doubrovkine wrote:
First, let me prefix all of this by saying that many people have built very successful APIs with Rails controllers.

I did a talk about exactly this at NYC.rb a while ago, the slides are here: http://www.slideshare.net/dblockdotorg/building-restful-apis-w-grape. I have a somewhat updated view of things.

I believe that Rails is very poorly suited for RESTful APIs because it does not speak the language of RESTful APIs. It speaks the language of MVC, instead. Rails does support APIs, but that is because it tries to be all things to everybody in a prescribed manner. Grape, on the other hand, is a tiny framework that tries to be nothing else than an API DSL.
  1. The words "router", "action" or "controller" are unnecessary abstractions.
Agreed 
  1. It's not clear where the API starts and ends. You can't say app/api is my API and everything is in there.
Agreed 
  1. Version 1 is easy, but version 2 is hard. It's difficult to maintain the matrix of routes to controllers when you're trying to do vendor-based content negotiation (Accept header).
Does not https://github.com/bploetz/versionist or https://github.com/filtersquad/rocket_pants provide some techniques to do versioning? 

I didn't know about the first one, thanks! It does seem to do something very similar to Grape's implementation, great. It wraps routes, so that's exactly the same idea. Looks clean, good stuff.

Rocket pants implements a certain vision of how you should or can do a RESTful API on top of Rails. Since I've never used it I am not really qualified to have an opinion.
 
 
  1. Testing an API via controller testing is insufficient because you need to test routes. But testing via requests makes tests asymmetrical to the API implementation.
What stop us from testing our api using controller tests using Rack::Test with get, post, put, delete methods? https://github.com/rubygems/rubygems.org/tree/master/test/functional/api/v1 does exactly this, you see something wrong with this technique? http://guides.rubyonrails.org/testing.html#functional-tests-for-your-controllers also use Rack::Test `get` in their own exemple. Requests specs in RSpec are the equivalent of integration tests, which rails define them as "Integration tests are used to test the interaction among any number of controllers".

What you're saying is that a good way to test a controller is by testing the website with Capybara and clicking on buttons. You can miss a lot of internals because it's not a 1:1 mapping of test/API. How many controllers/methods/actions is a GET /foo/bar actually touching? In Grape it's clear(er).
 
  1. Everything is optimized for separating view, including, say caching. IMO the JSON representation of a resource is "just another view". That's why active_model_serializers actually exists and you can (and should) totally use that with Grape.
Oh I see, Entities are not part of grape by default now, and you're free to select what you want, good to know. 
  1. Controllers encourage logic via functions, private methods, etc. They couple resource-based logic through full blown classes with pre/post filters. It only works if you keep them thin, but in practice it becomes a mess. Thick logic is very hard with Grape, you cannot share implementation between endpoints unless you abstract it away, forcing better code.
Agreed! 
Hope this helps. I am happy to answer any questions.

cheers
dB.


On Wed, Apr 3, 2013 at 3:44 PM, Mathieu Allaire <mathieu...@gmail.com> wrote:
I'm still unsure if I should go with Grape in my Rails app or simply create a namespace and use ActionController::Metal + active_model_serializers to present my JSON. Could you guys tell me the big benefits of Grape mounted in rails instead of my other option? Not trying to start a war here, only looking for opinions (biased or not :P).

Thanks!

--
You received this message because you are subscribed to the Google Groups "Grape Framework Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-grape+...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
You received this message because you are subscribed to the Google Groups "Grape Framework Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-grape+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Mathieu Allaire

unread,
Apr 4, 2013, 12:28:41 AM4/4/13
to ruby-...@googlegroups.com
I think we misunderstood each other about controllers testing. I'm not talking about capybara, which is acceptance/features tests. I was only saying that's its perfectly acceptable to test your API using controllers tests. I think what you tried to tell me is controllers testing does not guarantee that the API will work if the route is broken and not properly pointing to our tested controller (since we never test the actual route there, we use something like get :index). Is this what you were trying to tell me?

If so, routes testing (which is also recommended by the rails guide rspec) should fix this issue, what do you think?
See for rspec:

I think this method is even better to test correctly an API endpoint. Our controller is isolated from any possible routing error and a specific routing test take care of making sure the right URL goes to the right controller and action!

Sorry if this is a bit long, but I would love to have your thoughts about that, since I'm trying everyday to get better at testing!

Cheers

Matt

Sent from my iPhone
Envoyé de mon iPhone
You received this message because you are subscribed to a topic in the Google Groups "Grape Framework Discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ruby-grape/Gh-vkqityZ8/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to ruby-grape+...@googlegroups.com.

Daniel Doubrovkine

unread,
Apr 4, 2013, 7:49:29 AM4/4/13
to ruby-...@googlegroups.com
Yes, exactly.

I am on the totally opposite side of this. I follow the following rules of thumb:

A test needs to test a certain functional unit. For me, that's an API endpoint. So you must have those tests anyway. It's a lot easier to test the API endpoint because it's exactly what it is - an API. It's a fantastic abstraction. You shouldn't be concerned by the implementation of an API, just what it accepts and returns.

If your API is implemented by a router and a controller, then you're also going to have to write both router and controller tests, as you point out. Separately they don't guarantee that your API works. Together they duplicate the above tests. Also, you know how fond I am of having an MVC to implement APIs, so you can see why I wouldn't like that in tests :)

cheers
dB.
Reply all
Reply to author
Forward
0 new messages