snogmetrics 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +24 -0
- data/Gemfile +13 -0
- data/LICENSE +20 -0
- data/README.mdown +50 -0
- data/Rakefile +44 -0
- data/example/snoggy/.gitignore +1 -0
- data/example/snoggy/README.mdown +7 -0
- data/example/snoggy/Rakefile +10 -0
- data/example/snoggy/app/controllers/application_controller.rb +2 -0
- data/example/snoggy/app/controllers/snogs_controller.rb +9 -0
- data/example/snoggy/app/views/layouts/application.html.erb +12 -0
- data/example/snoggy/app/views/snogs/new.html.erb +11 -0
- data/example/snoggy/app/views/snogs/thank_you.html.erb +1 -0
- data/example/snoggy/config/boot.rb +110 -0
- data/example/snoggy/config/environment.rb +13 -0
- data/example/snoggy/config/environments/development.rb +6 -0
- data/example/snoggy/config/environments/production.rb +4 -0
- data/example/snoggy/config/environments/test.rb +6 -0
- data/example/snoggy/config/initializers/snogmetrics.rb +14 -0
- data/example/snoggy/config/routes.rb +4 -0
- data/example/snoggy/script/about +4 -0
- data/example/snoggy/script/console +3 -0
- data/example/snoggy/script/dbconsole +3 -0
- data/example/snoggy/script/destroy +3 -0
- data/example/snoggy/script/generate +3 -0
- data/example/snoggy/script/performance/benchmarker +3 -0
- data/example/snoggy/script/performance/profiler +3 -0
- data/example/snoggy/script/plugin +3 -0
- data/example/snoggy/script/runner +3 -0
- data/example/snoggy/script/server +3 -0
- data/example/snoggy/vendor/plugins/snogmetrics/init.rb +4 -0
- data/lib/snogmetrics.rb +164 -0
- data/rails/init.rb +4 -0
- data/spec/snogmetrics_spec.rb +132 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +15 -0
- metadata +100 -0
data/.document
ADDED
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Theo
|
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.mdown
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# SNOGmetrics
|
2
|
+
|
3
|
+
SNOGmetrics is a bridge between Rails and KISSmetrics' JavaScript API.
|
4
|
+
|
5
|
+
## But KISSmetrics has a Ruby API!
|
6
|
+
|
7
|
+
Yes, but it's not as good as the JavaScript one, they even say so themselves:
|
8
|
+
|
9
|
+
> One thing to note about the Ruby API is that it is not as full featured as the JavaScript client. Therefore, in most cases we recommend using the JavaScript client. However, some things are easier to track server-side, therefore we have provided a basic Ruby client.
|
10
|
+
|
11
|
+
It's true, but why settle for either or?
|
12
|
+
|
13
|
+
SNOGmetrics works similarly to flash messages. Events are recorded and saved to the session, and are then sent when the next page is rendered. This way you get all of the benefits of the JavaScript API, but you can record events in your controllers. All you have to do is install this gem, configure it, and add a snipplet of code to your layout.
|
14
|
+
|
15
|
+
## How do I use it?
|
16
|
+
|
17
|
+
1. `gem install snogmetrics`
|
18
|
+
2. Edit `config/environment.rb` and add `config.gem 'snogmetrics'`
|
19
|
+
3. Edit your layout(s) and add `<%= km.js! %>` where you keep your JavaScript includes.
|
20
|
+
4. Replace all your `KM.record(...)` and `KM.identify(...)` calls in JavaScript with calls to `km.record(...)` and `km.identify(...)`
|
21
|
+
|
22
|
+
Have a look at the included example application to see it in action.
|
23
|
+
|
24
|
+
## Does it use the asynchronous API?
|
25
|
+
|
26
|
+
Yes it does.
|
27
|
+
|
28
|
+
## What if I want to call KISSmetrics from both my controllers _and_ JavaScript?
|
29
|
+
|
30
|
+
Just do it. You need to make sure that the `_kmq` array exists, though. SNOGmetrics will define it where you place <%= km.js! %>, but that is usually at the bottom of the page (with the async API you could probably put it at the top if you wanted to), so if you want to add things to `_kmq` before that you need to define it yourself. Just add `var _kmq = _kmq || []` and you're set.
|
31
|
+
|
32
|
+
## Anything else I should know?
|
33
|
+
|
34
|
+
Yes, SNOGmetrics will _not_ output the KISSmetrics API code unless `RAILS_ENV` is `production`. Instead it will output code that logs all calls to the console (if `console` is defined).
|
35
|
+
|
36
|
+
In a future version this behaviour might be overrideable.
|
37
|
+
|
38
|
+
## Note on Patches/Pull Requests
|
39
|
+
|
40
|
+
* Fork the project.
|
41
|
+
* Make your feature addition or bug fix.
|
42
|
+
* Add tests for it. This is important so I don't break it in a
|
43
|
+
future version unintentionally.
|
44
|
+
* Commit, do not mess with rakefile, version, or history.
|
45
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
46
|
+
* Send me a pull request. Bonus points for topic branches.
|
47
|
+
|
48
|
+
## Copyright
|
49
|
+
|
50
|
+
Copyright (c) 2010 Theo Hultberg / Burt. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec/rake/spectask'
|
2
|
+
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
require File.expand_path('../lib/snogmetrics', __FILE__)
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = 'snogmetrics'
|
9
|
+
gem.summary = %Q{SNOGmetrics is a KISSmetrics helper for Rails}
|
10
|
+
gem.description = %Q{SNOGmetrics gives you the best of both worlds: access to KISSmetrics' JavaScript API through Ruby}
|
11
|
+
gem.email = 'theo@iconara.net'
|
12
|
+
gem.homepage = 'http://github.com/iconara/snogmetrics'
|
13
|
+
gem.authors = ['Theo']
|
14
|
+
gem.version = Snogmetrics::VERSION
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
|
20
|
+
end
|
21
|
+
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spec => :check_dependencies
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
begin
|
38
|
+
require 'yard'
|
39
|
+
YARD::Rake::YardocTask.new
|
40
|
+
rescue LoadError
|
41
|
+
task :yardoc do
|
42
|
+
abort 'YARD is not available. In order to run yardoc, you must: sudo gem install yard'
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
/log
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# SNOGmetrics example application
|
2
|
+
|
3
|
+
This is a small Rails application that uses SNOGmetrics. Look in `app/controllers/snogs_controller.rb` to see how you interact with the API from a controller, and look at `app/views/layouts/application.html.erb` to see the snipplet you need to add to your layout file.
|
4
|
+
|
5
|
+
Because it's easier for me when I code I've added SNOGmetrics as a plugin in the `vendor/plugins` directory (by way of symlinks), but in a real application you would add the gem in `config/environment.rb` (there's a out-commented line there if you want to see how it's done).
|
6
|
+
|
7
|
+
To set the KISSmetrics API key you need to add an initializer, see `config/initializers/snogmetrics.rb` for an example.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
|
+
|
4
|
+
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
|
5
|
+
|
6
|
+
require 'rake'
|
7
|
+
require 'rake/testtask'
|
8
|
+
require 'rake/rdoctask'
|
9
|
+
|
10
|
+
require 'tasks/rails'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% form_for :snog, :url => {:action => :create} do |f| -%>
|
2
|
+
<p>
|
3
|
+
<%= f.label :who, 'Who are you?' %><br/>
|
4
|
+
<%= f.text_field :who %>
|
5
|
+
</p>
|
6
|
+
<p>
|
7
|
+
<%= f.label :whom, 'Whom would you like to snog?' %><br/>
|
8
|
+
<%= f.text_field :whom %>
|
9
|
+
</p>
|
10
|
+
<p><%= f.submit 'Fullfill my wish!' %></p>
|
11
|
+
<% end -%>
|
@@ -0,0 +1 @@
|
|
1
|
+
Thank you for participating!
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# Don't change this file!
|
2
|
+
# Configure your app in config/environment.rb and config/environments/*.rb
|
3
|
+
|
4
|
+
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
5
|
+
|
6
|
+
module Rails
|
7
|
+
class << self
|
8
|
+
def boot!
|
9
|
+
unless booted?
|
10
|
+
preinitialize
|
11
|
+
pick_boot.run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def booted?
|
16
|
+
defined? Rails::Initializer
|
17
|
+
end
|
18
|
+
|
19
|
+
def pick_boot
|
20
|
+
(vendor_rails? ? VendorBoot : GemBoot).new
|
21
|
+
end
|
22
|
+
|
23
|
+
def vendor_rails?
|
24
|
+
File.exist?("#{RAILS_ROOT}/vendor/rails")
|
25
|
+
end
|
26
|
+
|
27
|
+
def preinitialize
|
28
|
+
load(preinitializer_path) if File.exist?(preinitializer_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def preinitializer_path
|
32
|
+
"#{RAILS_ROOT}/config/preinitializer.rb"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Boot
|
37
|
+
def run
|
38
|
+
load_initializer
|
39
|
+
Rails::Initializer.run(:set_load_path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class VendorBoot < Boot
|
44
|
+
def load_initializer
|
45
|
+
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
|
46
|
+
Rails::Initializer.run(:install_gem_spec_stubs)
|
47
|
+
Rails::GemDependency.add_frozen_gem_path
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class GemBoot < Boot
|
52
|
+
def load_initializer
|
53
|
+
self.class.load_rubygems
|
54
|
+
load_rails_gem
|
55
|
+
require 'initializer'
|
56
|
+
end
|
57
|
+
|
58
|
+
def load_rails_gem
|
59
|
+
if version = self.class.gem_version
|
60
|
+
gem 'rails', version
|
61
|
+
else
|
62
|
+
gem 'rails'
|
63
|
+
end
|
64
|
+
rescue Gem::LoadError => load_error
|
65
|
+
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
|
69
|
+
class << self
|
70
|
+
def rubygems_version
|
71
|
+
Gem::RubyGemsVersion rescue nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def gem_version
|
75
|
+
if defined? RAILS_GEM_VERSION
|
76
|
+
RAILS_GEM_VERSION
|
77
|
+
elsif ENV.include?('RAILS_GEM_VERSION')
|
78
|
+
ENV['RAILS_GEM_VERSION']
|
79
|
+
else
|
80
|
+
parse_gem_version(read_environment_rb)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def load_rubygems
|
85
|
+
min_version = '1.3.2'
|
86
|
+
require 'rubygems'
|
87
|
+
unless rubygems_version >= min_version
|
88
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
89
|
+
exit 1
|
90
|
+
end
|
91
|
+
|
92
|
+
rescue LoadError
|
93
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
94
|
+
exit 1
|
95
|
+
end
|
96
|
+
|
97
|
+
def parse_gem_version(text)
|
98
|
+
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
def read_environment_rb
|
103
|
+
File.read("#{RAILS_ROOT}/config/environment.rb")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# All that for this:
|
110
|
+
Rails.boot!
|
@@ -0,0 +1,13 @@
|
|
1
|
+
RAILS_GEM_VERSION = '2.3.5' unless defined? RAILS_GEM_VERSION
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'boot')
|
4
|
+
|
5
|
+
Rails::Initializer.run do |config|
|
6
|
+
# Usually you would add SNOGmetrics by adding the gem here, but in this
|
7
|
+
# example app I have put the code as a plugin, because it's more convenient
|
8
|
+
# when I code new features.
|
9
|
+
#config.gem 'snogmetrics'
|
10
|
+
|
11
|
+
config.frameworks -= [:active_record, :active_resource, :action_mailer]
|
12
|
+
config.action_controller.session = {:key => '_snoggy_session', :secret => 'd08d2ef897ba8d7477bc3088dde396ac'}
|
13
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
config.cache_classes = true
|
2
|
+
config.whiny_nils = true
|
3
|
+
config.action_controller.consider_all_requests_local = true
|
4
|
+
config.action_controller.perform_caching = false
|
5
|
+
config.action_view.cache_template_loading = true
|
6
|
+
config.action_controller.allow_forgery_protection = false
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# This is where you configure SNOGmetrics. Just override the #kissmetrics_api_key
|
2
|
+
# method of the module to return the API key.
|
3
|
+
module Snogmetrics
|
4
|
+
def kissmetrics_api_key
|
5
|
+
'abc123'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# If you need to load the API from a YAML file, you can do something like the
|
10
|
+
# following. It loads the key and puts it in a local variable, then it overrides
|
11
|
+
# the #kissmetrics_api_key method with a closure that has access to the local
|
12
|
+
# variable 'key'.
|
13
|
+
#key = YAML.load(ERB.new(File.read('path/to/file.yml')).result)[RAILS_ENV].symbolize_keys[:kissmetrics_api_key]
|
14
|
+
#Snogmetrics.send(:define_method, :kissmetrics_api_key) { key }
|
data/lib/snogmetrics.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
module Snogmetrics
|
2
|
+
VERSION = '0.1.0'
|
3
|
+
|
4
|
+
def km
|
5
|
+
@km_api ||= KissmetricsApi.new(kissmetrics_api_key, session)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Override this method to set the KISSmetrics API key
|
9
|
+
def kissmetrics_api_key
|
10
|
+
''
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
class KissmetricsApi
|
16
|
+
include ERB::Util
|
17
|
+
|
18
|
+
def initialize(api_key, session)
|
19
|
+
@session = session
|
20
|
+
@api_key = api_key
|
21
|
+
end
|
22
|
+
|
23
|
+
def record(*args)
|
24
|
+
raise 'Not enough arguments' if args.size == 0
|
25
|
+
raise 'Too many arguments' if args.size > 2
|
26
|
+
|
27
|
+
@session[:km_events] ||= []
|
28
|
+
|
29
|
+
if args.size == 1 && args.first.is_a?(Hash)
|
30
|
+
@session[:km_events] << {:properties => args.first}
|
31
|
+
elsif args.size == 1
|
32
|
+
@session[:km_events] << {:name => args.first}
|
33
|
+
else
|
34
|
+
@session[:km_events] << {:name => args.first, :properties => args.last}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def identify(identity)
|
39
|
+
unless user_identified?(identity)
|
40
|
+
@session[:km_identity] = identity
|
41
|
+
@session[:km_user_identified] = nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def js(options={})
|
46
|
+
options = {:reset => false}.merge(options)
|
47
|
+
|
48
|
+
buffer = []
|
49
|
+
|
50
|
+
unless user_identified? || @session[:km_identity].blank?
|
51
|
+
identity = html_escape(@session[:km_identity])
|
52
|
+
|
53
|
+
buffer << push_call('identify', identity)
|
54
|
+
|
55
|
+
user_identified! if options[:reset]
|
56
|
+
end
|
57
|
+
|
58
|
+
unless events.empty?
|
59
|
+
safe_events.each do |event|
|
60
|
+
if event[:name].blank?
|
61
|
+
buffer << push_call('record', event[:properties])
|
62
|
+
elsif event[:properties].blank?
|
63
|
+
buffer << push_call('record', event[:name])
|
64
|
+
else
|
65
|
+
buffer << push_call('record', event[:name], event[:properties])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
reset_events! if options[:reset]
|
70
|
+
end
|
71
|
+
|
72
|
+
if buffer.empty?
|
73
|
+
''
|
74
|
+
else
|
75
|
+
<<-JAVASCRIPT
|
76
|
+
<script type="text/javascript">
|
77
|
+
var _kmq = _kmq || [];
|
78
|
+
#{api_js}
|
79
|
+
#{buffer.join("\n")}
|
80
|
+
</script>
|
81
|
+
JAVASCRIPT
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def js!
|
86
|
+
js(:reset => true)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def user_identified?(who=nil)
|
92
|
+
if who
|
93
|
+
@session[:km_user_identified] == who
|
94
|
+
else
|
95
|
+
!!@session[:km_user_identified]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def push_call(*args)
|
100
|
+
%(_kmq.push(#{args.to_json});)
|
101
|
+
end
|
102
|
+
|
103
|
+
def api_js
|
104
|
+
if Rails.env.production?
|
105
|
+
%((function(){function _kms(u,d){if(navigator.appName.indexOf("Microsoft")==0 && d)document.write("<scr"+"ipt defer='defer' async='true' src='"+u+"'></scr"+"ipt>");else{var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(s);}}_kms('https://i.kissmetrics.com/i.js');_kms('http'+('https:'==document.location.protocol ? 's://s3.amazonaws.com/' : '://')+'scripts.kissmetrics.com/#{@api_key}.1.js',1);})();)
|
106
|
+
else
|
107
|
+
<<-JS
|
108
|
+
var KM = {
|
109
|
+
record: function() {
|
110
|
+
_kmq.push(["record"].concat(Array.prototype.slice.apply(arguments)));
|
111
|
+
},
|
112
|
+
identify: function() {
|
113
|
+
_kmq.push(["identify"].concat(Array.prototype.slice.apply(arguments)));
|
114
|
+
}
|
115
|
+
};
|
116
|
+
|
117
|
+
if (window.console) {
|
118
|
+
_kmq = (function(queue) {
|
119
|
+
function printCall() {
|
120
|
+
console.dir(arguments);
|
121
|
+
}
|
122
|
+
|
123
|
+
for (var i = 0; i < queue.length; i++) {
|
124
|
+
printCall.apply(null, queue[i]);
|
125
|
+
}
|
126
|
+
|
127
|
+
return {push: printCall};
|
128
|
+
})(_kmq);
|
129
|
+
}
|
130
|
+
JS
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def events
|
135
|
+
@session[:km_events] || []
|
136
|
+
end
|
137
|
+
|
138
|
+
def reset_events!
|
139
|
+
@session[:km_events] = []
|
140
|
+
end
|
141
|
+
|
142
|
+
def user_identified!
|
143
|
+
@session[:km_user_identified] = @session[:km_identity]
|
144
|
+
@session[:km_identity] = nil
|
145
|
+
end
|
146
|
+
|
147
|
+
def safe_properties(hash)
|
148
|
+
return {} if hash.nil? || hash.empty?
|
149
|
+
hash.keys.inject({}) do |h, k|
|
150
|
+
h[html_escape(k)] = html_escape(hash[k])
|
151
|
+
h
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def safe_events
|
156
|
+
events.map do |event|
|
157
|
+
safe_event = {}
|
158
|
+
safe_event[:name] = html_escape(event[:name].strip) unless event[:name].blank?
|
159
|
+
safe_event[:properties] = safe_properties(event[:properties]) unless event[:properties].blank?
|
160
|
+
safe_event
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
|
4
|
+
module Rails
|
5
|
+
def self.env
|
6
|
+
self
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.production?
|
10
|
+
false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
describe Snogmetrics do
|
16
|
+
|
17
|
+
before do
|
18
|
+
@session = {}
|
19
|
+
@context = Object.new
|
20
|
+
@context.extend(Snogmetrics)
|
21
|
+
@context.stub!(:session).and_return(@session)
|
22
|
+
@context.stub!(:kissmetrics_api_key).and_return('abc123')
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#record' do
|
26
|
+
it 'will output code that pushes an event with the specified name and properties' do
|
27
|
+
@context.km.record('hello world', :foo => 'bar')
|
28
|
+
@context.km.js.should include('_kmq.push(["record","hello world",{"foo":"bar"}]);')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'will output code that pushes an event with name only' do
|
32
|
+
@context.km.record('foo')
|
33
|
+
@context.km.js.should include('_kmq.push(["record","foo"]);')
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'will output code that pushes an event with properties only' do
|
37
|
+
@context.km.record({:foo => 'bar', :plink => :plonk})
|
38
|
+
@context.km.js.should match(%r#_kmq.push\(\["record",\{(?:"foo":"bar","plink":"plonk"|"plink":"plonk","foo":"bar")\}\]\)#)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'complains if called without arguments' do
|
42
|
+
running { @context.km.record }.should raise_error
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'complains if called with more than two arguments' do
|
46
|
+
running { @context.km.record(1, 2, 3) }.should raise_error
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'will output code that pushes events with the same name in the order they were recorded' do
|
50
|
+
@context.km.record('An important event', :p => 3)
|
51
|
+
@context.km.record('An important event', :p => 4)
|
52
|
+
js = @context.km.js
|
53
|
+
js.should include('_kmq.push(["record","An important event",{"p":"3"}]);')
|
54
|
+
js.should include('_kmq.push(["record","An important event",{"p":"4"}]);')
|
55
|
+
js.index('_kmq.push(["record","An important event",{"p":"3"}]);').should < js.index('_kmq.push(["record","An important event",{"p":"4"}]);')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#identify' do
|
60
|
+
it 'will output code that pushes an identify call with the provided identity' do
|
61
|
+
@context.km.identify('Phil')
|
62
|
+
@context.km.js.should include('_kmq.push(["identify","Phil"]);')
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'will only output the last identity set' do
|
66
|
+
@context.km.identify('Phil')
|
67
|
+
@context.km.identify('Anne')
|
68
|
+
@context.km.identify('Steve')
|
69
|
+
@context.km.js.should_not include('Phil')
|
70
|
+
@context.km.js.should_not include('Anne')
|
71
|
+
@context.km.js.should include('Steve')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#js' do
|
76
|
+
it 'outputs nothing if there are no events and no identity' do
|
77
|
+
@context.km.js.should be_empty
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'in production' do
|
81
|
+
before do
|
82
|
+
Rails.stub!(:env).and_return(mock('env', :production? => true))
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'outputs a JavaScript tag that loads the KISSmetrics API' do
|
86
|
+
@context.km.identify('Phil')
|
87
|
+
@context.km.js.should include('scripts.kissmetrics.com/abc123.1.js')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'outputs code that conditionally sets the _kmq variable' do
|
92
|
+
@context.km.identify('Phil')
|
93
|
+
@context.km.js.should include('var _kmq = _kmq || [];')
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'outputs code that pushes an event for every #record call' do
|
97
|
+
@context.km.record('1')
|
98
|
+
@context.km.record('2')
|
99
|
+
@context.km.record('3')
|
100
|
+
@context.km.js.scan(/_kmq.push\(\["record","\d"\]\)/).size.should == 3
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'resets the session when passed :reset => true' do
|
104
|
+
@context.km.record('hello world')
|
105
|
+
@context.km.js(:reset => true)
|
106
|
+
@context.km.js.should be_empty
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#js!' do
|
111
|
+
it 'works like #js(:reset => true)' do
|
112
|
+
@context.km.record('hello world')
|
113
|
+
@context.km.js!
|
114
|
+
@context.km.js.should be_empty
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'does not push an identify call if the identity has already been sent once' do
|
118
|
+
@context.km.identify('Steve')
|
119
|
+
@context.km.js!
|
120
|
+
@context.km.identify('Steve')
|
121
|
+
@context.km.js!.should_not include('_kmq.push(["identify"')
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'ouputs code that pushes an identify call if #identify is called with a new identity' do
|
125
|
+
@context.km.identify('Steve')
|
126
|
+
@context.km.js!
|
127
|
+
@context.km.identify('Anne')
|
128
|
+
@context.km.js!.should include('_kmq.push(["identify","Anne"])')
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
|
4
|
+
require 'snogmetrics'
|
5
|
+
require 'active_support'
|
6
|
+
require 'action_view/erb/util'
|
7
|
+
require 'spec'
|
8
|
+
require 'spec/autorun'
|
9
|
+
|
10
|
+
|
11
|
+
alias :running :lambda
|
12
|
+
|
13
|
+
Spec::Runner.configure do |config|
|
14
|
+
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: snogmetrics
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Theo
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-30 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: "SNOGmetrics gives you the best of both worlds: access to KISSmetrics' JavaScript API through Ruby"
|
22
|
+
email: theo@iconara.net
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- LICENSE
|
29
|
+
- README.mdown
|
30
|
+
files:
|
31
|
+
- .document
|
32
|
+
- .gitignore
|
33
|
+
- Gemfile
|
34
|
+
- LICENSE
|
35
|
+
- README.mdown
|
36
|
+
- Rakefile
|
37
|
+
- example/snoggy/.gitignore
|
38
|
+
- example/snoggy/README.mdown
|
39
|
+
- example/snoggy/Rakefile
|
40
|
+
- example/snoggy/app/controllers/application_controller.rb
|
41
|
+
- example/snoggy/app/controllers/snogs_controller.rb
|
42
|
+
- example/snoggy/app/views/layouts/application.html.erb
|
43
|
+
- example/snoggy/app/views/snogs/new.html.erb
|
44
|
+
- example/snoggy/app/views/snogs/thank_you.html.erb
|
45
|
+
- example/snoggy/config/boot.rb
|
46
|
+
- example/snoggy/config/environment.rb
|
47
|
+
- example/snoggy/config/environments/development.rb
|
48
|
+
- example/snoggy/config/environments/production.rb
|
49
|
+
- example/snoggy/config/environments/test.rb
|
50
|
+
- example/snoggy/config/initializers/snogmetrics.rb
|
51
|
+
- example/snoggy/config/routes.rb
|
52
|
+
- example/snoggy/script/about
|
53
|
+
- example/snoggy/script/console
|
54
|
+
- example/snoggy/script/dbconsole
|
55
|
+
- example/snoggy/script/destroy
|
56
|
+
- example/snoggy/script/generate
|
57
|
+
- example/snoggy/script/performance/benchmarker
|
58
|
+
- example/snoggy/script/performance/profiler
|
59
|
+
- example/snoggy/script/plugin
|
60
|
+
- example/snoggy/script/runner
|
61
|
+
- example/snoggy/script/server
|
62
|
+
- example/snoggy/vendor/plugins/snogmetrics/init.rb
|
63
|
+
- lib/snogmetrics.rb
|
64
|
+
- rails/init.rb
|
65
|
+
- spec/snogmetrics_spec.rb
|
66
|
+
- spec/spec.opts
|
67
|
+
- spec/spec_helper.rb
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: http://github.com/iconara/snogmetrics
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options:
|
74
|
+
- --charset=UTF-8
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
requirements: []
|
92
|
+
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 1.3.6
|
95
|
+
signing_key:
|
96
|
+
specification_version: 3
|
97
|
+
summary: SNOGmetrics is a KISSmetrics helper for Rails
|
98
|
+
test_files:
|
99
|
+
- spec/snogmetrics_spec.rb
|
100
|
+
- spec/spec_helper.rb
|