Integrate Google Calendar API into rails application

Google Calendar is a widely used tool that helps millions of people stay organized and on top of their schedules.

By incorporating its powerful API into our Rails application, we can unlock a wealth of functionality that empowers us to seamlessly synchronize events, create new appointments, and even automate reminders.

In this blog post, we’ll explore the step-by-step process of integrating the Google Calendar API into our Rails application.

To integrate the Google Calendar API into our rails application first, we’ll need to install the google-api-ruby-client gem.

Add it into the Gemfile -

  gem 'google-apis-calendar_v3'

After adding it in the Gemfile run bundle install in the console to install it and the head over to the Google Console. Enable the Google Calendar API from the library page by clicking on the Google Calendar API on the screen which is present under the Google Workspace section. Alternatively, we can also search on the library page and find it.

Once the API has been enabled visit this link for steps on configuring OAuth consent.

Now copy the API key and Client ID and paste it into the .env file -

GOOGLE_CLIENT_ID="YOUR_CLIENT_ID"
GOOGLE_CLIENT_SECRET="YOUR_CLIENT_SECRET"

Now let’s create a separate controller for it:

rails g controller Calendars

After we’ve generated the controller let’s add the redirect action to it -

class CalendarsController < ApplicationController
  def redirect
    respond_to do |format|
      format.json { render json: { url: @client.authorization_uri.to_s } },
      format.html { redirect_to client.authorization_uri.to_s }
    end
  end

  private

    def client_options
      {
        client_id: ENV.fetch("GOOGLE_CLIENT_ID", ""),
        client_secret: ENV.fetch("GOOGLE_CLIENT_SECRET", ""),
        authorization_uri: "https://accounts.google.com/o/oauth2/auth",
        token_credential_uri: "https://oauth2.googleapis.com/token",
        scope: Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY,
        redirect_uri: callback_url
      }
    end

After writing this head over to the routes.rb file and add the following routes -

  get "/redirect", to: "calendars#redirect"
  get "/callback", to: "calendars#callback"

Now open the browser and visit the /redirect route which will redirect us to Google’s consent screen where we’ll need to provide the consent to let the user access the data.

Signet is just an underlying implementation of OAuth 2.0 that the google-api-client gem uses.

authorization_uri method does all the work of constructing the correct URI with the required params provided we have entered all the correct details in the client options, we just need to convert the constructed URI to string.

token_credential_uri parameter is Google’s OAuth 2.0 token endpoint, the scope parameter determines the level of API access that our application is asking for, and the redirect_uri parameter is the route in the application that Google will redirect back to after it has authenticated the user.

In the above example, we are using the scope - Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY which indicates that the API access given to the user will only consist of fetching the data and not creating, updating, or deleting. We can also, use the URL https://www.googleapis.com/auth/calendar.readonly instead.

The next step after this would be the implementation of the callback method for which we already have a route written for it. What we do in this method is exchange the authorization code that we get from the URL and exchange it for the access token. Let’s have a look -

  def callback
    client = Signet::OAuth2::Client.new(client_options)

    authorization_code = params[:code]

    @client.code = authorization_code

    response = @client.fetch_access_token!
    session[:authorization] = response

    redirect_to calendars_url
  end

Let’s add a calendar route as well or else this would fail -

  get "/calendars", to: "calendars#calendars"

Response is a hash containing keys like this -

  {"access_token"=>"YOUR_ACCESS_TOKEN",
  "expires_in"=>3599,
  "refresh_token"=>"REFRESH TOKEN FROM THE SERVER",
  "scope"=>"https://www.googleapis.com/auth/calendar.readonly",
  "token_type"=>"Bearer"}

Now, after we get the access and store it inside the session we can now fetch the list of calendars -

  def calendars
    client = Signet::OAuth2::Client.new(client_options)

    client.update!(session[:authorization])

    service = Google::Apis::CalendarV3::CalendarService.new
    service.authorization = client

    @calendar_list = service.list_calendar_lists
  end

Here we authenticate the user, update the client with the hash we got in the previous method, use the Google::Apis::CalendarV3::CalendarService service as it provides the methods needed for calling the calendar API, and list_calendar_lists gives us the list of calendars.

Now when we visit the /calendars route we’ll be able to see the list of calendars after we add a view and loop over the calendar list to show it.

  get "/events/:calendar_id", to: "calendars#events", as: "events", calendar_id: "/[^\/]+/"

After we’ve got the list of calendars, we can now finally get the list of events -

  def events
    service = Google::Apis::CalendarV3::CalendarService.new
    service.authorization = client

    @event_list = service.list_events(params[:calendar_id])
  rescue Google::Apis::AuthorizationError
    response = client.refresh!

    session[:authorization] = session[:authorization].merge(response)

    retry
  end

Here, we use the CalendarService just like before and we use the list_events method from the calendar service.

list_events method accepts a calendar_id as an argument which we get from the params after we click on a calendar from the view file.

The access token provided by Google expires in an hour and if we want to use it further more than that we can rescue the Google::Apis::AuthorizationError.

Refresh the access token using client.refresh!.

Then merge it into the existing session[:authorization] which updates the existing hash and makes use of retry which would re-run the method from the beginning making use of the newly acquired access token.

Using retry anywhere can cause the application to go in an infinite loop if not used properly.

Summary

We looked into how we can integrate Google Calendar into our Rails application, enabling the API from developers console, and learning what Signet does as well as what values the client options hold and what each option does.

Need help on your Ruby on Rails or React project?

Join Our Newsletter