Habovh
Habovh

Reputation: 499

How to manage multiple APIs in Rails

I have a Rails backend that serves multiple clients:

At first, I only had the iOS App, and used classical API versioning in rails when substantial changes were brought to the client (naming my versions v1, v2 and so on).

When we came up with the Angular front end, we needed a specific API, so I did a new version that I would use only with Angular (let's say v5).

At that point, v1 through v4 are dedicated to iOS, and v5 to Angular.

Obviously, I can simultaneously update my backend along with my Angular API, since both are served to the client every time they access the website. Therefore, there is no need for the Angular API to be versioned.

However, I'm at that point where I need to update my iOS API, and it is starting to get very wrong : v1..v4 are for iOS, and v5 is taken by Android. So the supposed next iOS API should be... v6? Definitely wrong.

I wanted to know if it was possible to name an API version angular, and thanks to this answer on SO I understand why this is not possible. I'll quote the interesting part for my case:

Ryan Bigg wrote:

I couldn't figure out how to get /api/asdf/users to match, because how do you determine if that is supposed to be a request to /api/<resource>/<identifier> or /api/<version>/<resource>?

Now you understand better my situation, here's the question.

The question

How am I supposed to manage multiple APIs, but which are not really like versions?

Is it possible to subdivide API versions? Like:

Is there any best practice to do so? Or should I just be using the current API versioning system, knowing which version corresponds to which client?

Upvotes: 0

Views: 1368

Answers (2)

nPn
nPn

Reputation: 16748

I think in the end this is a design issue. Your API should be thought of as the methods to access your model in networked MVC. Just as in any MVC the model should be independent of it's view and controller. I think having a different API per client is almost like having a different model for each client, which I don't think is what you are intending.

As an example, (I am assuming your API is Restful), a GET request to

api/v1/user/1

might return a json "view" of user 1, each of your clients should be written to work with that same output. If you decide you will no longer support this, or add or remove some content from the returned json that would break an existing client, then you might bump the version and implement the change on that version

I would suggest your next API version expose all of the resources needed by any clients you currently have, and then overtime update your clients to work with this new unified API. If you find your self making changes to your model (API) that would break an existing client, then you can release a new version, allowing existing clients to continue to work with the old API and new or updated clients can pick up the new version.

A set of automated tests on your API will help identify when you break an existing client.

I am not expert at this, but I did (as a learning project) create a rails app with an api, and I was able to use the same api for android and ios.

Upvotes: 1

Wes Foster
Wes Foster

Reputation: 8900

In regards to your routing issue quoted from Ryan Bigg, you can resolve it by applying a constraint to the route. For example:

get /api/:type/:version/users/all, to: "users#index", constraints: {type: /(ios|angular)/, version: /\d+/}

Ensuring the the version is a number and the type is either "ios" or "angular", you can easily set up the routes for two separate APIs.

To answer the questions as to whether or not it is possible--yes. Anything is possible, especially with Ruby!

I, first of all, would not have two separate APIs to manage. However, if I did, I would create separate namespaces for each API and name the as AngularAPI and IosAPI. I would just route to them separately. The correct answer will depend on how exactly you've set up your API system.

How would I maintain two separate APIs? (from the comment)

It depends on how substantially different the APIs are. If there are only a few differences, it would make sense to simply use a different controller with different routes. For example, AngularUsersController and IosUsersController. They would both extend a ApiUsersController and alter only what was needed for each platform. This would still allow for proper versioning as it grew, and also keep code duplication at bay.

Upvotes: 1

Related Questions