google-api-ruby-client icon indicating copy to clipboard operation
google-api-ruby-client copied to clipboard

AdMob API undefined method `has_key?' for #<Array:0x007fbf08109568>

Open jonasmora opened this issue 4 years ago • 6 comments

Environment details

  • OS: macOS 11.0
  • Ruby version: ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin19]
  • Gem name and version: google-api-client (0.44.0), googleauth (0.13.1)

Steps to reproduce

  1. Run example code

Code example

require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'google/apis/admob_v1'

OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'

Admob = Google::Apis::AdmobV1

def self.get_credentials
    scope = "https://www.googleapis.com/auth/admob.report"
    client_id = Google::Auth::ClientId.from_file("googleauth/client-secrets.json")
    token_store = Google::Auth::Stores::FileTokenStore.new(file: "googleauth/tokens.yaml")
    authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store)

    user_id = "default"

    credentials = authorizer.get_credentials(user_id)
    if credentials.nil?
        url = authorizer.get_authorization_url(base_url: OOB_URI)
        puts "Open the following URL in your browser and authorize the application."
        puts url
        puts "Enter the authorization code:"
        code = gets
        credentials = authorizer.get_and_store_credentials_from_code(
            user_id: user_id, code: code, base_url: OOB_URI)
    end

    credentials
end

publisher_id = "pub-XXXXXXXXXXXXXXXX"

admob = Admob::AdMobService.new

result = admob.generate_network_report "accounts/#{publisher_id}",
    {report_spec: {
        date_range: {start_date: {year: 2020, month: 1, day: 1}, end_date: {year: 2020, month: 9, day: 1}},
        metrics: ["ESTIMATED_EARNINGS"],
    }},
    options: {authorization: get_credentials, retries: 5}
➜  ruby sample.rb
/Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/hash/binding.rb:12:in `read': undefined method `has_key?' for #<Array:0x007fbf08109568> (NoMethodError)
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/deserializer.rb:11:in `block in <module:Representable>'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/pipeline.rb:18:in `evaluate'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/pipeline.rb:10:in `block in call'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/pipeline.rb:9:in `each'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/pipeline.rb:9:in `inject'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/pipeline.rb:9:in `call'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/binding.rb:37:in `uncompile_fragment'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable.rb:53:in `block in call'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable.rb:51:in `each'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable.rb:51:in `call'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable.rb:70:in `representable_map!'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable.rb:37:in `update_properties_from'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/hash.rb:30:in `from_hash'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/json.rb:39:in `from_json'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/google-api-client-0.44.0/lib/google/apis/core/api_command.rb:87:in `decode_response_body'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/google-api-client-0.44.0/lib/google/apis/core/http_command.rb:194:in `process_response'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/google-api-client-0.44.0/lib/google/apis/core/http_command.rb:309:in `execute_once'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/google-api-client-0.44.0/lib/google/apis/core/http_command.rb:113:in `block (2 levels) in execute'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/retriable-3.1.2/lib/retriable.rb:61:in `block in retriable'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/retriable-3.1.2/lib/retriable.rb:56:in `times'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/retriable-3.1.2/lib/retriable.rb:56:in `retriable'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/google-api-client-0.44.0/lib/google/apis/core/http_command.rb:110:in `block in execute'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/retriable-3.1.2/lib/retriable.rb:61:in `block in retriable'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/retriable-3.1.2/lib/retriable.rb:56:in `times'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/retriable-3.1.2/lib/retriable.rb:56:in `retriable'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/google-api-client-0.44.0/lib/google/apis/core/http_command.rb:102:in `execute'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/google-api-client-0.44.0/lib/google/apis/core/base_service.rb:366:in `execute_or_queue_command'
	from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/google-api-client-0.44.0/generated/google/apis/admob_v1/service.rb:182:in `generate_network_report'
	from sample.rb:35:in `<main>'

In this line:

from /Users/jonas/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/representable-3.0.4/lib/representable/json.rb:39:in `from_json'

# Parses the body as JSON and delegates to #from_hash.
def from_json(data, *args)
    data = MultiJson.load(data)
    from_hash(data, *args)
end

The code assumes data is a hash but it receives an array

[1] pry(#<Google::Apis::AdmobV1::GenerateNetworkReportResponse::Representation>)> data
=> [{"header"=>{"dateRange"=>{"startDate"=>{"year"=>2020, "month"=>1, "day"=>1}, "endDate"=>{"year"=>2020, "month"=>9, "day"=>1}}, "localizationSettings"=>{"currencyCode"=>"USD"}}}, {"row"=>{"metricValues"=>{"ESTIMATED_EARNINGS"=>{"microsValue"=>"1"}}}}, {"footer"=>{"matchingRowCount"=>"1"}}]

jonasmora avatar Sep 02 '20 15:09 jonasmora

Unfortunately this isn't something we can fix in the client. The GenerateNetworkReport call is a streaming call, which is not described correctly in the API specification (discovery document), and so the client can't tell it's supposed to be an array.

dazuma avatar Sep 09 '20 01:09 dazuma

Ok. Who is responsible for the API specification?

On Tue, 8 Sep 2020 at 22:21 Daniel Azuma [email protected] wrote:

Unfortunately this isn't something we can fix in the client. The GenerateNetworkReport call is a streaming call, which is not described correctly in the API specification (discovery document), and so the client can't tell it's supposed to be an array.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/googleapis/google-api-ruby-client/issues/902#issuecomment-689239894, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHE6KBHSKMK7SI5KYXRYMTSE3KCTANCNFSM4QTEXCWQ .

-- j^_^j

jonasmora avatar Sep 09 '20 02:09 jonasmora

+1 Having the same issue.

marcalc avatar Oct 16 '20 05:10 marcalc

👋 Greetings @jonasmora, for technical discussions with developers and members of the AdMob API team, visit the Google AdMob API Technical Forum.

I'm going to close this issue because the folks who own this repo have no actionable way to resolve it directly, but please let us know if there's anything we can do to help!

fhinkel avatar Dec 08 '20 14:12 fhinkel

Reopening as it remains an issue, and we're tracking an active internal effort to address it internally.

dazuma avatar Dec 08 '20 16:12 dazuma

As a workaround I did this

Google::Apis::AdmobV1::GenerateMediationReportResponse.class_eval do
  attr_accessor :rows
end

Google::Apis::AdmobV1::GenerateMediationReportResponse::Representation.class_eval do
  def from_json(data, *args)
    data = MultiJson.load(data)
    new_data = {}
    data.each do |datum|
      if datum.has_key? 'header'
        new_data['header'] = datum['header']
      elsif datum.has_key? 'row'
        new_data['rows'] ||= []
        new_data['rows'] << datum['row']
      elsif datum.has_key? 'footer'
        new_data['footer'] = datum['footer']
      end
    end
    from_hash(new_data, *args)
  end

  collection :rows, as: 'rows', class: Google::Apis::AdmobV1::ReportRow, decorator: Google::Apis::AdmobV1::ReportRow::Representation
end

jonasmora avatar Jan 15 '21 17:01 jonasmora