5 ms·
I came here to say the exact same thing. After having worked on/scaled an API that served >100k requests per minute, I feel I can say with some experience that
by jerhinesmith 12y ago
I came here to say the exact same thing. After having worked on/scaled an API that served >100k requests per minute, I feel I can say with some experience that defining your JSON in your model is a very bad idea.
A classic example that we ran into repeatedly: Assume you want to have an endpoint that populates a user's profile (for the user to see). You probably want id, name, email, age, location, created_at, updated_at, etc. However, when exposing this same user instance through an endpoint that publicly aggregates users (e.g. search), sending over all those fields is 1) overkill, and 2) raises privacy concerns.
So far, my favorite approach to this problem uses the ActiveModel::Serializer gem (https://github.com/rails-api/active_model_serializers https://github.com/rails-api/active_model_serializers). It moves the JSON logic to something more akin to a view, and provides an easy way to present instances differently depending on the context.
- Glyptodon 12y agoI don't think there's actually a good way to solve this (that I know of) for applications with complex enough permission and role hierarchies. Once you need a list of all the glass marbles with their attributes, but can only see the color of marbles you supervise, and only the radius of a marble if it has a shooter role and only the names and emails of marbles ranked above you... ...and so on... it becomes a situation where each result has to be filtered item by item pretty much. And the filter hierarchies will snowball like tribbles.
- lumpypua 12y agoThe `djangorestframework-composed-permissions` package for DRF gets pretty close to handling this situation effectively. Basically roles and permissions arbitrarily composable with boolean expressions. Although you can model permission hierarchies, I think there are enough corner cases that it's worthwhile to declare permissions as explicitly as conveniently possible. API Docs: https://djangorestframework-composed-permissions.readthedocs.org/en/latest/ https://djangorestframework-composed-permissions.readthedocs...
- cheald 12y agoView models/decorators have served me very well in this case. The view model would take the marble instance, viewing user instance, etc and decide which attributes it should emit as JSON. The result is frequently very clean, very maintainable code.
- jordanthoms 12y agoActiveModel::Serializer is really nice, but it doesn't seem particularly fast when large responses are involved - when we have 500+ comments to serialize it can take 400ms or more in the views code. Is there a way to speed it up when building large responses?
- byroot 12y agoYou can add caching to it pretty easily. If you cache the objects independently and leverage memcache multiget you can get some very nice speedups. AMS have unfortunately no caching by default, and the development was stale for almost a year. The mailing list is active again since the last couple days, so it might get fixed soon.