我希望了解如何访问方法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
其中一个问题是,在new_users方法中可以使用局部变量client和result,这些可以更改为什么?带有@的实例变量?或者一个带有@@ ?
您的直觉很好—您不想重复自己,并且有更好的方法来构建此代码。但是,与其共享变量,不如考虑小块、松散连接的。编写能很好地完成一件事的方法,并将它们组合在一起。例如,我们可以编写一个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数据格式才能使用它。
通过Skype聊天,我认为有几件事值得关注
Init
当前,每次要使用该模块时都使用google_analytics_api
方法。这是完全没有效率的,也是现在出现这个问题的部分原因。相反,我将创建一个init
方法,它将在每次初始化对象时触发(并使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
所指的,是一个实例方法的概念。这可以作为对象的属性,但实际上允许您在方法的实例上调用一段功能。
在Alex的例子中,你有:
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
需要注意的是,如果没有模块,这是否可以工作。我想应该可以,但是我还没有测试过