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

时间:2014-07-23 07:56:01

标签: 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_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,我会获得一组返回分配给变量结果的结果。

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

有没有办法重构这个,以便授权调用可以包含在其on方法中,所有我改变的是分配给结果的请求参数?

这样的事情

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

其中一个问题是在new_users方法中可以使用局部变量 client result ,这些可以改为什么?一个带@的实例变量?或带有@@?

的类变量

2 个答案:

答案 0 :(得分:4)

你的直觉很好 - 你don't want to repeat yourself,并且有更好的方法来构建这段代码。但是,您应该考虑小块,松散地加入,而不是共享变量。编写能很好地完成一件事的方法,并将它们组合在一起。例如,我们可以编写一个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

它是protected,因为外部代码 - 您Analytic课程之外的内容 - 不应该直接使用它。他们应该使用我们为他们提供的方法。


您还可以提供帮助方法来从API获取结果。我不熟悉查询API,但看起来它的metrics值会发生变化。也许是这样的:

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_visits会返回get_result('ga:pageViews')['totalsForAllResults']['ga:pageviews']。课堂外的代码不应该知道要使用它的GA数据格式。这称为encapsulation

答案 1 :(得分:1)

通过谈论Skype,我认为有几件事要看


<强>初始化

目前,每次要使用该模块时,都使用google_analytics_api方法。这完全是低效的,这也是你现在遇到这个问题的部分原因。相反,我会创建一个init方法,每当你initialize the object(并将GoogleAnalytics变成自己的类)时,它会触发:

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

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

@analytics = GoogleAnalytics.new #-> fires initialize method

这将使您能够调用对象(将从API中提取数据),然后根据您拥有的不同用例相应地拆分数据。


实例方法

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

你所指的是什么,以及Alex P所指的是实例方法的概念。这可以兼作对象的属性,但实质上允许您在方法的实例上调用一段功能。

所以在亚历克斯的例子中,你有:

def new_users
  get_result('ga:newUsers')
end

这只是调用您班级的instance方法:

GoogleAnalytics::Analytic.new_users

这将创建Analytic类的实例,然后调用new_users方法(应该是class method)。然后,此方法将允许您在新初始化的对象上调用instance方法,因此get_result方法调用

-

我建议的是在对象初始化后使用instance methods ,让您对使用google_analytics_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

对此的一个警告是,这是否可以在没有模块的情况下工作。我认为它应该,但它对我来说没有经过考验