With Google API Client, how to create client
Asked Answered
A

3

13

I'm working to use the Google API Client: https://github.com/google/google-api-ruby-client

Specifically, I want to access Google Contacts via the Google API client using the following google_contacts_api.rb: https://gist.github.com/lightman76/2357338dcca65fd390e2

I am trying to use google_contacts_api.rb like so (x is intentional and is actually the correct keys):

require './lib/google_contacts_api.rb'
auth = User.first.authentications.first
client = OAuth2::Client.new('x', 'x', :site => 'https://accounts.google.com')
oauth2_object = OAuth2::AccessToken.new(client, auth.token)
x = ContactList::GoogleContactsApi.new(client, oauth2_object).all_contacts

This is erring with undefined methodget' for # Did you mean? gem`

I believe the issue is I am not sending client correctly and I have been unable to find any doc or examples showing how to create client. How can I get this to work?

Agar answered 23/2, 2017 at 5:47 Comment(4)
Did you check alvin's answer here: #25637985?Yeld
Which Signet::OAuth2::Client are you using?Sansen
@Sansen I have the following installed: gem 'signet', '0.7.3'Agar
Part of the problem you are having is you are mixing apis. The ruby client was meant to work with discovery APIs. While the contacts API is an old GData api. github.com/tokumine/GData Gdata talks xml discovery talks Json. The two do not speak the same language. Have you looked at the People API as far as I can tell the data is similar.Callie
M
10

Note : As getting a contacts list usually requires a user's authentication to read private data, in the example below I assume that you've already implemented Oauth2 authentication with a sufficient scope and you got a valid ’token’ from that first step.

Lot of outdated/confusing documentation online because APIs' authentication and APIs themselves have been upgraded many times. To me most useful documentation is the one at http://www.rubydoc.info/github/google/google-api-ruby-client/

gem 'google-api-client' is still in alpha and moving quite fast, after lot of struggling I've been able to work with authenticated calls to Youtube, Gmail and Analytics APIS. I hope Contacts API work the same.

The Google API Ruby Client contains everything needed to manage API authentication and then request authorized subservices APIs. No need to struggle with Hurley, Signet or other HTTP/Rest clients.

#Gemfile
gem 'google-api-client'


#Class file
require 'google/api_client/client_secrets.rb' #Manage global google authentication
require 'google/apis/youtube_v3' #To be replaced with the proper Contact API

access = {...} #Credentials object returned by your Oauth strategy (gem 'omniauth-google-oauth2' works like a charm) 
secrets = Google::APIClient::ClientSecrets.new({
"web" => {"access_token" => access['token'], 
"refresh_token" => access['refresh_token'],
"client_id" => "xxxxxxxx.apps.googleusercontent.com", 
"client_secret" => "xxxxxxxxxxxx"}})

client = Google::Apis::YoutubeV3::YouTubeService.new #As per the require line, update it with you service API
client.authorization = secrets.to_authorization
client.authorization.refresh!

So far client variable is an authorized and ready to query object that I use like this for example in order to search for Youtube contents

client.list_searches('snippet', q: 'xxxxxx', type: 'channel'){ |res, err|
Millerite answered 3/3, 2017 at 13:23 Comment(3)
This was also an extremely frustrating problem for me. Wrote up a blog post that came to similar conclusions as you: medium.com/@_benrudolph/…Piteous
Do you always run refresh! ? It feels unnecessary to make the extra trip to Google if the access_token hasn't expired.Apathetic
@FellowStranger not exactly implemented that way but yes it seems allright to save a request by testing first the expiration date of the actual token before requesting a refresh.Millerite
Z
3

You're getting that error because you're using passing the wrong objects to
ContactList::GoogleContactsApi.new(client, auth). That gist expects for client to be an instance of the dead Hurley HTTP client and auth to be an OAuth2 instance from Google's Signet library. Instead you're trying to Intridea's OAuth2 libary.

Since Hurley is a dead project, and that gist lacks any unit tests, I'd recommend you use a tested and working implementation such as the google_contacts_api gem which is compatible with Intridea's OAuth2 library:

require 'google_contacts_api'

auth = User.first.authentications.first
client = OAuth2::Client.new('x', 'x', :site => 'https://accounts.google.com')
oauth2_object = OAuth2::AccessToken.new(client, auth.token)
google_contacts_user = GoogleContactsApi::User.new(oauth2_object)

The issue of refreshing tokens really belongs in a separate question. In short, you'll have to make a request for a new token periodically using the refresh token Google provides:

data = {
  :client_id => GOOGLE_APP_KEY,
  :client_secret => GOOGLE_APP_SECRET,
  :refresh_token => oauth2_refresh_token_for_user,
  :grant_type => "refresh_token"
}
response = ActiveSupport::JSON.decode(RestClient.post("https://accounts.google.com/o/oauth2/token"), data)
if response["access_token"].present?
  puts response["access_token"]
else
  # No Token
end
rescue RestClient::BadRequest => e
  # Bad request
rescue
  # Something else bad happened
end
Zolly answered 26/2, 2017 at 18:17 Comment(2)
Thanks but this example doesn't deal with needed to refresh the token which is where I got stuck. Any idea how to refresh the token for this recommended gem?Agar
You'll have to refresh the token yourself. See #21708234 and github.com/zquestz/omniauth-google-oauth2/issues/37 for examples. I've included a short one above.Zolly
S
2

https://gist.github.com/lightman76/2357338dcca65fd390e2 says client should be a Hurley client. It looks like you are passing an OAuth2::Client, which apparently doesn't respond to

get()

For client and auth, I would recommend trying a Hurley client and a Signet::OAuth2::Client auth.

Sansen answered 25/2, 2017 at 14:38 Comment(1)
Thanks but can you show an example on how to do that?Agar

© 2022 - 2024 — McMap. All rights reserved.