Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/54.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在另一个Ruby方法中访问局部变量_Ruby On Rails_Ruby_Ruby On Rails 4_Methods_Google Api - Fatal编程技术网

Ruby on rails 在另一个Ruby方法中访问局部变量

Ruby on rails 在另一个Ruby方法中访问局部变量,ruby-on-rails,ruby,ruby-on-rails-4,methods,google-api,Ruby On Rails,Ruby,Ruby On Rails 4,Methods,Google Api,我希望了解如何访问方法a中的变量集,然后在方法B中使用该变量,以及如何以干净的方式重用代码的相同部分,然后只更改查询 require 'google/api_client' module GoogleAnalytics class Analytic SERVICE_ACCOUNT_EMAIL_ADDRESS = ENV['SERVICE_ACCOUNT_EMAIL_ADDRESS'] PATH_TO_KEY_FILE = ENV['PATH_TO_KEY_FI

我希望了解如何访问方法a中的变量集,然后在方法B中使用该变量,以及如何以干净的方式重用代码的相同部分,然后只更改查询

require 'google/api_client'

module GoogleAnalytics
 class Analytic

 SERVICE_ACCOUNT_EMAIL_ADDRESS = ENV['SERVICE_ACCOUNT_EMAIL_ADDRESS']
 PATH_TO_KEY_FILE              = ENV['PATH_TO_KEY_FILE']
 PROFILE                       = ENV['ANALYTICS_PROFILE_ID']

def google_analytics_api

client  = Google::APIClient.new(
  application_name: "Example Application",
  application_version: "1.0")

client.authorization = Signet::OAuth2::Client.new(
  :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
  :audience             => 'https://accounts.google.com/o/oauth2/token',
  :scope                => 'https://www.googleapis.com/auth/analytics.readonly',
  :issuer               => SERVICE_ACCOUNT_EMAIL_ADDRESS,
  :signing_key          => Google::APIClient::KeyUtils.load_from_pkcs12(PATH_TO_KEY_FILE, 'notasecret')).tap { |auth| auth.fetch_access_token! }

  api_method = client.discovered_api('analytics','v3').data.ga.get


  # make queries
  result = client.execute(:api_method => api_method, :parameters => {
  'ids'        => PROFILE,
  'start-date' => Date.new(2014,1,1).to_s,
  'end-date'   => Date.today.to_s,
  'dimensions' => 'ga:pagePath',
  'metrics'    => 'ga:pageviews',
  'filters'    => 'ga:pagePath==/'
 })
  end
 end
end
因此,如果我运行google_analytics_api方法,我会得到一组分配给变量result的返回结果

那么,如果我想要另外两个单独的方法,它们将返回不同的结果集,那么 新用户和跳出率,这将是两个不同的调用更改请求参数,不是吗?我需要重复整个方法吗

有没有办法重构它,这样授权调用就可以封装在它的on方法中,我所做的更改就是将请求参数分配给result

像这样的

def api_call
  logic to make request
end

def new_users
  api_call
   # make queries
  result = client.execute(:api_method => api_method, :parameters => {
  'ids'        => PROFILE,
  'start-date' => Date.new(2014,1,1).to_s,
  'end-date'   => Date.today.to_s,
  'dimensions' => 'ga:pagePath',
  'metrics'    => 'ga:newUsers',
  'filters'    => 'ga:pagePath==/'
 })


end

尽管其中一个问题是,在新的_users方法中可以使用局部变量客户机和结果,但这些可以更改为什么?带有@的实例变量?或者是一个带有@@?

的类变量,你的直觉很好-你自己,而且有更好的方法来构造这段代码。但与其共享变量,不如考虑松散连接的小块。写一个能很好地完成一件事的方法,并将它们结合在一起。例如,我们可以编写一个
get_client
方法,该方法只返回一个
client
,供其他方法使用:

protected
def get_client
  client  = Google::APIClient.new(
    application_name: "Example Application",
    application_version: "1.0")

  client.authorization = Signet::OAuth2::Client.new(
    :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
    :audience             => 'https://accounts.google.com/o/oauth2/token',
    :scope                => 'https://www.googleapis.com/auth/analytics.readonly',
    :issuer               => SERVICE_ACCOUNT_EMAIL_ADDRESS,
    :signing_key          => Google::APIClient::KeyUtils.load_from_pkcs12(PATH_TO_KEY_FILE, 'notasecret')).tap { |auth| auth.fetch_access_token! }
  client
end
它受到
保护
,因为外部代码-你的
分析类之外的东西-不应该直接使用它。他们应该使用我们为他们提供的方法


您还可以提供一个助手方法来从API获取结果。我不熟悉查询API,但看起来是您的
度量值改变了。所以可能是这样的:

protected
def get_result(metrics)
  client = self.get_client
  api_method = client.discovered_api('analytics','v3').data.ga.get

  result = client.execute(:api_method => api_method, :parameters => {
    'ids'        => PROFILE,
    'start-date' => Date.new(2014,1,1).to_s,
    'end-date'   => Date.today.to_s,
    'dimensions' => 'ga:pagePath',
    'metrics'    => metrics,
    'filters'    => 'ga:pagePath==/'
   })
  result
end

现在,您可以编写外部类可以使用的简单方法:

def new_users
  get_result('ga:newUsers')
end

def total_visits
  get_result('ga:pageViews')
end

如果可以,尝试从这些方法返回简单数据。也许
total_visions
将返回
get_result('ga:pageViews')['totalsForAllResults']['ga:pageViews']
。类外的代码不必知道GA数据格式就可以使用它。这就是所谓的。

你的直觉是好的-你,而且有更好的方法来构建这段代码。但与其共享变量,不如考虑松散连接的小块。写一个能很好地完成一件事的方法,并将它们结合在一起。例如,我们可以编写一个
get_client
方法,该方法只返回一个
client
,供其他方法使用:

protected
def get_client
  client  = Google::APIClient.new(
    application_name: "Example Application",
    application_version: "1.0")

  client.authorization = Signet::OAuth2::Client.new(
    :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
    :audience             => 'https://accounts.google.com/o/oauth2/token',
    :scope                => 'https://www.googleapis.com/auth/analytics.readonly',
    :issuer               => SERVICE_ACCOUNT_EMAIL_ADDRESS,
    :signing_key          => Google::APIClient::KeyUtils.load_from_pkcs12(PATH_TO_KEY_FILE, 'notasecret')).tap { |auth| auth.fetch_access_token! }
  client
end
它受到
保护
,因为外部代码-你的
分析类之外的东西-不应该直接使用它。他们应该使用我们为他们提供的方法


您还可以提供一个助手方法来从API获取结果。我不熟悉查询API,但看起来是您的
度量值改变了。所以可能是这样的:

protected
def get_result(metrics)
  client = self.get_client
  api_method = client.discovered_api('analytics','v3').data.ga.get

  result = client.execute(:api_method => api_method, :parameters => {
    'ids'        => PROFILE,
    'start-date' => Date.new(2014,1,1).to_s,
    'end-date'   => Date.today.to_s,
    'dimensions' => 'ga:pagePath',
    'metrics'    => metrics,
    'filters'    => 'ga:pagePath==/'
   })
  result
end

现在,您可以编写外部类可以使用的简单方法:

def new_users
  get_result('ga:newUsers')
end

def total_visits
  get_result('ga:pageViews')
end

如果可以,尝试从这些方法返回简单数据。也许
total_visions
将返回
get_result('ga:pageViews')['totalsForAllResults']['ga:pageViews']
。类外的代码不必知道GA数据格式就可以使用它。这就是所谓的。

通过在Skype上的交谈,我认为有几件事需要考虑


Init

目前,每当您想使用该模块时,您都在使用
google\u analytics\u api
方法。这是完全没有效率的,这也是你现在有这个问题的部分原因。相反,我将创建一个
init
方法,它将在每次启动时启动(并将
GoogleAnalytics
生成一个自己的类):

这将允许您将当前模块视为真正的Ruby对象-如下所示:

@analytics = GoogleAnalytics.new #-> fires initialize method
这将使您能够调用对象(它将从API中提取数据),然后根据您拥有的不同用例相应地分割数据


实例方法

这使我很好地理解了实例方法的概念

您所指的,实际上也是Alex p所指的,是实例方法的思想。它兼作对象的属性,但本质上允许您在方法实例上调用一段功能

在Alex的例子中,你有:

def new_users
  get_result('ga:newUsers')
end
这只是调用类的
实例
方法:

GoogleAnalytics::Analytic.new_users
这将创建一个
analysis
类的实例,然后调用
new\u users
方法(应该是一个实例)。然后,此方法将允许您对新初始化的对象调用
实例
方法,从而调用
获取结果
方法

--

我的建议是在对象初始化后使用
实例方法
,让您能够访问使用
google\u analytics\u api定义的数据

例如:

#app/controllers/analyics_controller.rb
Class AnalyticsController < ApplicationController
   def index
       @analytics = GoogleAnalytics.new
       @new_users = @analytics.new_users
   end
end

#lib/google_analytics.rb
Class GoogleAnalytics
   def initialize
       ... google_analytics_api method here
   end

   def new_users
      return [new_users_data]
   end
end
#app/controllers/analyics_controller.rb
类AnalyticsController<应用程序控制器
def索引
@analytics=GoogleAnalytics.new
@新用户=@analytics.new\u用户
终止
终止
#lib/google_analytics.rb
类分析
def初始化
... google_analytics_api方法
终止
def新用户
返回[新用户\u数据]
终止
终止

需要注意的一点是,在没有模块的情况下,这是否会起作用。我想应该是的,但这对我来说还没有经过测试,从Skype上讲,我认为有几件事需要考虑


Init

目前,每当您想使用该模块时,您都在使用
google\u analytics\u api
方法。这是完全没有效率的,这也是你现在有这个问题的部分原因。相反,我将创建一个
init
方法,它将在每次您(并将
GoogleAnalytics
放入它的一个类中)启动