我希望了解如何在方法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 ,这些可以改为什么?一个带@的实例变量?或带有@@?
的类变量答案 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
对此的一个警告是,这是否可以在没有模块的情况下工作。我认为它应该,但它对我来说没有经过考验