gxapi_rails 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +161 -0
- data/Rakefile +25 -0
- data/app/helpers/gxapi_helper.rb +108 -0
- data/lib/gxapi.rb +160 -0
- data/lib/gxapi/base.rb +100 -0
- data/lib/gxapi/controller_methods.rb +41 -0
- data/lib/gxapi/engine.rb +14 -0
- data/lib/gxapi/google_analytics.rb +193 -0
- data/lib/gxapi/ostruct.rb +86 -0
- data/lib/gxapi/version.rb +3 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/posts_controller.rb +11 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/posts_helper.rb +2 -0
- data/spec/dummy/app/models/post.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/posts/_form.html.erb +25 -0
- data/spec/dummy/app/views/posts/edit.html.erb +6 -0
- data/spec/dummy/app/views/posts/index.html.erb +36 -0
- data/spec/dummy/app/views/posts/new.html.erb +5 -0
- data/spec/dummy/app/views/posts/show.html.erb +15 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +70 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +22 -0
- data/spec/dummy/config/database.yml.default +111 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +38 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/gxapi.yml +17 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/konfig/application.rb +16 -0
- data/spec/dummy/config/konfig/development.rb +10 -0
- data/spec/dummy/config/konfig/production.rb +3 -0
- data/spec/dummy/config/konfig/test.rb +3 -0
- data/spec/dummy/config/konfig/test_prod.rb +3 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/test.p12 +0 -0
- data/spec/dummy/data/log/dummy/development.log +113 -0
- data/spec/dummy/data/log/dummy/test.log +927 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +1443 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/features/display_variant_js_spec.rb +34 -0
- data/spec/helpers/gxapi_helper_spec.rb +63 -0
- data/spec/lib/gxapi/base_spec.rb +80 -0
- data/spec/lib/gxapi/google_analytics_spec.rb +70 -0
- data/spec/lib/gxapi_spec.rb +32 -0
- data/spec/spec_helper.rb +32 -0
- metadata +233 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1fc14fc4272595a73becebfd7d22821d6c0f90af
|
4
|
+
data.tar.gz: cb8ec33f3f319d597e91666bf3a14301374d07d3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1d787804b60b6a832378ba4ad5cfeccdda4126a49cac129c26986abb98a6fcad44fe46d2c98ae22a47be8e9f6c118cb4e5bf26625df99a50fad9612ec35e34a1
|
7
|
+
data.tar.gz: 061edc4dadaf492b59137b5660df80aaa828a75db68c4f633a7a8c74a72c1168f4847b5355718842b352ea556081fc9fb5b0d93165b14c738f368988ae32e929
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Dan Langevin
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# Gxapi
|
2
|
+
|
3
|
+
[![Code Climate](https://codeclimate.com/repos/5276603656b10215e9014c80/badges/ddae4ab98746f66abf45/gpa.png)](https://codeclimate.com/repos/5276603656b10215e9014c80/feed) [![Build Status](https://travis-ci.org/dlangevin/gxapi_rails.png?branch=master)](https://travis-ci.org/dlangevin/gxapi_rails)
|
4
|
+
|
5
|
+
Gxapi interfaces with Google Analytics Experiments to retrieve data from
|
6
|
+
its API and determine which variant should be presented to a given user
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
% gem install gxapi_rails
|
10
|
+
% rails g gxapi_rails
|
11
|
+
|
12
|
+
## Configuration
|
13
|
+
|
14
|
+
First, you must create a Google Analytics Service Account.
|
15
|
+
Information can be found here https://developers.google.com/accounts/docs/OAuth2ServiceAccount
|
16
|
+
|
17
|
+
Gxapi uses `#{Rails.root}/config/gxapi.yml` to configure variables. You can
|
18
|
+
use different configurations per environment (development/test/production)
|
19
|
+
|
20
|
+
### Example Configuration
|
21
|
+
development:
|
22
|
+
google_analytics:
|
23
|
+
account_id: ACCOUNT_ID
|
24
|
+
profile_id: PROFILE_ID
|
25
|
+
web_property_id: WEB_PROPERTY_ID
|
26
|
+
google:
|
27
|
+
email: SERVICE_ACCOUNT_EMAIL
|
28
|
+
private_key_path: 'PATH_TO_SERVICE_ACCOUNT_PRIVATE_KEY'
|
29
|
+
|
30
|
+
### Where the F do I find all this stuff?
|
31
|
+
|
32
|
+
<a href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount"
|
33
|
+
target="_blank">Some instructions</a>
|
34
|
+
on creating a Google Analytics Service Account
|
35
|
+
|
36
|
+
<a href="https://developers.google.com/analytics/resources/concepts/gaConceptsAccounts"
|
37
|
+
target="_blank">Some instructions</a> on where to find your
|
38
|
+
Google Analytics settings
|
39
|
+
|
40
|
+
|
41
|
+
## Usage
|
42
|
+
|
43
|
+
### Layout
|
44
|
+
|
45
|
+
First, add the experiment Javascript in your layout
|
46
|
+
|
47
|
+
# app/views/layouts/application.html.erb
|
48
|
+
<%= gxapi_experiment_js %>
|
49
|
+
|
50
|
+
This will render the Javascript tag to pull in the Google Analytics
|
51
|
+
Content Experiment JS source and the corresponding call to send your
|
52
|
+
experiment data in. If you are specifying a custom variable name
|
53
|
+
(the default is 'variant'), you can add it here as well
|
54
|
+
|
55
|
+
# app/views/layouts/application.html.erb
|
56
|
+
<%= gxapi_experiment_js(:custom_var) %>
|
57
|
+
|
58
|
+
If you have multiple experiments on the same page, you can add this same
|
59
|
+
call for each experiment in a view
|
60
|
+
|
61
|
+
# app/views/layouts/application.html.erb
|
62
|
+
<%= gxapi_experiment_js %>
|
63
|
+
|
64
|
+
# app/views/posts/index.html.erb
|
65
|
+
<%= gxapi_experiment_js(:other_experiment_key) %>
|
66
|
+
|
67
|
+
### Controller
|
68
|
+
|
69
|
+
Once you have set up an experiment in Google Analytics, you can reference
|
70
|
+
it by name in your controller
|
71
|
+
|
72
|
+
class PostsController < ApplicationController
|
73
|
+
|
74
|
+
def index
|
75
|
+
gxapi_get_variant("My Experiment")
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
This will use the default key `variant` for the experiment. To customize
|
81
|
+
this name, you can pass another value. This is useful when you are using
|
82
|
+
multiple experiments on the same page
|
83
|
+
|
84
|
+
class PostsController < ApplicationController
|
85
|
+
|
86
|
+
def index
|
87
|
+
gxapi_get_variant("My Experiment", :exp1)
|
88
|
+
gxapi_get_variant("Other Experiment", :exp2)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
### Control Flow
|
94
|
+
|
95
|
+
In the controller and the view, you can access the variant name to determine
|
96
|
+
which path your code should take. `gxapi_get_variant` returns a
|
97
|
+
`Celluloid::Future` to prevent blocking while the result is calculated. To
|
98
|
+
get the value in the controller you can call `#value`. In the view,
|
99
|
+
Gxapi provides a the `gxapi_variant_name` helper.
|
100
|
+
|
101
|
+
class PostsController < ApplicationController
|
102
|
+
|
103
|
+
def index
|
104
|
+
gxapi_get_variant("My Experiment", :exp1)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
# app/views/posts/index.html.erb
|
110
|
+
|
111
|
+
<h1>My Page</h1>
|
112
|
+
|
113
|
+
<% if gxapi_variant_name(:exp1) == 'version_a' -%>
|
114
|
+
Do some stuff...
|
115
|
+
<% else -%>
|
116
|
+
Do some other stuff...
|
117
|
+
<% end -%>
|
118
|
+
|
119
|
+
### Testing and overriding
|
120
|
+
|
121
|
+
In order to view a specific version, you can pass `experiment_name=value`
|
122
|
+
into a GET request to the action. This will short-circuit the rendering
|
123
|
+
of the JavaScript call to Google so testing will not affect your results
|
124
|
+
|
125
|
+
# GET /posts.html?variant=my_var
|
126
|
+
|
127
|
+
# app/controllers/posts_controller.rb
|
128
|
+
def index
|
129
|
+
gxapi_get_variant("My Experiment")
|
130
|
+
end
|
131
|
+
|
132
|
+
# app/views/posts/index.html.erb
|
133
|
+
gxapi_variant_name # Will always equal 'my_var'
|
134
|
+
|
135
|
+
|
136
|
+
# GET /posts.html?custom_name=my_var
|
137
|
+
|
138
|
+
# app/controllers/posts_controller.rb
|
139
|
+
def index
|
140
|
+
gxapi_get_variant("My Experiment", :custom_name)
|
141
|
+
end
|
142
|
+
|
143
|
+
# app/views/posts/index.html.erb
|
144
|
+
gxapi_variant_name(:custom_name) # Will always equal 'my_var'
|
145
|
+
|
146
|
+
|
147
|
+
## Contributing to gxapi
|
148
|
+
|
149
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
150
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
151
|
+
* Fork the project.
|
152
|
+
* Start a feature/bugfix branch.
|
153
|
+
* Commit and push until you are happy with your contribution.
|
154
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
155
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
156
|
+
|
157
|
+
## Copyright
|
158
|
+
|
159
|
+
Copyright (c) 2013 Dan Langevin. See LICENSE.txt for
|
160
|
+
further details.
|
161
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'rspec/core'
|
15
|
+
require 'rspec/core/rake_task'
|
16
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
17
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
21
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
22
|
+
spec.rcov = true
|
23
|
+
end
|
24
|
+
|
25
|
+
task :default => :spec
|
@@ -0,0 +1,108 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# View helper for Gxapi.
|
4
|
+
#
|
5
|
+
# @author [dlangevin]
|
6
|
+
#
|
7
|
+
module GxapiHelper
|
8
|
+
|
9
|
+
#
|
10
|
+
# Get the HTMl to load script from Google Ananlytics
|
11
|
+
# and setChosenVariation to tell it which one we served
|
12
|
+
#
|
13
|
+
# @return [String] HTML
|
14
|
+
def gxapi_experiment_js(*args)
|
15
|
+
# extract options
|
16
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
17
|
+
# default
|
18
|
+
ivar_name = args.first || :variant
|
19
|
+
|
20
|
+
unless variant = self.get_variant(ivar_name)
|
21
|
+
return ""
|
22
|
+
end
|
23
|
+
|
24
|
+
# our return value
|
25
|
+
ret = ""
|
26
|
+
# first time we call this, we add the script
|
27
|
+
unless @gxapi_experiment_called == true
|
28
|
+
ret += self.gxapi_source(opts)
|
29
|
+
Gxapi.logger.debug {"Rendered Gxapi source"}
|
30
|
+
end
|
31
|
+
|
32
|
+
@gxapi_experiment_called = true
|
33
|
+
ret += self.get_variant_js(variant)
|
34
|
+
|
35
|
+
Gxapi.logger.debug { "#{ivar_name} is now #{variant.value.name}" }
|
36
|
+
|
37
|
+
ret.html_safe
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Get the version for a given variant
|
42
|
+
# @return [String]
|
43
|
+
def gxapi_variant_name(ivar_name = :variant)
|
44
|
+
# if we have params[ivar], we just use it
|
45
|
+
return "default" unless variant = instance_variable_get("@#{ivar_name}")
|
46
|
+
return variant.value.try(:name) || "default"
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
#
|
52
|
+
# Get the variant if it exists and has an experiment_id
|
53
|
+
#
|
54
|
+
# @param ivar_name [String] Name of the instance variable for the
|
55
|
+
# variant
|
56
|
+
#
|
57
|
+
# @return [Gxapi::Ostruct, false] Variant if it exists, false otherwise
|
58
|
+
def get_variant(ivar_name)
|
59
|
+
# make sure we have our variant
|
60
|
+
unless variant = instance_variable_get("@#{ivar_name}")
|
61
|
+
Gxapi.logger.debug { "No variant found - #{ivar_name}" }
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
# and a valid experiment id
|
65
|
+
unless variant.value.experiment_id.present?
|
66
|
+
Gxapi.logger.debug { "No experiment_id found : #{variant.value} "}
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
return variant
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Get the JS for a variant
|
74
|
+
#
|
75
|
+
# @param variant [Ostruct] Variant definition
|
76
|
+
#
|
77
|
+
# @return [String] JS to render
|
78
|
+
def get_variant_js(variant)
|
79
|
+
javascript_tag{
|
80
|
+
"cxApi.setChosenVariation(
|
81
|
+
#{variant.value.index},
|
82
|
+
'#{escape_javascript(variant.value.experiment_id)}'
|
83
|
+
);".html_safe
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# The Javascript tag for the Content experiment API
|
89
|
+
#
|
90
|
+
# @param [Hash] opts Hash of options
|
91
|
+
#
|
92
|
+
# @return [String] HTML for the tag
|
93
|
+
def gxapi_source(opts)
|
94
|
+
ret = javascript_include_tag(
|
95
|
+
"https://www.google-analytics.com/cx/api.js"
|
96
|
+
)
|
97
|
+
ret += "\n"
|
98
|
+
# set domain name if present
|
99
|
+
if opts[:domain]
|
100
|
+
domain_call = javascript_tag{
|
101
|
+
"cxApi.setDomainName('#{escape_javascript(opts[:domain])}');".html_safe
|
102
|
+
}
|
103
|
+
ret += domain_call.html_safe
|
104
|
+
ret += "\n"
|
105
|
+
end
|
106
|
+
ret
|
107
|
+
end
|
108
|
+
end
|
data/lib/gxapi.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'celluloid'
|
3
|
+
require 'erb'
|
4
|
+
require 'json'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
require File.expand_path('../gxapi/base', __FILE__)
|
8
|
+
require File.expand_path('../gxapi/google_analytics', __FILE__)
|
9
|
+
require File.expand_path('../gxapi/ostruct', __FILE__)
|
10
|
+
require File.expand_path('../gxapi/version', __FILE__)
|
11
|
+
|
12
|
+
|
13
|
+
if defined?(::Rails)
|
14
|
+
require File.expand_path('../gxapi/controller_methods', __FILE__)
|
15
|
+
require File.expand_path('../gxapi/engine', __FILE__)
|
16
|
+
end
|
17
|
+
|
18
|
+
module Gxapi
|
19
|
+
|
20
|
+
#
|
21
|
+
# get our cache instance
|
22
|
+
#
|
23
|
+
# @return [ActiveSupport::Cache::Store]
|
24
|
+
def self.cache
|
25
|
+
# if we have an overridden cache, return it
|
26
|
+
return @overridden_cache if defined?(@overridden_cache)
|
27
|
+
# use Rails.cache if it is defined
|
28
|
+
return ::Rails.cache if defined?(::Rails) && ::Rails.cache
|
29
|
+
# last resort, just use our own cache choice
|
30
|
+
@cache ||= ActiveSupport::Cache::MemoryStore.new
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# setter for {Gxapi.cache}
|
35
|
+
#
|
36
|
+
# @return [ActiveSupport::Cache::Store] The new cache object
|
37
|
+
def self.cache=(cache)
|
38
|
+
@overridden_cache = cache
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# namespace for our cache keys
|
43
|
+
#
|
44
|
+
# @return [String, nil]
|
45
|
+
def self.cache_namespace
|
46
|
+
@cache_namespace
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# setter for {Gxapi.cache_namespace}
|
51
|
+
#
|
52
|
+
# @return [String] New value for cache_namespace
|
53
|
+
def self.cache_namespace=(val)
|
54
|
+
@cache_namespace = val
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Gxapi config - this is loaded based on the
|
59
|
+
# {Gxapi.config_path}
|
60
|
+
#
|
61
|
+
# @return [Gxapi::Ostruct]
|
62
|
+
def self.config
|
63
|
+
@config ||= begin
|
64
|
+
# parse our yml file after running it through ERB
|
65
|
+
contents = File.read(self.config_path)
|
66
|
+
yml = ERB.new(contents).result(binding)
|
67
|
+
Gxapi::Ostruct.new(YAML.load(yml)[Gxapi.env])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# get the config path for our config YAML file
|
73
|
+
#
|
74
|
+
# @return [String] defaults to #{Rails.root}/config/gxapi.yml
|
75
|
+
def self.config_path
|
76
|
+
@config_path ||= File.join(Rails.root, "config/gxapi.yml")
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# setter for config path
|
81
|
+
#
|
82
|
+
# @return [String] value of {Gxapi.config_path}
|
83
|
+
def self.config_path=(val)
|
84
|
+
@config_path = val
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# our environment - defaults to Rails.env or test
|
89
|
+
#
|
90
|
+
# @return [String]
|
91
|
+
def self.env
|
92
|
+
@env ||= defined?(::Rails) ? ::Rails.env : "test"
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# Set the value of {Gxapi.env}
|
97
|
+
#
|
98
|
+
# @return [String] environment
|
99
|
+
def self.env=(val)
|
100
|
+
@env = val
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# instance of logger for Gxapi
|
105
|
+
#
|
106
|
+
# @return [Logger, Log4r::Logger]
|
107
|
+
def self.logger
|
108
|
+
@logger ||= begin
|
109
|
+
if defined?(::Rails) && ::Rails.logger
|
110
|
+
::Rails.logger
|
111
|
+
else
|
112
|
+
Logger.new(STDOUT)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
#
|
119
|
+
# Setter for the Logger
|
120
|
+
# @param logger [Logger, Log4r]
|
121
|
+
#
|
122
|
+
# @return [Logger, Log4r] Logger instance
|
123
|
+
def self.logger=(logger)
|
124
|
+
@logger = logger
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# Reload all data from experiments
|
129
|
+
#
|
130
|
+
# @return [Boolean] Always true
|
131
|
+
def self.reload_experiments
|
132
|
+
Base.new("").reload_experiments
|
133
|
+
true
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
#
|
138
|
+
# root directory for gxapi
|
139
|
+
#
|
140
|
+
# @return [String]
|
141
|
+
def self.root
|
142
|
+
File.expand_path("../../", __FILE__)
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# Wrap with error handling
|
147
|
+
# logs errors and returns false if an error
|
148
|
+
# occurs
|
149
|
+
#
|
150
|
+
# @return [Value, false]
|
151
|
+
def self.with_error_handling(&block)
|
152
|
+
begin
|
153
|
+
yield
|
154
|
+
rescue => e
|
155
|
+
self.logger.error(e.message)
|
156
|
+
self.logger.error(e.backtrace)
|
157
|
+
false
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|