Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Organize External API Calls in Rails 4 - Module or Class?

I am creating a Rails app that will use quite a few external APIs such as SalesForce, FolderGrid(like Dropbox) etc., which would all sync to my database. I've never worked with external api calls so I created a few basic Ruby scripts with scattered methods to test the call to those resources. Now I would like to implement them with my full Rails app.

So far, I started off by creating a directory in my /lib folder for holding the api call modules/classes..

/lib/apis/foldergrid.rb

Now I'm not sure what the best approach would be towards organizing the code. In my standalone Ruby scripts, I have methods for authenticating, creating a folder, auditing files, downloading files etc.

What should be in a Module? Do I even need a Module? What should be in a class? How do I make sure I can use these methods in my models and controllers where needed? Is there a best practices concerning external APIs?

Any resources, links, and/or deeper understanding is highly appreciated.

like image 769
shroy Avatar asked Jun 05 '15 22:06

shroy


People also ask

What is external API call?

External API allows you to create workflows that send HTTP requests to external web servers, API endpoints, and URLs. This allows your bot to integrate with almost any third party service or even your own server.

Is Rails API RESTful?

Having spent a lot of time working with JavaScript and React recently, I thought I'd revisit Rails for some practice, and wanted to write a post about creating a RESTful API using Ruby on Rails. Rails now has the option to create an API application which is a slimmed down version of a traditional Rails web app.


2 Answers

I have an app that does this too (pulls data from multiple APIs) so I can tell you what I would did (or in some cases what I would do now if I was to start over).

Data Storage

First off if you are already persisting the data pulled from those into a Rails app, then you will have models representing the data themselves. So that's what you would refer to in your controllers unless your controller is in charge of calling the APIs.

Use Gems where possible

Second make sure to leverage existing gems that existing for the APIs so you're not recreating the wheel of authentication, parsing the JSON to and from the app, etc. For example: there is a rest-force gem for salesforce.

Use Ruby Objects in Lib for mapping between your models and API responses

Third, I would make the classes that map data in between API responses and your models into "Plain old ruby objects" and store them in a lib/apis folder (no need in these cases to store in a module, yet IMHO). They might end up very functional and in the case of mapping data, that is ok.

APIs without existing Gems

In those cases, I would definitely keep them in one or more classes under a module, in their own folder in lib. That way you can parse them out if needed as a Gem (or if you to take the time make them a Gem to start with, I'm sure others could benefit). I just started down this road myself this week using Infoconnect's API which didn't have a Gem (or any code samples in any language). But I'm not very far along.

If needed, create service objects for code in between V and C (view and controllers)

If you do end up needing to do anything to interact with users for the API information or anything that calls those request, I would put those in service objects so your code doesn't get bloated in the view or controller.

like image 80
creativereason Avatar answered Oct 22 '22 06:10

creativereason


What should be in a Module?

A module should contain code that is shared by different classes, or it can be added to a single class.

Do I even need a Module?

No, you can achieve the same thing with inheritance. If there is no code to share, then you probably don't need a module.

How do I make sure I can use these methods in my models and controllers where needed?

You can access them using the class from within a controller:

SalesForceAPI.get_data

"Module or class?" is an age-old question in Ruby, and any other language that supports both.

I would encapsulate the functionality for each API in a class. For example, you can have a SalesForceAPI class. Then, if you need to share functionality between the classes for authenticating, creating a folder, auditing files, or downloading files, you can create an API class.

Each of the classes that needs access to the API class would inherit from it:

SalesForceAPI < API

You can achieve the same thing by creating an API module, and mixing it into the other classes. In this case, it's largely a matter of preference, because either solution is good.

FWIW, I don't know if there would be much shared functionality for authenticating, creating a folder, auditing files, or downloading files, because each API can work quite differently. However, if they are REST API's then you may create some REST helper methods and put them in the API class.

A great, easy to understand, and complete resource on the topic is Practical Object Oriented Design Ruby.

like image 36
B Seven Avatar answered Oct 22 '22 05:10

B Seven