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

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.

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.

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.

Related

RoR; Third party library wrapper for specific needs with service object

Is there any best practice to where third parties wrapper libraries are settled on rails application?
I've been developing with app/service driven way, so it's easy to encapsulate the action behind the scenes.
Ref: http://brewhouse.io/blog/2014/04/30/gourmet-service-objects.html
Now the problem is
Where should I put third party library wrappers for specific needs?
For example,
Mailchimp: wrapper for email subscription
Prawn: The wrapper for PDF receipt
Slack notifier
....
I could create gems for each ones, or put them into models.
If the code is big enough such as PDF receipt wrapper, I could go for creating gem, but if it's small I don't think it's good to put neither model/gem.
Any suggestions?
It's really up to you.
You can put custom code in new files in config/initializers - these will be required automatically.
It's also common to put code in lib/ and add it to the autoload path (there are other questions for this).
You could make a model for each service as well. You don't necessarily need a database table for models (there are other questions for configuring this).
I think this information (where to put custom code) is really integral to rails and I see a lot of beginners confused by it.

guidelines for where to put classes in Rails apps that don't fit anywhere

I'm wondering if there are any best practices about where to put non-standard Ruby files in Rails apps, those that don't fit in any of the default directories (controllers/models etc.).
I'm talking about classes that are used by controllers/models etc., but are not subclasses of any of the Rails base classes. Classes that include functionality extracted from models to make them less fat. Some of them kind of look like models but aren't AR models, some of them look more like "services", some are something in between or something else.
A few random examples:
"strategy" classes that handle authentication with password, via facebook etc.
"XParams" objects that encapsulate params or "XCreator" objects that handle processing of params to execute some complex action that results in creating some AR models in the end
classes that make requests to external APIs or encapsulate those requests and responses
fake models that can be substituted for a real AR model (e.g. guest user)
Resque jobs
classes that store and read information from Redis
classes that execute some specific actions like processing data, generating reports etc. and are called from Resque jobs or rake tasks
I've got quite a lot of these now, some of them are added to lib which ends up as a pile of random classes and modules, some sneak into app/models. I'd like to organize this somehow, but I don't know where to start.
Should only AR models go into app/models? Or is it ok to also put there any domain or helper models? How you decide if something is a model?
Should everything that doesn't fit into app go into lib? Or maybe I should add a few new custom subdirectories to app? What subdirectories, and how do I divide the custom classes?
How do you handle this in your projects? I know every project is a bit different, but there must be some similarities.
Good question - i don't have a concrete answer for you
but I recommend checking out this post
- http://blog.codeclimate.com/blog/2012/02/07/what-code-goes-in-the-lib-directory/
- be sure to read through all the comments
on a current project i have a ton of non-ActiveRecord objects under app/models, it works but not ideal
i put 're-useable' non application specific code under lib
other alternatives I have tried on side projects (say we have a bunch of command objects)
rails is a pain when it comes to namespaces under app, it loads everything up into the same namespace by default
app/
commands/
products/create_command.rb # Products::CreateCommand
products/update_price_command.rb # Products::UpdatePriceCommand
alternate, everything besides rails under src or an app_name directory
app/
src/
commands/
create_product.rb # Commands::CreateProduct
update_product_price.rb # Commands::UpdateProductPrice
I haven't come across a good solution for this, ideally the 2nd one is better, but would be nice to not have the additional directory under app, that way you open app and see controllers, commands, models etc...
You touch on a number of different use cases, and I think that this part is the closest to the "right" answer:
I've got quite a lot of these now, some of them are added to lib which ends up as a pile of random classes and modules, some sneak into app/models. I'd like to organize this somehow, but I don't know where to start.
That's pretty much right on in my book. The one thing you don't mention is extracting various pieces into separate gems. Classes that talk to external services are excellent candidates for extraction, as are strategy classes if they're sufficiently general. These can be private, since running your own gem server isn't hard, and you can then obviously reuse them across ROR apps.
Last and most concretely, resque jobs I stuff into lib/jobs.
My rule of thumb is if it's a model of some kind, it goes into app/models. If not, it probably belongs in lib or some appropriately named subdirectory thereof, e.g. lib/jobs, lib/extensions, lib/external, or the like.
If you're interested, I also wrote a follow-up article about this a bit later summing up what I found: http://blog.lunarlogic.io/2013/declutter-lib-directory/
I place any model classes (like STI subclasses) in apps/models. I place my other classes in lib, as it seems to be the best place to put them. It's easy for me to know where to look. It's also easier for me to group my tests since my model classes are all in one place.
Convention-wise I'm loathe to put helper classes in app/models. If they're presenter classes they belong in the app/helpers. If they're not then lib seems to be the best place for them.
Often my classes find their way into lib in subdirectories where modules with the same name as the subdirectory is responsible for including them. (Rails is very touchy about filenames and classnames when it comes to the autoloader.)
Another option is to encapsulate each module into its own gem and then refer to the gem via your Gemfile. This permits code sharing across projects.

Where to put completely miscellaneous code in a Rails app

I have a rails app the works with multiple 3rd party APIs. Some of these APIs are rate limited and many have methods that can take hours to complete and you have to continually check to see if your request is ready. As such, I have built a queueing system to manage all the baggage.
Each request that goes into this queue has a JSON string that details which 3rd party API the request pertains to, which method, what arguments and a callback to handle the response. I'm going to need a good many callback methods and they handle wildly different tasks. Some update the service status of the 3rd party, some update customer information, some create another queued request to download a large CSV or parse a CSV, etc.
I'm not sure where to put all these unrelated callback methods. They are so varied and meddle with so many different models that I'm not sure it's right to put them under the QueuedRequest model (although that seems the easiest especially regarding testing). I'd like to consolidate them in a single place (again to make testing easier) so trying to shoehorn them into their related models (though often they may not be related to a model at all) isn't going to work.
A utility class of sorts seems to be the best place but where would I put that file?
Details:
Rails 3.2.6
Update: To elaborate on the answer below, what I ended up doing was putting a module of utility methods in /lib/api. I added /lib/api to my autoload_paths in /config/application.rb and, unmentioned, I created an initializer to load the module into my app for me.
/lib/api/callbacks.rb
module Callbacks
extend self
def some_method
# magic
end
end
/config/application.rb
config.autoload_paths += %W(#{config.root}/lib/api)
/config/initializers/application.rb
require 'callbacks'
Under the lib directory, and don't forget to add it to your autoload paths (or eagerload paths if your app is threadsafe!). Make a folder called api and then stick that stuff in a namespace
For example, lib/api/stack_overflow.rb
module API
class StackOverflow
# schtuff
end
end
You could always just throw it into the lib folder.
I am working on an application which queries an external API and presents the data to the user without actually saving it to the DB. There are various elements involved in this process (passing the API key and user ID to the API, validating the query parameters in the request, parsing the response, etc.) which don't have a lot to do with the actual rails application (which will be mainly focused on presenting this data to the user), so I split off all the API stuff into its own directory under lib.
By doing it this way I can test it separately from the main application, which makes for a clean separation of concerns. Also, since my classes for the library are not based on activemodel, the library can be spun off into its own gem and potentially used in other non-rails projects. I have considered, for example, switching rails for sinatra, which is easy to do given the current setup.

Rails: Re-using models, controllers and even views between Rails applications

I have a rails app which contains some fairly generic functionality (eg managing users). I would like to use that common functionality in other rails apps without copying it. The hard part seems to be that this code contains a number of models, controllers and views.
I know that gems and plug-ins allow code to be shared but they seem to apply more to sharing utility and library functionality rather than core parts of an app.
Any advice on how to do this would be greatly appreciated.
We are working with a Rails engine to share functionality between client projects and have gotten quite far with it. The engine contains controllers, models, views, and even routes. It provides core functions needed in each project (access to our in-house content management system) so projects don't have to start from scratch.
Most of the code has been structured in a way that it can be easily extended or overwritten where needed in the projects (mostly by subclassing). It's distributed as gem.
I can't show you code (it's not open-source), but I can point you to some helpful resources:
Rails 3 Plugins - Part 1 - The Big Picture
Rails 3 Plugins - Part 2 - Writing an Engine
Rails::Engine documentation
Plugin Authors: Toward a Better Future
Hope this helps!
Making copies is not always bad. That's why I ask about the reasons you don't want to copy the code.
If you create a 'library', you must ensure that every application will use it in the same manner. Or you have to prepare the 'library' for every possible difference between your applications which use it.
If you share the code, you are adding a dependency to your program. Any change in that shared code will affect more than one application.
Often it's much simpler to copy the code to another application, because then your may apply any modification without thinking about others.
Are you sure that managing users is so generic that you will not make any application-specific changes to it?
What about creating links to the files/directories that have the MVC? That is better than making copies.

Rails-The best way to use external SOAP API?

I am developing a Rails application which will need frequent access to public APIs, and I am not sure what is best way to put external API (SOAP/WSDL) code in Rails application, what about model thingy, how we can manage that? Any ideas, comments?
The current contenders for "best" library for consuming External SOAP services seems to be either Savon or Handsoap. There is a comparison between the two here
I can't comment on handsoap as I haven't used it by I am happy with Savon which is working well for me.
In terms of Application structure then I would create a folder under lib for the interface named after the external entity and then store files under there using the namespacing features of rails.
So an example I have an external interface to a system called Sentinel. So I have RAILS_ROOT/lib/sentinel and then all classes within that folder are declared within a Sentinel module.
The first thing to do would be to see if there are any gems for the API's you want to interface with. Write a small wrapper class for the gem or just include it and use it where needed.
If you're looking to talk to a REST service, I would suggest the rest-client gem. If you want to do something completely custom you could make use of Jon Nunemaker's HTTParty. Nokogiri, an XML parser gem is useful for consuming XML-based services as well.

Resources