Build a Custom API to Connect WordPress With Ruby on Rails

Final product image
What You'll Be Creating

Once upon a time, web applications used to be monoliths that did everything all by themselves. These days, not so much. With web services opening up their APIs, developers are moving to using third party applications to handle parts of the functionality—things such as authentication or emailing users.

While the most common case is one where you use an API to connect to one of the popular online services (Google, Twitter, and so on) there are times when both of the applications you want to connect are your own.

This happened to me some time ago: I had created a custom shopping cart as a Ruby on Rails application and, for a while, was happy to use it together with a plain HTML landing page. After some time, however, I found that to make the landing page more appealing, I needed to upgrade it to something more frequently updated. I wanted a blog, and so WordPress was the natural choice. 

With the WordPress site built, all was good except for one little thing: when visitors added items to the shopping cart and then came back to shop for more, they forgot they had added items to their shopping cart! The shopping cart and the web site needed to work together. I needed to display the contents of the cart on the main web site.

This was a place for some API development. 

By exposing the shopping cart API to the world and then calling it from my WordPress theme, I would be able to pass the data in an elegant manner, without hacking either system.

In this tutorial, based on the lessons learned in doing this project, I will go through both ends of the API communication: First, with the help of the Grape gem, we will create an API to expose a part of a Ruby on Rails based shopping cart to outside applications. Then, we will use the API to retrieve the shopping cart contents and display them on a WordPress site. Depending on what your needs are, you might find that creating the API is what interests you or that you are actually just interested in the part about calling an external API from WordPress. Either way, I hope you will find the tutorial useful and interesting.

To run the code in this tutorial, you will need the following set up: 

  • Ruby on Rails version 3.2
  • PHP 5.3 
  • cURL and its PHP / Apache libraries 

While there is nothing really complicated about the tutorial, a basic understanding of Ruby and Ruby on Rails as well as PHP and WordPress is required.

1.  Get to Know the Example Application

As you are planning to connect a Ruby on Rails application to a WordPress powered web site, it's probably safe to assume you already have a Rails application—and maybe even a WordPress site—up and running. So, for the tutorial's needs, I have created a simplified but functional version of the shopping cart, with methods for the basic actions required in place.

You can download the sample code or just read the tutorial and apply it to a Rails project of your own. 

The example Ruby on Rails project is bare bones and consists of just a model (ShoppingCart) and a controller (ShoppingCartController). In the ShoppingCart model, you will find the following methods:

  • find_or_create_with(token): This static method looks up and returns a shopping cart object with the given identifying token. If one is not found (or no token is given), a new shopping cart is created and returned.
  • token: This method returns a token identifying the current shopping cart object.
  • as_json: This method returns the contents of the shopping cart as a JSON formatted string.

The controller, ShoppingCartController contains an action for adding items to a cart. The action, add, takes two parameters: token and (product) id:

http://<SERVER_PATH>/shopping_cart/add/<id>?token=<token>

We will get back to all of these later, but now, let's get to work and create the API for the shopping cart.

2. Install Grape and Create an API

Now, with the Rails project in place, it’s time to start creating the API. 

To build our API, we will use a tool called Grape. Grape is a micro-framework designed for implementing simple, REST-like APIs in situations where, as the developers say, "you don't need the heavy lifting power of large frameworks like Rails."

The Grape framework can be used on its own but it also sits nicely next to Rails, providing an easy way to create APIs for accessing a subset (or why not all) of the functionality of your Rails application. Which is exactly what we are going to be doing in this tutorial.

Step 1: Install Grape

To add the gem to your Rails project, add the following line to your Gemfile:

Then update your gems by calling (on the command line):

That's it. The gem has been installed and we can start using it.

Step 2: Configure Grape Paths

To start writing the API, you first need to create a ruby source file that will hold the API functionality. This is a lightweight framework, and so we can write the entire API in just one file. Place this file inside your Rails application, in a directory called api right under the main app directory.

In the example project, you will find the API code in app/api/cart_external.rb

Add the following lines to your application.rb configuration file to make sure the files in app/api are included:

Step 3: Create the API Module

Inside the API source file, we will now define a module that will contain our API class:

This is the most bare bones version of the contents of a simple Grape API. At this point, it doesn't do anything yet, but let's take a look at the configuration elements at the beginning of the code inside the class.

  • First, the line version 'v1', :using => :path tells that this is version v1 of the API and that the version the API user wants to access should be defined in the URL, for example http://localhost:3000/v1/. Other options for this configuration field are :header, :accept_version_header and :param, each of them defining a different method of passing the version information. See the Grape documentation for more information about using each of them.
  • format :json tells Grape to encode outgoing responses as JSON formatted strings (:txt and :xml can also be used).

Step 4: Mount the API

Before we start adding functionality to the API, as the final setup step, declare the API class to your Rails application so that it will know to serve it to people and services requesting it. 

To do this, add the following line to config/routes.rb:

2. Make the API Do Something

Now, let's get back to the CartExternal::API class we defined above.

Step 1: Define a Resource

Inside the API class, you will find two elements I didn't mention yet: helpers and resource

  • helpers is a macro that can be used together with a block (or a module) to introduce helper methods that can then be used within the API actions. These methods can be for example helpers needed to verify API parameters or methods for contacting the parent Rails application.
  • resource defines a logical collection of API methods. You can add as many as you like, but in our case we will do fine with just one, which we will call :cart. This  resource will contain all API methods related to the shopping cart. With this definitions, any calls made to http://<APPLICATION_PATH>/v1/cart will be routed to our resource and the actions defined inside of it. 

Step 2: Create Your First API Action

To see how this works, let's start by creating an API call for retrieving the items in a shopping cart, identified by the parameter token. 

Inside the resources block, add the following code:

Now, we have created an action that responds to GET requests sent to the path /items

The action takes one optional string parameter, token, declared in the params block. While it isn't mandatory to declare parameters, it's good practice as it makes your code more readable and also saves you time as Grape will do most of the parameter validation for you. For required parameters, you can use a similar construct, replacing optional with requires. Required parameters cannot have a default value.

Our action looks up a shopping cart that matches the token or creates a new one if no token is passed. Then it returns a JSON encoded response that consists of a status, the actual shopping cart token, and the contents of the shopping cart.

Step 3: Test the API Action

If you are running your Rails application locally, you can now start your server and point your browser to http://localhost:3000/v1/cart/items to see the response, which should look somewhat like this:

As we didn't pass a token in our call, a new shopping cart was created and assigned a randomly generated, unique token value. That's also why the cart is still empty. 

If you like, for testing, you can use the action add in ShoppingCartController to add an item to the cart: 

http://localhost:3000/shopping_cart/add/1?token=TOKEN_FROM_PREVIOUS_CALL

After adding the product, when you call the API again, you will notice that now there is an item in the cart:

{"status":200,"token":"XBrf2nCkTYfQJoU8d4A1nw","cart":{"item_count":1,"items":[{"cart_id":2,"created_at":"2014-05-20T16:44:24Z","id":4,"product_id":1,"product_name":"Test Product","product_price":"10.0","updated_at":"2014-05-20T16:44:24Z"}]}}

Add as many items as you like—and then, before adding any more functionality, let's complete the setup and have WordPress talk to the API.

3. Call the API from WordPress

We have now tested the API by calling it from a web browser and next, it's time to make WordPress communicate with it.

The WordPress code that follows can be included either in a WordPress plugin or in a WordPress theme's functions.php depending on your project and the context of where the API communication is needed. In my own shopping cart integration, I decided to add the code in a child theme for simplicity.

Whichever way you decide to go, the code will be the same.

Step 1: Create a Function for Calling the API

Open your functions.php file (or a suitable plugin PHP file) and insert the following PHP function. It's a helper function that encapsulates the API communication so that in the future, if you need to change the API signature or other generic elements in the calls, you can do it in one place.

Here are the bare bones of what needs to be in that function:

The function takes in the path to the API action and the required parameters, combines them into a URL and then uses cURL to make a request to the API. 

After receiving the response, the function parses it into an array, using json_decode, a function that is a part of the standard PHP libraries.

Step 2: Call the API and Render Response

Now that we have created the functionality for calling the API, let's use it to query the contents of the shopping cart through our API method /cart/items and then print out the response:

The function makes an API call to /items and prints out the response with some basic HTML formatting. At the end of the function, I included a simple print_r block to render the contents of the JSON response for debugging purposes. 

This is useful especially in the beginning, when the cart is still empty and we want to make sure there are no communication errors preventing the code from showing its contents.

Step 3: Hook the Function to WordPress

Now that we have the functions for making the call and printing the response in place, all that is left is making WordPress call them. 

The simplest way to do this would be to go straight to the theme's template files and just call show_shopping_cart right there in the place where you want to show the shopping cart. If the theme is your own and you are sure this is all you need, it might be a viable option. 

At the other end of the spectrum is the most flexible and user friendly approach of embedding the call into a WordPress widget. This way, you can move the shopping cart around and place it in any sidebar area on your WordPress site. It's not all that hard, so let's go ahead and do that. 

All we need is a WP_Widget sub class with a constructor and some code for rendering the shopping cart contents in the function widget. The two other functions, form and options can be left empty for now (if you want to add customization to the widget, this is where it will go). 

Now, go to your WordPress admin, and drag the widget Shopping Cart Widget to one of your sidebars:

Now, visit the WordPress site to see the code in action. You should see something like this:

Your shopping cart is still empty, but as you can see from the print_r output below the shopping cart, the communication works and the WordPress blog is receiving data from our Rails application.

Now, with the basics covered, let's look at making the communication a bit more secure.

4. Secure the Connection With an API Key

We have now built an API for a Ruby on Rails application and called it from a WordPress site; however, there is still something important missing: securing the API so that it's not open for everyone on the Internet to call as they like. I'm sure you can think of all kinds of bad things that would happen if you left the door completely open for everyone, right?

A simple way to secure an API is to generate a secret key for every application you allow to call your API. This way, whenever an application makes a request to the API, it needs to send its API key for the server to check. Callers without a valid API key will not be allowed to make requests. For added security, most services also include an API secret in addition to the API key.

So now, let's get back to work and add the API key, first to our Ruby code and then on the WordPress side.

Step 1: Add a Method for Checking the API Key

First, add a method for checking the API key. This one goes in the helpers block of your API class:

This is a simple version with just one API key, so depending on your application you might have to extend it. For example, if you have multiple applications calling the API, you will need to define a unique API key for each of them and store them in the database. You might also want to create an admin page for creating new API keys. 

At the very least, you need to replace API_KEY with a real, generated key that is not too easy to guess. For this example however, all that matters is that you have an API key and a method for checking that the key passed in matches with the one stored in the system.

Step 2: Use the Helper Method to Verify an API Key

With the helper method in place, we can add the check to our one and only API call by surrounding the code in it with the following if...else construct:

Notice the else block where we raise an error using the Grape method error!.

Now, restart the Rails server and reload your WordPress home page and you will see something like this:

This is because we haven't yet add the API key to our WordPress code and so the Rails API no longer accepts the requests it makes. If you like, at this point, you can add some proper error handling and display a nice error message. 

Then, let's move on and make the API call work again.

Step 3: Add Settings Field for API Key

For now, you could just go ahead and hard code the API key in your api_get_as_json function, but as adding new options to the WordPress General Settings page is very straightforward, let's do this through a settings field. 

And while add it, we can also add an option for defining the URL for the API. 

This way, later when you deploy the WordPress code to an actual live server, you will be able to configure it without having to touch the code—which is always nice.

Here's the settings field definition for the API endpoint URL using the same construct:

Visit your WordPress General Settings menu to set the proper values for these settings, making sure the API key matches with whatever you have set its value to be in your Rails service.

Step 4: Pass API Key With API Requests

Now, with the API key and URL stored in the WordPress options, let's update the function that makes the API call. 

The changes go at the beginning of the function, like this:

Looking at the new code above, you will notice that the $api_key and $api_endpoint settings are read from WordPress options. $api_endpoint was already used to create the URL to call, but for $api_key, we need to add a line (14) to include the value in the parameters sent to the API.

Refresh your WordPress home page and the shopping cart contents pop up again, this time secured with an API key. Everything looks good—actually, the same as before requiring the API key—and you have connected the Rails application with your WordPress site.

5. Add a Shared Session

The WordPress code we have written so far makes API calls and secures them with an API key, but does so in a completely stateless way. For simple, stateless actions such as posting updates to a message board or your own Twitter like microblogging platform, one-off calls like this are all you need. However, for our shopping cart example, this is not quite enough. 

As you notice when testing the code, while our Rails server identifies a shopping cart with a token, we haven't used this token anywhere, so every time a call to cart/list is made, the server creates a new, empty shopping cart.

Not very good. For a shopping cart connection to be of any use, you need to be able to add items to your cart and keep them there for a while, even as you move from one page to the other. 

In one word, you need a session.

There are multiple ways you could create a session, but let's go with the simplest one, using the token passed to us by the Rails application and storing it in a client cookie. As your WordPress site is the interface the user (and her web browser) sees and communicates with, that's also where we need to set the cookie.

Step 1: Set a Cookie

Cookies can only be set in the header, before any content has been rendered, so we need to do some rearranging in the code, moving the /cart/items call up in the execution flow. To do this, let's create a new PHP function, get_shopping_cart, and call it right at the beginning of the WordPress site's execution.

This can be done using WordPress action hooks. For a full list of hooks, you can look at the WordPress Codex. In this case, the action init does what we need, so let's hook our request to that one.

add_action( "init", "get_shopping_cart" );

The function get_shopping_cart itself looks like this:

First, the function makes the by now familiar call to our /items API action. Then we have something new: on line 3, we extract the shopping cart token returned by the API and then, a couple of lines later, save it in a cookie. The cookie is set to expire in 30 minutes as I assume someone shopping in an online store will have forgotten about the shop by that time...

On line 7, you may notice another new function call: set_saved_cart_data. We'll get back to it in just a minute. But first, let’s make the API calls use the token too. 

Step 2: Use the Token From the Cookie

First, let's create a helper function to retrieve the token from the cookie:

And then, using that function, add the following line to api_get_as_json, right after the line where we set the API key parameter:

With this addition, every time a call to the API is made, the method api_get_as_json looks up the shopping cart token from the cookie and adds it to the request parameters. If a cookie isn't found, the API will receive an empty token and treat the call as a new visitor, creating a new, empty shopping cart.

Step 3: Optimize Execution By Saving Some Data

And now, back to set_saved_cart_data.

As we notice in the code above, get_shopping_cart receives the full contents of the shopping cart—the very same data that we are querying in show_shopping_cart. This means that we are calling the API twice in one WordPress page render when one call should be enough. Saving the response for the HTTP request's duration is a simple optimization that we can use to reduce the number of API calls into half.

In PHP, global variables are specific to and only live through one HTTP request, so we can safely use one for storing the data from get_shopping_cart to the point where it is used for actually rendering the shopping cart contents. 

To do this, I have created a simple pair of functions, set_saved_cart_data and get_saved_cart_data, which wrap the global variable $g_shopping_cart_data to keep the code readable and easy to maintain: 

With the shopping cart data stored to a global variable, all you need to do is to change the first line in show_shopping_cart to:

With this change done, the shopping cart now has a session and the user can add items to the cart and move between pages while still seeing the same shopping cart. 

Step 4: Test By Adding Some Items to Cart

To test the functionality, let's create a link to the controller action shopping_cart/add and print it out at the end of show_shopping_cart. Notice, that for the controller to share our session it too needs the shopping cart token as a parameter:

Click on the link, Add test item to cart, to add an item. Then return to your WordPress site and now you can see an item from the shopping cart appear on the WordPress blog!

Some Final Words

That's it: you have now successfully connected a Ruby on Rails based shopping cart to your WordPress blog or web site. 

Remove the print_r debugging, style the output with some CSS and create some real "Add to Cart" links (as well as a "Check Out" button that leads the user back to the actual shopping cart application) and you have a fully functional shopping cart integration.

More importantly, however, you can use the method of creating and talking back to an API to link two applications of your own. They could be anything, so now, go ahead and create some APIs!

Tags:

Comments

Related Articles