Using the Core API in Ruby

The Core API is based on HTTP and OAuth and provides low-level calls to access and manipulate a user's Dropbox account.

If you want to follow along, first register a new app on the App Console. You'll need the app key to access the Core API. Then install the Ruby SDK and you'll be ready to go.

Authenticating your app

The Core API uses OAuth v2, but the Ruby SDK will take care of most of it so you don't have to start from scratch.

You'll need to provide your app key and secret you were given when creating the app to create a DropboxOAuth2FlowNoRedirect object.

# Install this the SDK with "gem install dropbox-sdk"
require 'dropbox_sdk'

# Get your app key and secret from the Dropbox developer website
APP_KEY = 'INSERT_APP_KEY'
APP_SECRET = 'INSERT_APP_SECRET'

flow = DropboxOAuth2FlowNoRedirect.new(APP_KEY, APP_SECRET)

Now we're all set to start the OAuth flow, which has two parts:

  1. Ask the user to authorize linking your app to their Dropbox account.
  2. Once authorized, exchange the given authorization code for an access token, which will be used for calling the Core API.

We'll start by using the DropboxOAuth2FlowNoRedirect object to generate an authorization URL with the start method.

authorize_url = flow.start()

With the authorization URL in hand, we can now ask the user to authorize your app. To avoid the hassle of setting up a web server in this tutorial, we're just printing the URL and asking the user to press the Enter key to confirm that they've authorized your app. However, in real-world apps, you'll want to automatically send the user to the authorization URL and pass in a callback URL so that the user is seamlessly redirected back to your app after pressing a button.

# Have the user sign in and authorize this app
puts '1. Go to: ' + authorize_url
puts '2. Click "Allow" (you might have to log in first)'
puts '3. Copy the authorization code'
print 'Enter the authorization code here: '
code = gets.strip

Once the user has granted permission to your app, we can exhange that code for an access token via finish:

# This will fail if the user gave us an invalid authorization code
access_token, user_id = flow.finish(code)

The access token is all you'll need to make API requests on behalf of this user, so you should store it away for safe-keeping (even though we don't for this tutorial). By storing the access token, you won't need to go through these steps again unless the user reinstalls your app or revokes access via the Dropbox website.

Now that the hard part is done, all you'll need to authorize your other API calls is to to pass the access token to DropboxClient. To test that we've got access to the Core API, try calling account_info which will return a dictionary with information about the user's linked account:

client = DropboxClient.new(access_token)
puts "linked account:", client.account_info().inspect

If you've made it this far, you have a simple app that uses the Core API to link to a Dropbox account and your first API call for account info. Next, we'll upload a file to Dropbox, get its metadata, and then download it back to our app.

Uploading files

Let's say we're building a text editing app and we want to use it to save your latest magnum opus to Dropbox. Let's browse the methods in the RDocs to see which one will do that for us. This page lists all the methods supported in the SDK. If you scroll down, you'll find put_file.

put_file takes a path pointing to where we want the file on our Dropbox, and then a file-like object or string to be uploaded there. For this example, let's upload a local copy of magnum-opus:

file = open('working-draft.txt')
response = client.put_file('/magnum-opus.txt', file)
puts "uploaded:", response.inspect

If all goes well magnum-opus.txt will now be in the root of your app folder (or Dropbox folder, depending on your app's access type). The variable response will be a hash containing the metadata of the newly uploaded file. It will look something like this:

{"modified"=>"Fri, 09 Sep 2011 21:48:16 +0000",
    "bytes"=>24,
    "size"=>"24 bytes",
    "is_dir"=>false,
    "rev"=>"303eca74c",
    "mime_type"=>"text/plain",
    "icon"=>"page_white_text",
    "root"=>"dropbox",
    "path"=>"/magnum-opus.txt",
    "thumb_exists"=>false,
    "revision"=>3}

Listing folders

If you peruse the various entries in the metadata above, you'll get a good sense for all info we can gather from the file. You can get this info for an entire folder by using the metadata call.

root_metadata = client.metadata('/')
puts "metadata:", root_metadata.inspect

The returned dictionary will list out the files and folders in the path given. It looks something like this:

{"bytes"=>0,
 "size"=>"0 bytes",
 "is_dir"=>true,
 "hash"=>"0dee1c7f4457c20b386d16c8aebfc973",
 "icon"=>"folder",
 "root"=>"app_folder",
 "path"=>"/",
 "thumb_exists"=>false,
 "contents"=>
  [{"modified"=>"Fri, 09 Sep 2011 21:48:16 +0000",
    "bytes"=>24,
    "size"=>"24 bytes",
    "is_dir"=>false,
    "rev"=>"303eca74c",
    "mime_type"=>"text/plain",
    "icon"=>"page_white_text",
    "root"=>"dropbox",
    "path"=>"/magnum-opus.txt",
    "thumb_exists"=>false,
    "revision"=>3},
   {"modified"=>"Fri, 09 Sep 2011 21:47:42 +0000",
    "bytes"=>0,
    "size"=>"0 bytes",
    "is_dir"=>true,
    "rev"=>"103eca74c",
    "icon"=>"folder",
    "root"=>"dropbox",
    "path"=>"/Sample Folder",
    "thumb_exists"=>false,
    "revision"=>1}]}

In the example above, the app folder root contains a directory named Sample Folder and the file we just uploaded named magnum-opus.txt. You'll also see other various but vital bits of information such as the exact location of the file (path), file sizes (bytes), last modified date (modified), and more. If you want to tell if something has changed in the directory, you'll want to store and compare the hash parameter. Similarly, a file's rev parameter tells you if the file has changed. It's useful to keep track of the status of your files, as we'll see in the following example.

Downloading files

Some time has passed and you're ready to start editing that magnum opus of yours again. We'll need the get_file_and_metadata method to download the file.

contents, metadata = client.get_file_and_metadata('/magnum-opus.txt')
open('magnum-opus.txt', 'w') {|f| f.puts contents }

In addition to writing the file contents into the resource, get_file_and_metadata also returns the file's metadata at its current revision. Every time a change is made to the file, the rev field of the file's metadata changes as well. By saving the revision when you download the file, you'll be able to tell if that file has been updated by another computer or device and choose to download the newer revision of that file.

The complete code

For those keeping score at home, here's the full source to this guide. Make sure to make a working-draft.txt file exists to get it to work fully. Also remember to insert your app key, app secret, and access type.

# Install this the SDK with "gem install dropbox-sdk"
require 'dropbox_sdk'

# Get your app key and secret from the Dropbox developer website
APP_KEY = 'INSERT_APP_KEY'
APP_SECRET = 'INSERT_APP_SECRET'

flow = DropboxOAuth2FlowNoRedirect.new(APP_KEY, APP_SECRET)
authorize_url = flow.start()

# Have the user sign in and authorize this app
puts '1. Go to: ' + authorize_url
puts '2. Click "Allow" (you might have to log in first)'
puts '3. Copy the authorization code'
print 'Enter the authorization code here: '
code = gets.strip

# This will fail if the user gave us an invalid authorization code
access_token, user_id = flow.finish(code)

client = DropboxClient.new(access_token)
puts "linked account:", client.account_info().inspect

file = open('working-draft.txt')
response = client.put_file('/magnum-opus.txt', file)
puts "uploaded:", response.inspect

root_metadata = client.metadata('/')
puts "metadata:", root_metadata.inspect

contents, metadata = client.get_file_and_metadata('/magnum-opus.txt')
open('magnum-opus.txt', 'w') {|f| f.puts contents }