How do I use Sinatra to access the Google+ API?

How do I use Sinatra to access the Google+ API?

RubyLearning is conducting many free, online courses on Google+. Some participants wanted an answer to their question “How do I use Sinatra to access the Google+ API?” This blog post explains the same. Read on.

Pre-requisite

Install Sinatra, Git, Heroku, Bundler

Refer RubyLearning’s article on Google+.

Create a folder on your hard disk

Create a folder sinatragplus. This is where we will store our Sinatra app. Open a Bash shell in this folder.

Create the following folders also

Folder for app

Organize your application

Static Files

Static files are served from the public folder. Note that the public folder name will not be included in the URL. A file ./public/stylesheets/style.css is made available as rubylearning.org/stylesheets/style.css. Do note that we can have any directory layout under the public folder.

Layout

We will soon create layout.erb file in the views folder. This allows the basic layout of our site headers, footers and navigation panes to be controlled independently. A change in layout.erb is instantly applied across our whole site.

Let’s look at a sample file:

<html>
  <head>..</head>
  <body>
    <%= yield %>
  </body>
</html>

In the above file, note the usage of yield. The file calls yield at the point you want the content to be included i.e. it refers to some .erb in the views folder and the results of that .erb are stuck at the place, where you called yield.

Now, let’s write our app’s layout.erb file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>A Sinatra app to access Google+</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="description" content="RubyLearning.org" />
    <meta name="keywords" content="rubylearning,ruby,ruby programming,ruby course,sinatra course" />
    <link rel="stylesheet" type="text/css" href="/stylesheets/style.css" />
    <link rel="icon" type="image/ico" href="/images/favicon.ico" />
  </head>
  <body>
    <%= yield %>
  </body>
</html>

Image

I am using a favicon (favicon.ico) for my app, which is stored in the public/images folder.

Stylesheet

We have our stylesheet namely style.css in the folder public/stylesheets.

body
{
  line-height: 1.6em;
}

h1 {
  color: #2A1959;
  border-bottom: 2px solid #2A1959;
}

h2 {
  color: #474B94;
  font-size: 1.2 em;
}

#footer {
  clear: both;
  border-top: 1px solid #2A1959;
  text-align: left; 
  height: 50px; 
  font-size: 70%;
  width: 100%;
}

#hor-minimalist-a
{
  font-family: "Lucida Sans Unicode", "Lucida Grande", Sans-Serif;
  font-size: 12px;
  background: #fff;
  margin: 45px;
  width: 480px;
  border-collapse: collapse;
  text-align: left;
}
#hor-minimalist-a th
{
  font-size: 14px;
  font-weight: normal;
  color: #039;
  padding: 10px 8px;
  border-bottom: 2px solid #6678b1;
}
#hor-minimalist-a td
{
  color: #669;
  padding: 9px 8px 0px 8px;
}
#hor-minimalist-a tbody tr:hover td
{
  color: #009;
}

View

A view is responsible for generating a user interface, normally based on data. For example, an online store will have a list of products to be displayed on a catalogue screen. The view accesses the data and formats it for the end-user.

All file-based views are looked up in the views folder.

Using ERB

ERB is written in pure Ruby and is included with the standard Sinatra distribution. ERB allows you to embed Ruby statements in an HTML page.

The important things to know about an .erb file is that <%= ruby_code %> evaluates the ruby code and outputs the result, and <% ruby_code %> evaluates the code, but doesn’t output anything.

We will use ERB for our app.

Note: If we write:

get '/' do
  erb :index
end

This tells Sinatra that when a GET request for ‘/’ comes in, that we should use the ERB helper to render the index.erb template, which is stored in the views sub-folder by convention and marked up with embedded Ruby (ERB).

Write the sinatragplus.rb app

Store sinatragplus.rb in the folder sinatragplus:

# sinatragplus.rb
require 'sinatra'
require 'google_plus'

error do
  erb :'500'
end

#class
class GPlus
  def initialize(apikey, gid)
    @apikey = apikey
    @gid = gid
    get_info
  end
  attr_reader :row0, :row1, :row2
  private
    #Get info about specific G+ ID
    def get_info
      # GooglePlus.api_key = 'Your API Key'
      begin
        GooglePlus.api_key = @apikey
        person = GooglePlus::Person.get(@gid.to_i)
        @row0 = person.display_name
        @row1 = person.tagline
        @row2 = person.url
      rescue Exception => msg  
        # display the system generated error message  
        puts msg  
      end  
    end
end
 
get '/' do
  erb :index
end

# Display Google+ details
post '/show' do
  @gplus = GPlus.new(params[:apikey], params[:gid])
  erb :show
end

Explanation

  • Install: gem install google_plus.
  • We are going to use the above installed google_plus gem.
  • To access the Google+ API, get your own Google API key.
  • Note down the Google+ ID of the person whose Google+ profile you want to display using this app. For example, here’s my Google+ URL and the number in the URL namely 107809992818057105754 is my Google+ ID.
  • When a GET request for ‘/’ comes in, we are going to render the index.erb template in the public/views folder.
  • The file index.erb has a HTML form that accepts the Google+ API key and ID for the user profile that you want to display. Note that even if you do not give any value to these fields, the app will not crash. Handler is the generic term that Sinatra uses for the “controllers”. A handler is the initial point of entry for new HTTP requests into your application. In handlers you can reach submitted form parameters directly via the params hash. Also note, that when you click on the submit button of the form a POST request is being sent.
  • The post '/show' do creates an object of our class GPlus passing to the initialize method the apikey and google id that your entered on the screen (via params). The initialize method in-turn calls a private method get_info that accesses the Google+ API and returns a person object We call the method display_name, tagline and url on the person object and populate instance variables @row0, @row1 and @row2.
  • The show.erb displays these values in a HTML table.

Error Handling

When someone comes to a page on your domain that is no longer there (either because it’s been deleted, because they’ve typed something in wrong or because the link that they followed was wrong) they are shown the dreaded 404 ‘page not found’ error page.

This error simply means that the person was able to communicate with your server but that the server couldn’t find the page that they were after.

404 errors should not be confused with “server not found” or similar errors, in which a connection to the destination server could not be made at all.

When a Sinatra::NotFound exception is raised, or the response’s status code is 404, the not_found handler is invoked:

Write 404.erb in the public/views folder. Note that I had to surround the erb :'404' in single quotes. This is because Ruby syntax doesn’t let symbol’s first character be a number. By quoting it, it gets around that issue.

A 500 error page will be thrown to the client when the Web server (running the Web Site) encounters an unexpected condition that prevents it from fulfilling the request by the client (e.g. your Web browser) for access to the requested URL.

By default error will catch Sinatra::ServerError. Sinatra will pass you the error via the ‘sinatra.error’ in request.env.

Write 500.erb in the public/views folder.

Our app is ready! Let’s deploy it to Heroku.

Create config.ru file in the folder sinatragplus

This file contains:

require './sinatragplus'
run Sinatra::Application

Install required gems for our app

In the Bash shell type:

$ bundle init

Edit the created Gemfile with your preferred text editor to let it look like this:

source "http://rubygems.org"
gem 'sinatra'
gem 'google_plus'

In the Bash shell type:

$ bundle check

Finally in the open Bash shell, type:

$ bundle install

Create a Procfile

Use a Procfile, a text file in the root directory of your application, to explicitly declare what command should be executed to start a web dyno. In this case, you simply need to execute the sinatragplus.rb using Ruby.

Here’s our Procfile:

web: bundle exec ruby sinatragplus.rb -p $PORT

Setup your local app to use Git

I have the sinatragplus.rb, Procfile and config.ru files already in the folder sinatragplus.

In the already open Bash shell, type:

$ git init
$ git add .
$ git commit -m "sinatragplus first commit"

Create the app on Heroku

In the bash shell, type:

$ heroku create sinatragplus

Push your application to Heroku

$ git push heroku master

That’s it, the app is now running on Heroku! You can take a look at it, in your browser type: http://sinatragplus.herokuapp.com/.

What next?

On the person object use the attributes method to get all the person fields back as a Hash:

properties = person.attributes
properties.each { |key, value| puts "#{key} equals #{value}" }

Exercise

In show.erb I have populated only the display_name, tagline and url fields of person. Populate all the other person fields in the HTML table that is generated by show.erb.

Have fun!

Do post a link to your version of this program. Feel free to ask questions and give feedback in the comments section of this post. Fellow Rubyists, if you would like to write a guest blog post for RubyLearning email me at satish [at] rubylearning.org

comments powered by Disqus