CRUD Actions with Google Calendar and Rails


In a previous post, I talked about setting up Google’s OAuth with a Rails app. Today I am going to go through the complete steps of adding, updating, and deleting a event from an Event Dashboard in your Rails app that will also add, update, and delete that event in a corresponding Google Calendar (I am adding, updating, and deleting events to my personal calendar, but you can change the calendarId option in the parameters to any calendar that you have admin access to).

Step 1: Getting your Event Model Ready for Google Calendar

The first thing we need to do is to add another attribute to our events model so that we can store the google event id after we create the event and push it to our Google Calendar. For simplicity, I called this google_event_id and gave it a string attribute.

Step 2: Creating an Event

We need to update the create action in our events controller so that after we make the API call to add the event to the Google Calendar, we save the google event id to the event object. We will need this google event id in the future to update and delete google calendar events from our Rails app.

def create
    @event = Event.new(event_params)

    if @event.save

      render :nothing => true
      google_event = { 'summary' => @event.title, 'description' => @event.description, 'location' => @event.location, 'start' => {'dateTime' => @event.start_time}, 'end' => {'dateTime' => @event.end_time}, 'attendees' => [{"email" =>'landon.marder@gmail.com'}] }

      client = Google::APIClient.new
      client.authorization.access_token = current_user.token
      service = client.discovered_api('calendar', 'v3')

      result = client.execute(:api_method => service.events.insert,
                              :parameters => {'calendarId' => 'landon.marder@gmail.com', 'sendNotifications' => true},
                              :body => JSON.dump(google_event),
                              :headers => {'Content-Type' => 'application/json'})

      @event.google_event_id = result.data.id
      @event.save
    else
      render :nothing => true
    end
  end

Step 3: Updating an Event

Now that we have a google_event_id as an attribute of each newly created event model, we can query the Google Calendar API for that specific event and update it in our events controller. I gave a conditional in case there is no google_event_id (for historical events that were not tied to the google calendar)

def update
  @event = Event.find(params[:id])


  if @event.update(event_params)
    render :nothing => true

    unless @event.google_event_id.nil?
      client = Google::APIClient.new
      client.authorization.access_token = current_user.token
      service = client.discovered_api('calendar', 'v3')

      result = client.execute(:api_method => service.events.get, :parameters => {'calendarId' => 'landon.marder@gmail.com', 'eventId' => @event.google_event_id } )

      event = result.data
      event.summary = @event.title
      event.start.dateTime = @event.start_time
      event.end.dateTime = @event.end_time
      event.description = @event.description
      event.location = @event.location

      result = client.execute(:api_method => service.events.update,
                              :parameters => {'calendarId' => 'landon.marder@gmail.com', 'eventId' =>  @event.google_event_id},
                              :body_object => event,
                              :headers => {'Content-Type' => 'application/json'})
    end
  else
    render :nothing => true
  end
end

Step 4: Deleting an Event

Similarly, with the google_event_id attribute of the event object, you can delete an event from the events controller.

def destroy
  @event = Event.find(params[:id])

  @event.destroy

  if @event.destroyed?
    unless @event.google_event_id.nil?
      client = Google::APIClient.new
      client.authorization.access_token = current_user.token
      service = client.discovered_api('calendar', 'v3')

      result = client.execute(:api_method => service.events.delete,
                              :parameters => {'calendarId' => 'landon@work-bench.com', 'eventId' => @event.google_event_id})
    end
  end
  redirect_to events_path, notice: "#{@event.title} - has been removed."
end