shrew 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +67 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +114 -0
- data/README.md +38 -0
- data/Rakefile +15 -0
- data/app/assets/javascripts/shrew.js +69 -0
- data/app/controllers/shrew/application_controller.rb +4 -0
- data/app/controllers/shrew/page_views_controller.rb +22 -0
- data/app/models/shrew/page_view.rb +19 -0
- data/app/views/shrew/_automatically_track_page_views.html.erb +11 -0
- data/config/routes.rb +9 -0
- data/db/migrate/1_add_shrew_page_view_table.rb +17 -0
- data/lib/generators/shrew/install_generator.rb +31 -0
- data/lib/generators/templates/page_view_migration.rb +17 -0
- data/lib/generators/templates/shrew.rb +4 -0
- data/lib/shrew/engine.rb +14 -0
- data/lib/shrew/tracks_page_views.rb +21 -0
- data/lib/shrew/version.rb +3 -0
- data/shrew.gemspec +26 -0
- data/spec/controllers/page_views_controller_spec.rb +56 -0
- data/spec/controllers/tracks_page_views_spec.rb +34 -0
- data/spec/rails_helper.rb +50 -0
- data/spec/shrew_spec.rb +6 -0
- data/spec/spec_helper.rb +52 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +82 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/assets.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +30 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/log/development.log +81 -0
- data/test/dummy/log/test.log +1689 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/test_helper.rb +15 -0
- metadata +77 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 08a92b898b271df0893a9cae07e5da9a9339438f
|
4
|
+
data.tar.gz: b2cb9fafe62a8abd0820a0f67448f6cadfa98914
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 66dbce425c0109ec66c1a709ae0fe394b42d459cc64cea9a2636a5d7e2fd7da4e85a1fa5b4d7ed558aafcb2b7f56f70178acdc46c91a4657526261984b6823e2
|
7
|
+
data.tar.gz: 3856eaf445d5c010d64eaf7f0f171f86daf13acfce1666c1e008a3a63fe5514d6e003b671f36be5d7f07ce33eeab2702abf25ab08c28633e781056f66faea7e6
|
data/.gitignore
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore the default SQLite database.
|
11
|
+
/db/*.sqlite3
|
12
|
+
/db/*.sqlite3-journal
|
13
|
+
|
14
|
+
# Ignore all logfiles and tempfiles.
|
15
|
+
/log/*.log
|
16
|
+
/tmp
|
17
|
+
|
18
|
+
#https://github.com/github/gitignore/blob/master/Rails.gitignore
|
19
|
+
*.rbc
|
20
|
+
capybara-*.html
|
21
|
+
.rspec
|
22
|
+
/log
|
23
|
+
/tmp
|
24
|
+
/db/*.sqlite3
|
25
|
+
/public/system
|
26
|
+
/public/uploads
|
27
|
+
/coverage/
|
28
|
+
/spec/tmp
|
29
|
+
**.orig
|
30
|
+
rerun.txt
|
31
|
+
pickle-email-*.html
|
32
|
+
|
33
|
+
# Comment out this rules if you are OK with secrets been uploaded to the repo
|
34
|
+
config/initializers/secret_token.rb
|
35
|
+
#config/secrets.yml
|
36
|
+
|
37
|
+
## Environment normalisation:
|
38
|
+
/.bundle
|
39
|
+
/vendor/bundle
|
40
|
+
|
41
|
+
# these should all be checked in to normalise the environment:
|
42
|
+
# Gemfile.lock, .ruby-version, .ruby-gemset
|
43
|
+
|
44
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
45
|
+
.rvmrc
|
46
|
+
|
47
|
+
#ignore idea
|
48
|
+
/.idea
|
49
|
+
|
50
|
+
#mac
|
51
|
+
.DS_Store
|
52
|
+
|
53
|
+
#precompiled assets
|
54
|
+
public/assets/
|
55
|
+
|
56
|
+
solr/**/data
|
57
|
+
solr/pids/
|
58
|
+
|
59
|
+
#uploaded files
|
60
|
+
public/file/
|
61
|
+
|
62
|
+
|
63
|
+
#javascript code coverage
|
64
|
+
spec/javascripts_coverage/
|
65
|
+
|
66
|
+
#node modules
|
67
|
+
node_modules
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
shrew (0.0.2)
|
5
|
+
activerecord (>= 4.0.0)
|
6
|
+
activesupport (>= 4.0.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionmailer (4.1.7)
|
12
|
+
actionpack (= 4.1.7)
|
13
|
+
actionview (= 4.1.7)
|
14
|
+
mail (~> 2.5, >= 2.5.4)
|
15
|
+
actionpack (4.1.7)
|
16
|
+
actionview (= 4.1.7)
|
17
|
+
activesupport (= 4.1.7)
|
18
|
+
rack (~> 1.5.2)
|
19
|
+
rack-test (~> 0.6.2)
|
20
|
+
actionview (4.1.7)
|
21
|
+
activesupport (= 4.1.7)
|
22
|
+
builder (~> 3.1)
|
23
|
+
erubis (~> 2.7.0)
|
24
|
+
activemodel (4.1.7)
|
25
|
+
activesupport (= 4.1.7)
|
26
|
+
builder (~> 3.1)
|
27
|
+
activerecord (4.1.7)
|
28
|
+
activemodel (= 4.1.7)
|
29
|
+
activesupport (= 4.1.7)
|
30
|
+
arel (~> 5.0.0)
|
31
|
+
activesupport (4.1.7)
|
32
|
+
i18n (~> 0.6, >= 0.6.9)
|
33
|
+
json (~> 1.7, >= 1.7.7)
|
34
|
+
minitest (~> 5.1)
|
35
|
+
thread_safe (~> 0.1)
|
36
|
+
tzinfo (~> 1.1)
|
37
|
+
arel (5.0.1.20140414130214)
|
38
|
+
builder (3.2.2)
|
39
|
+
database_cleaner (1.3.0)
|
40
|
+
diff-lcs (1.2.5)
|
41
|
+
erubis (2.7.0)
|
42
|
+
hike (1.2.3)
|
43
|
+
i18n (0.6.11)
|
44
|
+
json (1.8.1)
|
45
|
+
mail (2.6.3)
|
46
|
+
mime-types (>= 1.16, < 3)
|
47
|
+
mime-types (2.4.3)
|
48
|
+
minitest (5.4.2)
|
49
|
+
multi_json (1.10.1)
|
50
|
+
rack (1.5.2)
|
51
|
+
rack-test (0.6.2)
|
52
|
+
rack (>= 1.0)
|
53
|
+
rails (4.1.7)
|
54
|
+
actionmailer (= 4.1.7)
|
55
|
+
actionpack (= 4.1.7)
|
56
|
+
actionview (= 4.1.7)
|
57
|
+
activemodel (= 4.1.7)
|
58
|
+
activerecord (= 4.1.7)
|
59
|
+
activesupport (= 4.1.7)
|
60
|
+
bundler (>= 1.3.0, < 2.0)
|
61
|
+
railties (= 4.1.7)
|
62
|
+
sprockets-rails (~> 2.0)
|
63
|
+
railties (4.1.7)
|
64
|
+
actionpack (= 4.1.7)
|
65
|
+
activesupport (= 4.1.7)
|
66
|
+
rake (>= 0.8.7)
|
67
|
+
thor (>= 0.18.1, < 2.0)
|
68
|
+
rake (10.3.2)
|
69
|
+
rspec (3.1.0)
|
70
|
+
rspec-core (~> 3.1.0)
|
71
|
+
rspec-expectations (~> 3.1.0)
|
72
|
+
rspec-mocks (~> 3.1.0)
|
73
|
+
rspec-core (3.1.7)
|
74
|
+
rspec-support (~> 3.1.0)
|
75
|
+
rspec-expectations (3.1.2)
|
76
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
77
|
+
rspec-support (~> 3.1.0)
|
78
|
+
rspec-mocks (3.1.3)
|
79
|
+
rspec-support (~> 3.1.0)
|
80
|
+
rspec-rails (3.1.0)
|
81
|
+
actionpack (>= 3.0)
|
82
|
+
activesupport (>= 3.0)
|
83
|
+
railties (>= 3.0)
|
84
|
+
rspec-core (~> 3.1.0)
|
85
|
+
rspec-expectations (~> 3.1.0)
|
86
|
+
rspec-mocks (~> 3.1.0)
|
87
|
+
rspec-support (~> 3.1.0)
|
88
|
+
rspec-support (3.1.2)
|
89
|
+
sprockets (2.12.3)
|
90
|
+
hike (~> 1.2)
|
91
|
+
multi_json (~> 1.0)
|
92
|
+
rack (~> 1.0)
|
93
|
+
tilt (~> 1.1, != 1.3.0)
|
94
|
+
sprockets-rails (2.2.0)
|
95
|
+
actionpack (>= 3.0)
|
96
|
+
activesupport (>= 3.0)
|
97
|
+
sprockets (>= 2.8, < 4.0)
|
98
|
+
sqlite3 (1.3.10)
|
99
|
+
thor (0.19.1)
|
100
|
+
thread_safe (0.3.4)
|
101
|
+
tilt (1.4.1)
|
102
|
+
tzinfo (1.2.2)
|
103
|
+
thread_safe (~> 0.1)
|
104
|
+
|
105
|
+
PLATFORMS
|
106
|
+
ruby
|
107
|
+
|
108
|
+
DEPENDENCIES
|
109
|
+
database_cleaner
|
110
|
+
rails (~> 4.1)
|
111
|
+
rspec (~> 3.1.0)
|
112
|
+
rspec-rails (~> 3.1.0)
|
113
|
+
shrew!
|
114
|
+
sqlite3
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Shrew
|
2
|
+
|
3
|
+
|
4
|
+
Simple analytics engine for rails
|
5
|
+
|
6
|
+
### Installation
|
7
|
+
|
8
|
+
Run the generator to install the migration and routes.
|
9
|
+
|
10
|
+
```
|
11
|
+
rails g analytics:install
|
12
|
+
rake db:migrate
|
13
|
+
```
|
14
|
+
|
15
|
+
Add page tracking to your application controller (or any other controller)
|
16
|
+
|
17
|
+
```
|
18
|
+
class ApplicationController < ActionController::Base
|
19
|
+
include Analytics::TracksPageViews
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
*For tracking javascript run time*
|
24
|
+
|
25
|
+
Include analytics.js in your application.js
|
26
|
+
|
27
|
+
```
|
28
|
+
//= require analytics
|
29
|
+
```
|
30
|
+
|
31
|
+
Include the partial at the end of your layout to automatically track javascript run time
|
32
|
+
|
33
|
+
```
|
34
|
+
...
|
35
|
+
<%= render "analytics/automatically_track_page_views" %>
|
36
|
+
</body>
|
37
|
+
</html>
|
38
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
desc 'Default: run specs'
|
5
|
+
task default: :spec
|
6
|
+
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
RSpec::Core::RakeTask.new do |t|
|
9
|
+
t.pattern = 'spec/**/*_spec.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
Bundler::GemHelper.install_tasks
|
13
|
+
|
14
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
15
|
+
load 'rails/tasks/engine.rake'
|
@@ -0,0 +1,69 @@
|
|
1
|
+
/* jshint: asi:false */
|
2
|
+
(function(config) {
|
3
|
+
var _validConfig = function(){
|
4
|
+
if(typeof config.pageViewUrl !== 'string'){
|
5
|
+
return false
|
6
|
+
}
|
7
|
+
if(typeof config.jTI !== 'string'){
|
8
|
+
return false
|
9
|
+
}
|
10
|
+
return true
|
11
|
+
}
|
12
|
+
|
13
|
+
/* http://stackoverflow.com/questions/8790099/detect-if-any-javascript-function-is-running */
|
14
|
+
var automaticallyTrackPageView = function() {
|
15
|
+
if (window.addEventListener) {
|
16
|
+
window.addEventListener("load", loadHandler, false)
|
17
|
+
}
|
18
|
+
else if (window.attachEvent) {
|
19
|
+
window.attachEvent("onload", loadHandler)
|
20
|
+
}
|
21
|
+
else {
|
22
|
+
window.onload = loadHandler
|
23
|
+
}
|
24
|
+
|
25
|
+
function loadHandler() {
|
26
|
+
setTimeout(trackPageView, 0)
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
var trackPageView = function() {
|
31
|
+
if(!_validConfig()){
|
32
|
+
if(typeof console !== 'undefined' && typeof console.error !== 'undefined'){
|
33
|
+
console.error('invalid shrew configuration')
|
34
|
+
}
|
35
|
+
return false
|
36
|
+
}
|
37
|
+
var xmlhttp = new XMLHttpRequest()
|
38
|
+
var params = 'url=' + encodeURIComponent(window.location.href) +
|
39
|
+
'&title=' + encodeURIComponent(document.title) +
|
40
|
+
'&jTI=' + encodeURIComponent(config.jTI) +
|
41
|
+
'&jRT=' + encodeURIComponent(new Date().getTime())
|
42
|
+
params.replace(/%20/g, '+')
|
43
|
+
xmlhttp.open('POST', config.pageViewUrl, true)
|
44
|
+
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
|
45
|
+
xmlhttp.send(params)
|
46
|
+
}
|
47
|
+
|
48
|
+
var setJTI = function(jTI){
|
49
|
+
config.jTI = jTI
|
50
|
+
}
|
51
|
+
|
52
|
+
var publicAccess = {
|
53
|
+
automaticallyTrackPageView: automaticallyTrackPageView,
|
54
|
+
trackPageView: trackPageView,
|
55
|
+
setJTI: setJTI,
|
56
|
+
config: config
|
57
|
+
}
|
58
|
+
|
59
|
+
if ( typeof define === "function" && define.amd ) {
|
60
|
+
define([], function(){
|
61
|
+
return publicAccess
|
62
|
+
})
|
63
|
+
} else {
|
64
|
+
window.shrew = publicAccess
|
65
|
+
}
|
66
|
+
})(typeof shrewConfig !== 'undefined' ? shrewConfig : {
|
67
|
+
pageViewUrl: '/shrew/page_views',
|
68
|
+
jTI: null
|
69
|
+
})
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Shrew
|
2
|
+
class PageViewsController < ApplicationController
|
3
|
+
def create
|
4
|
+
empty_response && return unless params[:jTI].present? && params[:jRT].present?
|
5
|
+
|
6
|
+
page_view = Shrew::PageView.find_by js_tracking_id: params[:jTI]
|
7
|
+
empty_response && return unless page_view
|
8
|
+
|
9
|
+
page_view.js_return_time = params[:jRT]
|
10
|
+
page_view.time_between_sent_and_return = page_view.js_return_time - page_view.sent_time if page_view.js_return_time && page_view.sent_time
|
11
|
+
page_view.save
|
12
|
+
|
13
|
+
empty_response
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def empty_response
|
19
|
+
render json: []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Shrew
|
2
|
+
class PageView < ActiveRecord::Base
|
3
|
+
self.table_name = 'shrew_page_views'
|
4
|
+
belongs_to :user, class_name: Shrew.user_class
|
5
|
+
|
6
|
+
def self.create_from_payload(payload)
|
7
|
+
attributes = payload.slice(:user_id, :controller, :status, :view_runtime,
|
8
|
+
:db_runtime, :sent_time, :js_return_time,
|
9
|
+
:js_tracking_id)
|
10
|
+
.merge(sent_time: milliseconds_since_epoch)
|
11
|
+
create(attributes)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def self.milliseconds_since_epoch
|
16
|
+
(Time.now.to_f * 1000).to_i
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<script defer async>
|
2
|
+
if (typeof define === "function" && define.amd) {
|
3
|
+
require(['shrew'], function(shrew){
|
4
|
+
shrew.setJTI('<%= @_js_tracking_id %>')
|
5
|
+
shrew.automaticallyTrackPageView()
|
6
|
+
})
|
7
|
+
} else {
|
8
|
+
shrew.setJTI('<%= @_js_tracking_id %>')
|
9
|
+
shrew.automaticallyTrackPageView()
|
10
|
+
}
|
11
|
+
</script>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
class AddShrewPageViewTable < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :shrew_page_views do |t|
|
4
|
+
t.integer :user_id
|
5
|
+
t.string :controller
|
6
|
+
t.integer :status
|
7
|
+
t.float :view_runtime
|
8
|
+
t.float :db_runtime
|
9
|
+
t.integer :sent_time
|
10
|
+
t.integer :js_return_time
|
11
|
+
t.integer :time_between_sent_and_return
|
12
|
+
t.binary :js_tracking_id, limit: 16
|
13
|
+
end
|
14
|
+
|
15
|
+
add_index :shrew_page_views, :user_id
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Shrew
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
include Rails::Generators::Migration
|
5
|
+
source_root File.expand_path('../../templates', __FILE__)
|
6
|
+
|
7
|
+
desc 'Create a shrew initializer'
|
8
|
+
|
9
|
+
def copy_initializer
|
10
|
+
template 'shrew.rb', 'config/initializers/shrew.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
def copy_migration
|
14
|
+
migration_template 'page_view_migration.rb', 'db/migrate/add_shrew_page_view_table.rb'
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_routes
|
18
|
+
route "mount Shrew::Engine => '/shrew', as: 'shrew'"
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.next_migration_number(path)
|
22
|
+
unless @prev_migration_nr
|
23
|
+
@prev_migration_nr = Time.now.utc.strftime('%Y%m%d%H%M%S').to_i
|
24
|
+
else
|
25
|
+
@prev_migration_nr += 1
|
26
|
+
end
|
27
|
+
@prev_migration_nr.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class AddShrewPageViewTable < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :shrew_page_views do |t|
|
4
|
+
t.integer :user_id
|
5
|
+
t.string :controller
|
6
|
+
t.integer :status
|
7
|
+
t.float :view_runtime
|
8
|
+
t.float :db_runtime
|
9
|
+
t.integer :sent_time
|
10
|
+
t.integer :js_return_time
|
11
|
+
t.integer :time_between_sent_and_return
|
12
|
+
t.binary :js_tracking_id, limit: 16
|
13
|
+
end
|
14
|
+
|
15
|
+
add_index :shrew_page_views, :user_id
|
16
|
+
end
|
17
|
+
end
|
data/lib/shrew/engine.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Shrew
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
initializer 'shrew.configure_rails_initialization' do |_|
|
4
|
+
ActiveSupport::Notifications.subscribe 'process_action.action_controller' do
|
5
|
+
|_, start, finish, _, payload|
|
6
|
+
|
7
|
+
duration = (finish - start) * 1000
|
8
|
+
payload[:duration] = duration
|
9
|
+
next if payload[:controller] == 'Shrew::PageViewsController'
|
10
|
+
Shrew::PageView.create_from_payload(payload)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Shrew
|
2
|
+
module TracksPageViews
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def append_info_to_payload(payload)
|
6
|
+
super
|
7
|
+
return unless @_tracking_page_views
|
8
|
+
payload[:user_id] = try(:current_user).try(:id)
|
9
|
+
payload[:js_tracking_id] = @_js_tracking_id
|
10
|
+
end
|
11
|
+
|
12
|
+
included do
|
13
|
+
before_action :tracks_page_views
|
14
|
+
end
|
15
|
+
|
16
|
+
def tracks_page_views
|
17
|
+
@_tracking_page_views = true
|
18
|
+
@_js_tracking_id = SecureRandom.uuid
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/shrew.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
require 'shrew/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'shrew'
|
8
|
+
s.version = Shrew::VERSION
|
9
|
+
s.date = '2014-11-05'
|
10
|
+
s.summary = 'Shrew'
|
11
|
+
s.description = 'A simple shrew gem'
|
12
|
+
s.authors = ['Adam Gross']
|
13
|
+
s.email = 'agross@synergydatasystems.com'
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
s.license = 'MIT'
|
18
|
+
|
19
|
+
s.add_dependency 'activesupport', '>=4.0.0'
|
20
|
+
s.add_dependency 'activerecord', '>=4.0.0'
|
21
|
+
|
22
|
+
s.add_development_dependency 'rspec', '~>3.1.0'
|
23
|
+
s.add_development_dependency 'rspec-rails', '~>3.1.0'
|
24
|
+
s.add_development_dependency 'sqlite3'
|
25
|
+
s.add_development_dependency 'database_cleaner'
|
26
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe Shrew::PageViewsController, type: :controller do
|
4
|
+
routes { Shrew::Engine.routes }
|
5
|
+
|
6
|
+
required_params = { jTI: '1', jRT: '100' }
|
7
|
+
|
8
|
+
context 'when missing parameter' do
|
9
|
+
required_params.each do |required_param|
|
10
|
+
it "#{required_param} does not attempt to find a page view" do
|
11
|
+
expect(Shrew::PageView).not_to receive(:find_by)
|
12
|
+
|
13
|
+
post :create, required_params.slice(required_param)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns a 200 empty response anyways' do
|
17
|
+
post :create, required_params.slice(required_param)
|
18
|
+
|
19
|
+
expect(response.status).to eq 200
|
20
|
+
expect(response.body).to eq '[]'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when the javascript tracking id matches no existing page view' do
|
26
|
+
it 'returns a 200 empty response anyways' do
|
27
|
+
expect(Shrew::PageView).to receive(:find_by).and_return(nil)
|
28
|
+
|
29
|
+
post :create, required_params
|
30
|
+
|
31
|
+
expect(response.status).to eq 200
|
32
|
+
expect(response.body).to eq '[]'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when successful' do
|
37
|
+
let(:page_view) { Shrew::PageView.new }
|
38
|
+
before(:each) do
|
39
|
+
expect(Shrew::PageView).to receive(:find_by).and_return(page_view)
|
40
|
+
expect(page_view).to receive(:save).and_return(true)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'updates the page view with the js return time' do
|
44
|
+
post :create, required_params
|
45
|
+
|
46
|
+
expect(page_view.js_return_time).to eq 100
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns a 200 empty response' do
|
50
|
+
post :create, required_params
|
51
|
+
|
52
|
+
expect(response.status).to eq 200
|
53
|
+
expect(response.body).to eq '[]'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
class ApplicationController < ActionController::Base
|
4
|
+
include Shrew::TracksPageViews
|
5
|
+
end
|
6
|
+
|
7
|
+
RSpec.describe ApplicationController do
|
8
|
+
controller do
|
9
|
+
def current_user
|
10
|
+
{}
|
11
|
+
end
|
12
|
+
def index
|
13
|
+
render json: 'ok'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Shrew::TracksPageViews do
|
18
|
+
it 'adds the js tracking id to be used in the layout' do
|
19
|
+
get :index
|
20
|
+
expect(assigns(:_js_tracking_id)).not_to eq nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'sets that we are going to track page views to append to payload' do
|
24
|
+
get :index
|
25
|
+
expect(assigns(:_tracking_page_views)).to eq true
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'creates the initial page view' do
|
29
|
+
expect {
|
30
|
+
get :index
|
31
|
+
}.to change{Shrew::PageView.count}.by(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
2
|
+
ENV["RAILS_ENV"] ||= 'test'
|
3
|
+
require 'spec_helper'
|
4
|
+
require File.expand_path("../../test/dummy/config/environment", __FILE__)
|
5
|
+
require 'rspec/rails'
|
6
|
+
# Add additional requires below this line. Rails is not loaded until this point!
|
7
|
+
|
8
|
+
# Requires supporting ruby files with custom matchers and macros, etc, in
|
9
|
+
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
|
10
|
+
# run as spec files by default. This means that files in spec/support that end
|
11
|
+
# in _spec.rb will both be required and run as specs, causing the specs to be
|
12
|
+
# run twice. It is recommended that you do not name files matching this glob to
|
13
|
+
# end with _spec.rb. You can configure this pattern with the --pattern
|
14
|
+
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
|
15
|
+
#
|
16
|
+
# The following line is provided for convenience purposes. It has the downside
|
17
|
+
# of increasing the boot-up time by auto-requiring all files in the support
|
18
|
+
# directory. Alternatively, in the individual `*_spec.rb` files, manually
|
19
|
+
# require only the support files necessary.
|
20
|
+
#
|
21
|
+
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
22
|
+
|
23
|
+
# Checks for pending migrations before tests are run.
|
24
|
+
# If you are not using ActiveRecord, you can remove this line.
|
25
|
+
ActiveRecord::Migration.maintain_test_schema!
|
26
|
+
|
27
|
+
RSpec.configure do |config|
|
28
|
+
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
29
|
+
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
30
|
+
|
31
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
32
|
+
# examples within a transaction, remove the following line or assign false
|
33
|
+
# instead of true.
|
34
|
+
config.use_transactional_fixtures = false
|
35
|
+
|
36
|
+
# RSpec Rails can automatically mix in different behaviours to your tests
|
37
|
+
# based on their file location, for example enabling you to call `get` and
|
38
|
+
# `post` in specs under `spec/controllers`.
|
39
|
+
#
|
40
|
+
# You can disable this behaviour by removing the line below, and instead
|
41
|
+
# explicitly tag your specs with their type, e.g.:
|
42
|
+
#
|
43
|
+
# RSpec.describe UsersController, :type => :controller do
|
44
|
+
# # ...
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# The different available types are documented in the features, such as in
|
48
|
+
# https://relishapp.com/rspec/rspec-rails/docs
|
49
|
+
config.infer_spec_type_from_file_location!
|
50
|
+
end
|