Adding Active Resource to your app
Service Oriented Architecture splits what would be a monolithic app into several services with the same functionality. This design pattern has many advantages like each service can be worked on independently by different teams making development faster, also the tech stack can be different between services and it makes the application more robust and resilient because you can scale the services that are being used the most individually. But it also brings some challenges, one of them is that the data gets shattered between services, so if you need information for let’s say a user, it might be in the user service and not in your local database, making it harder to work with that information in the way Rails developers are used to. There is a Gem to having foreign models’ information in our app in a manner that can be worked with as if it were a local model called Active Resource, in this article we are going to have a glimpse at that Gem, how to use it and how to customize it for your needs.
To start let’s define what is Active Resource. Active Resource is a gem that creates a wrapper to get information from other services and treat them as if they were active record objects, it accomplishes that by abstracting the Restful API calls to get the resource from other services, and helps to bridge the gap between client-side Rails applications and external services by encapsulating the logic needed to make HTTP requests and parse HTTP responses into programmatically manageable objects. Active Resource is ideal for applications that need to interact with external REST APIs in a way that feels natural to Rails developers, leveraging conventions they already know, using CRUD operations to simplify the creation, reading, updating, and deletion of resources through REST API. It supports associations like belongs_to, and has_many, which can be mapped to related resources in other services and works with XML and JSON-based APIs. all the properties described are out-of-the-box behavioral and demand that the API you get the information from follows the REST structure for endpoint organization, but can also be customized to be more flexible to your application needs.
All of this has several advantages to the development of Ruby on Rails applications under the SOA pattern, some of them are:
- Rapid Development and Prototyping: For projects that need to quickly prototype ideas or build applications with significant dependencies on external APIs, Active Resource can accelerate development by handling much of the repetitive work involved in API communications.
- Reduced Complexity in Dealing with External Services: Active Resource handles much of the complexity involved in communicating with external services, such as constructing URLs, managing query parameters, and parsing XML or JSON responses. This simplifies the development process, particularly when dealing with multiple external APIs.
- Integration with Rails Applications: Active Resource is designed to integrate seamlessly with the Rails ecosystem, making it easier to plug into Rails apps without adapting to a different architecture or library for external API interactions.
- Convention Over Configuration: Active Resource follows this Rails philosophy, allowing developers to interact with RESTful APIs using familiar patterns and practices. This means less time spent on boilerplate code and more on business logic.
But one drawback is that for more complex or non-standard APIs, or when performance and fine-grained control over HTTP interactions are critical, developers might opt for alternative HTTP clients or libraries that provide more flexibility.
Now that we have seen all the functionality that the Gem can handle let’s dive into how to implement it using a simple example with a publicly available API. All the code presented here will be available in my GitHub Repo. For this example, we will use the Pokemon API and integrate the Pokemon model into our application using Active Resource.
First, we have to define the class for the Pokemon model, this class will be inside the models folder as any regular model but instead of inheriting from ApplicationRecord or anything related to Active Record, it will inherit from ActiveResource::Base. After that is done we will configure the base URL that the Pokemon model is going to use to make the calls to get the information, that is defined in the self.site attribute. If the API doesn’t support different formats and is not responding to the calls that are being made, set the self.include_format_in_path to false, that way it won’t put the .json or .xml at the end of the URL when making the request. This is a great point to tell you about a Gem that will help you debug any call made by the application, including the Active Resource ones, the Gem is called httplog and it will let you see the information sent in the outgoing request for easy troubleshooting.
More configurations are not in the example like the self.headers to set the authorization tokens or any other header that the API may require and the self.ssl_options that will determine if the call validates the certificate. Those are very useful but for the particular API that we are using, they weren’t required.
Now that we have the basics of the model working, we can get into customizing it to fit our needs and data flow to fully integrate it into our application. For this, we will have to override some methods to fit our needs and create some custom ones to support the overridden methods.
The first method that we have to override is self.element_path, this method will tell Active Resource what is the path for getting a single element from the API, in the example it has a basic REST structure to get one element but in case your API has special or custom endpoints or uses Odata this is where you build the single element path.
The Same as the element path method, the self.collection_path method will build the URL to get the collection in case your API has special requirements.
If the API returns too many attributes for a record you can override the self.load method to pick which attributes you want your model to have. This is also useful when some attributes are giving you weird errors when creating the model object, with this method you can filter out attributes and leave out the ones that are causing issues (assuming you don’t need them).
Now that we have the model all figured out, let’s customize the functionality to find records. Active Resource has wrappers that mimic the regular methods that we use with regular models like .all, .first, .last, and .where. For each of those, it creates a scope and calls the appropriate method to get the information.
So as you can see in the example for all, first and last, it gets all the records and just picks the ones specified by the scope and options.
For getting a single element, there will be a different helper method to make the call and create the object.
After it makes the call, we have to extract the information from the response, if the structure is not standard you will have to create another helper method to parse the response following the desired structure and then return the data to instantiate the objects.These methods will help you tackle most of the issues that Active Resource might give you
Active Resource is a powerful tool to integrate different services by giving developers the flexibility of using the information from other applications in their application as if it were local. If you want to explore this Gem I recommend reading the official repo page linked in the references and a surprising resource that will get you close to what you may need is Chat GPT. That is everything I wanted to share with you about Active Resource, if you liked this article give it a clap and consider following for more development articles. Thank you for reading all the way and I hope it helped you in your development journey.