The Evernote SDK for Ruby Quick Start Guide

The purpose of this guide is describing how to download, install and configure the Evernote SDK for Ruby. If everything goes as planned, this shouldn’t take more than 10–15 minutes.

The sample application described in this tutorial will perform the following actions:

  • Authenticate with the Evernote Cloud API using OAuth.
  • List all of the notebooks in the authenticated user’s account, their username and the total number of notes in their account.

  • 1. What You Need

    Before we start working with the Evernote Cloud API, let’s make sure everything we need is present and accounted for.

    Evernote API Key

    If you don’t already have an Evernote Cloud API Key, you can request one on the Evernote Developer site. The API key is made up of two pieces: a Consumer Key and a Consumer Secret. You’ll need both of these to complete the sample app below.

    Evernote Sandbox Account

    Sandbox is Evernote’s development server. You’ll need to create an account on that server for use with the sample app below. If you don’t already have a Sandbox account, you can create one here.

    Ruby

    The Ruby programming language runtime is installed by default on Mac OS X and most Unix-based operating systems (including Linux). This tutorial assumes you’re using version 1.9.3 or higher of the Ruby runtime. To determine the version of Ruby running on your computer, issue the following command at the console:

    ruby -v

    If your computer doesn’t have Ruby installed, you can find information on how to do that on the Ruby language website.

    RubyGems

    The Evernote SDK for Ruby is available as a gem (a package format used by the popular RubyGems package manager). You’ll need to download and install RubyGems if you haven’t already, as we’ll be using it to install a few packages upon which our sample app depends. Once you’ve installed it, issue this command in your terminal/console:

    gem --version

    This will print the current version of RubyGems. This tutorial assumes you’re using version 1.8.24 (the current version as of this writing). If the number displayed is lower, you would do well to update to the latest version by issuing the following command:

    gem update --system

    (Note: updating RubyGems may require root or administrative privileges.)

    Sinatra

    The sample application described in this chapter uses Sinatra, a popular web development framework and DSL, written in Ruby. Some familiarity with Sinatra will make this example easier to understand, but isn’t required.

    Sinatra is available from RubyGems and can be installed using the gem command:

    gem install sinatra

    Our sample app uses the current stable version of Sinatra, version 1.3.3.

  • 2. Installing the Evernote SDK for Ruby

    The Evernote SDK for Ruby can be easily installed by issuing the following command:

    gem install evernote_oauth

    This package includes the complete Evernote SDK and some additional functionality to make it simpler to work with the OAuth authentication protocol (which is required by the Evernote Cloud API).

    We now have all of the necessary software installed to construct our sample application. Let’s do that now.

  • 3. The Sample App

    (You can view the complete sample app on GitHub if you have trouble following along here.)

    Our sample app is comprised of two Ruby source files:

    1. evernote_config.rb, which contains a few bits of configuration information.
    2. en_oauth.rb, the application source code.

    Configuration

    evernote_config.rb will look something like this:

    The two require statements at the top are for the Ruby OAuth gem, followed by the evernote_oauth gem. This gem depends on the oauth gem and implements the entire Evernote Cloud API, plus additional OAuth-related functionality.

    Below that, we have our Consumer Key and Consumer Secret values (which should be set to the corresponding parts of your Evernote Cloud API Key).

    Finally, we have a boolean variable SANDBOX which controls whether our app will connect to the Sandbox development server. If false, our app would connect to the production Evernote service.

    Our App’s Components

    Within en_oauth.rb, we have a few different pieces of our application: the before filter, the helpers functions, our get routes and a pair of simple ERB templates.

    First, let’s cover what I’m lovingly calling “the preamble”:

    First, we include the Sinatra gem and enable cookie-based sessions (part of Sinatra). Second, we include the current directory in the $LOAD_PATH (so we can load our configuration file). Finally, we load said configuration file. Pretty straightforward.

    Now, on with the meat of the app…

    before

    This filter runs when the app is initialized and verifies that the OAUTH_CONSUMER_KEY and OAUTH_CONSUMER_SECRET constants have been set in evernote_config.rb. If either constant is initialized to empty string, the error message is displayed:

    helpers

    A collection of plain Ruby functions that will be used in our application. Many of them simply represent variables that we’ve abstracted out of the routes portion of the application. As it happens, this section also contains the calls to the Evernote Cloud API. Let’s quickly look at each of these:

    • auth_token stores the authentication token we’ll be using to make calls against the Evernote Cloud API. Because our web app is necessarily stateless, this value is stored in Sinatra's session:
    • client represents the instance of EvernoteOAuth::Client. It is instantiated using auth_token (if we have one), OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET and SANDBOX.
    • user_store and note_store are the two services of the Evernote Cloud API: the former deals with user and account information, the latter with the user’s notes, notebooks, etc.
    • en_user represents a single Evernote User instance retrieved from the Evernote Cloud API.
    • notebooks contains a collection of Notebook objects as returned by the Evernote Cloud API when NoteStore.listNotebooks() is called.

    total_note_count is the only function in our app that performs logic beyond simply returning a value and deserves a little more explanation…

    We begin with filter, a new (empty) instance of NoteFilter. Since we want to query the entire account, we won’t be adding any additional filtering criteria (see the full NoteFilter definition here).

    Next, we call findNoteCounts, passing our auth_token and filter as parameters (the false parameter indicates that we don’t want notes from the account’s Trash container). findNoteCounts returns an instance of NoteCollectionCounts — a hash of notebook GUIDs mapped to the number of notes in the corresponding notebook. Iterating over all of our notebooks, we ask counts (our instance of NoteCollectionCounts) for the number of notes in that notebook—using its GUID—and return the total of these counts.

    get Routes

    Each instance of get in our app represents an HTTP request and a corresponding URL pattern. Our application has a total of seven routes. Four of them deal directly with our OAuth implementation and will be discussed in the next section. The remaining three are:

    The root of our site, this route simply displays the index template (defined as @@index at the end of en_auth.rb) and prompts the user to begin the OAuth authentication process.

    In this route, we first clear the session object (which is used to track the user’s progress and state across a necessarily stateless web interaction), then redirect the user to / so they can begin the process again.

    This method collects various information about the user’s account (using methods defined in the helpers section of our app), adds them to the current session object and renders the index template. If there are any problems, the rescue block of our code is triggered and the @last_error variable is populated with the cause of the error and is sent to the error template (also defined at the end of en_auth.rb).

    OAuth

    As with most OAuth flows, our authentication takes places over a series of steps:

    1. Retrieve a request token from the Evernote Cloud API. This token is used to request an authentication token in the next step.
    2. Using the request token, send the user to the Evernote site where they will authenticate with their login credentials and authorize our application to access their account.
    3. The Evernote website will redirect the user back to our defined callback URL and append, among other things, the authentication token we will use when making calls against the Evernote Cloud API.

    This process is somewhat automated in our sample application (at least, in terms of user interaction). That is to say, as each step of the process is completed, the next step will be invoked automatically using Sinatra’s redirect facility.

    Here, we ask the Evernote Cloud API for our temporary request token.

    To start, we take the current URL as defined by the request object’s url member, remove the requesttoken portion and replace it with callback to build our callback URL. Then, we call client.authentication_request_token to request our token (and sending the callback_url variable to tell the Evernote Cloud API where to send the response. If all of this goes well, the session[:request_token] is populated with the token value and the user is scuttled off to /authorize:

    Once we verify that session[:request_token] exists, we grab the authorize_url from the request token and send the user there where they’ll be prompted to login with their Evernote account credentials and authorize our application to access their account. If session[:requesttoken] is not set, the user will see an error and be prompted to start the process over.

    After successfully authenticating with Evernote and authorizing our app, they’re sent to /callback (which we defined during the /requesttoken route):

    When the user is sent back to our callback URL, we verify that either:

    1. The oauth_verifier parameter is set in the URL.
    2. The request_token value is already present in the session.

    If one of these two conditions is true, we include the oauth_verifier parameter in our session. If neither of these conditions is true, the user is shown an error.

    Next, we extract the access token (used to make API calls) from the and add it to session. If it’s not there, an error is displayed. If it is, we send the user to the /list route we defined earlier. Assuming everything worked as advertised, the user will see their username, number of notes in their account and the name of each notebook in their account.

    Templates

    Our app utilizes two ERB templates: index and error:

    Clearly, this is a very simple template. First, we allow the user to authenticate with the Evernote Cloud API. This is displayed no matter what. If session[:notebooks] is defined, we can be reasonably sure that the user’s data has been retrieved from the Evernote Cloud API. Then we display each piece of data.

    Even simpler than index is error, which displays the value of @last_error and prompts the user to reset their session and begin the process again.

  • 4. Conclusion

    We made it!

    If you had any problems with the above application, ensure that you’re running the required versions of the various components. If you still need help, head over to the Evernote Developer site and get in touch.

Stay on top of what's happening in the Evernote developer community.