Raystorm
Raystorm

Reputation: 6548

Why Am I getting a NoMethodError when using the google API to run a query against google Big Query?

I'm trying to run a Query against Google Big Query, using the Ruby API.

This is my first project with Ruby and I'm still learning the language.

This is also my first project using the Google API.

ENVIORNMENT:

My Code runs without giving any warnings or error messages through:

@client.authorization.fetch_access_token! 
doc = File.read('bigQueryAPI.json')
@bigQuery = @client.register_discovery_document('bigquery', 'v2', doc)

NOTE: @bigQuery is loaded from a file because when I try to load @bigquery with
@bigquery = @client.discovered_api('bigquery', 'v2')
I get Google::APIClient::ClientError: Not Found and inspect only prints
#<Google::APIClient::API:0x17c94cc ID:bigquery:v2>

However If I save the Big Query API as a text file from https://www.googleapis.com/discovery/v1/apis/bigquery/v2/rest

and then load it as a text file with

doc = File.read('bigQueryAPI.json')
@bigQuery = @client.register_discovery_document('bigquery', 'v2', doc)

then @bigQuery.inspect actually returns something useful. @bigQuery.inspect output.

However, When I try to actually run a query, like so:

result = @client.execute!(
           :api_method => @bigQuery.batch_path.query,
           :body_object => { "query" => "SELECT count(DISTINCT repository_name) as repository_total, " +
                                 "count(payload_commit) as commits_total, " +
                                 "count(DISTINCT repository_name) / count(payload_commit) as average, " +
                                 "FROM [githubarchive:github.timeline]" }, #,
           :parameters => { "projectId" => @project_id })

I get the following error:

NoMethodError: undefined method `query_values' for nil:NilClass

Here's the Full Stacktrace of the error:

    1) Error:  
test_averages(Test_GitHub_Archive):   
NoMethodError: undefined method `query_values' for nil:NilClass  
   C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client/request.rb:145:in `uri=' 
   C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client/request.rb:101:in `initialize'  
   C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client.rb:518:in `new'  
   C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client.rb:518:in `generate_request'  
   C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client.rb:583:in `execute!'  
   C:/Users/tfburton/Documents/private/ProjectSuggestor/RubyStats/GitHub_Archive.rb:39:in `get_averages'  
   C:/Users/tfburton/Documents/private/ProjectSuggestor/RubyStats/TestSpec/test_GitHub_Archive.rb:26:in `test_averages'  

Here is the results for @client.inspect
NOTE: I would have pasted here, but my post ended over the length limit.

After doing some digging. It looks like I'm not passing the proper @bigQuery prameter to get the query function.
Looking at the dump for @bigQuery.inspect I need to pass the method at line 751.
However I can't seem to figure out how to pass that method.

If you strip out the rest of the inspect output the "path" looks like this:
{ "resources => { "jobs" => { "methods" => { "query"

I've tried @bigQuery.Jobs.query and that results in an error stating that @bigQuery.Jobs doesn't exist.

Upvotes: 2

Views: 1613

Answers (1)

David
David

Reputation: 5519

Here's how I got it to work with the bigquery.jobs.query method, which is probably what you need.

I had to set OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE because otherwise the authorization process would fail miserably, but that might be specific to min Win7/MgitSys environment. In any case, this specific line is not safe in prod.

require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/installed_app'
require 'google/api_client/auth/file_storage'
require 'openssl'
require 'json'

OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE 

# Initialize the client.
client = Google::APIClient.new(
  :application_name => 'Example Ruby application',
    :application_version => '1.0.0'
    )

    CREDENTIAL_STORE_FILE = "#{$0}-oauth2.json"
     file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
    # Initialize Google+ API. Note this will make a request to the
    # discovery service every time, so be sure to use serialization
    # in your production code. Check the samples for more details.
    @bigQuery = client.discovered_api('bigquery', 'v2')

    # Load client secrets from your client_secrets.json.
    client_secrets = Google::APIClient::ClientSecrets.load

     file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
      if file_storage.authorization.nil?
        client_secrets = Google::APIClient::ClientSecrets.load
        # The InstalledAppFlow is a helper class to handle the OAuth 2.0 installed
        # application flow, which ties in with FileStorage to store credentials
        # between runs.
        flow = Google::APIClient::InstalledAppFlow.new(
          :client_id => client_secrets.client_id,
          :client_secret => client_secrets.client_secret,
          :scope => ['https://www.googleapis.com/auth/cloud-platform','https://www.googleapis.com/auth/bigquery']
        )
        client.authorization = flow.authorize(file_storage)
      else
        client.authorization = file_storage.authorization
      end



      puts "authorized, requesting"

      # Make an API call.
      result = client.execute!(
           :api_method => @bigQuery.jobs.query,
           :body_object => { "query" => "SELECT count(DISTINCT repository_name) as repository_total, " +
                                 "count(payload_commit) as commits_total, " +
                                 "count(DISTINCT repository_name) / count(payload_commit) as average, " +
                                 "FROM [githubarchive:github.timeline]" }, #,
           :parameters => { "projectId" => "845227657643" })

          puts  JSON.dump result.data

Upvotes: 2

Related Questions