rails api and normal application on the same codebase - ruby-on-rails

friends,
need your opnion here please.
I a have already a big rails application, but I need to provide a REST API for other clients like mobile.
My doubt is, it is a rigth choice to use the same codebase, that I already have, to develop my API or I need to create it separeted to the existing application?
The API will work with data that the existing application already have or manipulate.
what cons and pros?

Put your API in the same app, within a namespace. If you have to ask the question, putting it in the same app is almost certainly the right answer.
Separate apps introduces an extra layer of complexity and you have to deal with stuff like eg. which app is responsible for database migrations? And if your non-API is handling migrations, then how do you ensure your API is up to date with the latest migrations? You'll likely also end up with some code shared between your app and API, which is more difficult if they're in separate apps. So, put them in the one app.
If you haven't built an API in rails before, this is a great starting point: https://www.codeschool.com/courses/surviving-apis-with-rails (well worth the money)

Related

What is the conventional architecture for a Rails 5 API with an Administrative UI as well?

I was setting out to start a new Rails 5 API, and realized I also need a content-administration "site" of some sort. The admin tool is very simple, just a UI for very basic CRUD operations.
I have an instinct to create two separate Rails applications - one web application for the content-admin tool, and another web application for the API.
This brings about the problem with sharing data models, which is solvable by using rails engines, or including the models as a gem.
As I was researching solutions, I seemed to observe a pattern of including the content-admin portion within the API app itself. There are some middleware includes and controller inheritances involved in this, but its quite simple to get a content-admin UI to run within the same app as an API. Its much less work, and I dont see much of a problem with scale, since the content-admin UI is lightly utilized and the API is the core of the business.
Is this the accepted convention? I might be gaining a bias due to web search results, but it seems like the simplest and most common approach. I plan to have a separate server for accessing the content-admin vs accessing the API, which is what led me to originally plan this as two separate apps. Now I am thinking I was just getting sucked into the "microservices" hype, and it seems more conventional to just include the content-admin UI with my API app.
On the other side, everything I read about Rails engines is 3-4 years out of date. There is little information (that I am stumbling upon) within the last year or so, and more specifically, little-to-no information concerning Rails 5. I am wondering if this sort of architecture has fallen by the wayside.
Is there a typical convention for Rails 5 API applications that also need a content-admin UI?
The approach I've used before is to have the api running out of /app/controllers/api and then have the ActiveAdmin gem installed, with the admin interface files in /app/admin. You can set up the routes to serve the admin interface at https://api.yourapp.com/admin and the API at https://api.yourapp.com/api/v1/ or similar.
I don't know how much of an accepted convention this is, but it works fine.

How to manage multiple APIs in Rails

I have a Rails backend that serves multiple clients:
Angular JS App
iOS App
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:
api/angular/v1
api/ios/v5 (moving v1..v4 to api/ios/ as well)
api/android/v1
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?
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.
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.

Linking a game database to a rails app

My friend has setting up a database for a Ragnarok Online server, and he wants me to code the relative website, which is going to use some of that data (and obviously, i'll have to add tables for the news system, website accounts, etc). Since i'm learning RoR i was going to do it that way.
I have a few "best practice" questions related to this :
Should I create a different database for the website, since it's going to have its particular data alongside the game data ? (i already have a few clues to link multiple databases with Rails, but that seems too much of a hassle for what it is).
If not, do i have to create Model/Controller for each of the tables composing the database, despite the fact that i'm not going to use 90% of it ? Or just the ones that i need ?
An example of this problem : the game database has its own "user" table, but i have to have another "user" table for the website, and do some Joins between those two. So, what's the best practice here ?
Uhm, best practice is not making your own user table. This will cause you much pain. Best practice? Use an API. Expose the game's database in some way to your website, and fetch that info with external requests in your web application.
The reason why making a second user table is a hassle:
1) You'll constantly have to update it, pulling data from the original
to keep it up-to-date.
And I mean furthermore, you're gonna have to create a CRON job or something pulling data from that original table to keep it up to date. Yuck. Also what if that CRON job makes a mistake? (It will)
2) It's almost inevitable that there will be inconsistencies if two
separate tables are maintained. Are you sure your web application is
really fail-proof?
Update:
What you're gonna need is essentially a second Rails application that acts as a REST API for that database. For a good idea of what REST is, I'd read through this to get you started: http://tomayko.com/writings/rest-to-my-wife
Once you have a good understanding of that, start making your app, and test if it's working by using tools like cURL to send requests to your API.
Once you have that done, I'd take a look into the Ruby rest-client gem like Nobita mentioned. This is what you're going to use from your web application to request information from your API application.
Just let me note, I think this would be a terrible first Rails project, unless you're already really well versed in other web development tools, preferably MVC frameworks.

What is the Rails way to handle different controller clients (Web, iOS API)?

I have a Rails app that has 2 "clients" -- an iOS app reads/writes JSON, and Web browsers that read HTML.
Now, if I said "I want different output for different browsers/clients", we could use different ERB files and render based on User-Agent or similar.
In this way Rails was imagined in the Web world -- where I type "cap deploy", and all of my "instances" are upgraded to the latest version (save active session AJAX calls).
As an iOS dev, however, I'm very used to if blocks in code to deal with different data versions & client app versions. It's painful (but required).
I would love to be able to say "I will magically think of the perfect data structure in version 1.0", but we probably all know that's not true -- I'll want to add & deprecate attributes or even models as time goes.
I don't want to mix all of that versioning logic with my normal HTML (which can upgrade gracefully, per above), so I've thought about:
Having a separate controller or just actions for my API calls from iOS
Writing a "forwarder" that treats the HTML/Web version as a layer on top of the API version
Am I trying to solve a Solved Problem? Are there any resources or guiding philosophies I should know about in undertaking this project?
I suggest you create 2 applications, one for the webapp and one for the API.
You could have an external library with all the models, tests and business logic used in those 2 applications.
You can then lock the api to a certain version of the library if needed.
You can create multiple versions of the API without affecting older versions.
You can implement caching at library level if needed and it will automatically affect all applications.
With this model you can also create specific needs, for example, you may want shorter urls for the api than the real webapp, since you don't care about SEO in the API.
What do you think?
Edit :
Here is what I have in mind, library is in the middle.

What's the best way to integrate a Django and Rails app sharing the same MySQL datastore?

I'm going to be collaborating with a Python developer on a web
application. I'm going to be building a part of it in Ruby and he is
going to build another part of it using Django. I don't know much about
Django.
My plan for integrating the two parts is to simply map a certain URL
path prefix (say, any request that begins with /services) to the Python
code, while leaving Rails to process other requests.
The Python and Ruby parts of the app will share and make updates to the
same MySQL datastore.
My questions:
What do people think generally of this sort of integration strategy?
Is there a better alternative (short of writing it all in one language)?
What's the best way to share sensitive session data (i.e. a logged in
user's id) across the two parts of the app?
As I see it you can't use Django's auth, you can't use Django's ORM, you can't use Django's admin, you can't use Django's sessions - all you are left with is URL mapping to views and the template system. I'd not use Django, but a simpler Python framework. Time your Python programmer expanded his world...
One possible way that should be pretty clean is to decide which one of the apps is the "main" one and have the other one communicate with it over a well-defined API, rather than directly interacting with the underlying database.
If you're doing it right, you're already building your Rails application with a RESTful API. The Django app could act as a REST client to it.
I'm sure it could work the other way around too (with the rest-client gem, for instance).
That way, things like validations and other core business logic are enforced in one place, rather than two.
A project, product, whatever you call it, needs a leader.
This is the first proof that you don't have one. Someone should decide either you're doing ruby or python. I prefer ruby myself, but I understand those who prefer python.
I think starting a product asking yourself those kind of questions is a BAD start.
If your colleague only knows prototype, and you only know JQuery, are you going to mix the technologies too? Same for DB? And for testing frameworks?
This is a never ending arguing subject. One should decide, IMHO, if you want so;ething good to happen. I work with a lot of teams, as a consultant, Agile teams, very mature teams for some of them, and that's the kind of stuff they avoid at all cost.
Except if one of you is going to work on some specific part of the project, which REALLY needs one or other of the technologies, but still think the other one is best for the rest of the application.
I think, for example, at a batch computing. You have ALL your web app in ror or django, and you have a script, called by CRON or whatever, computing huge amounts of data outside the web app, filling a DB or whatever.
My2Cts.

Resources