ahoy_matey 1.4.1 → 1.4.2
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/CHANGELOG.md +4 -0
- data/Gemfile +2 -0
- data/README.md +6 -4
- data/ahoy_matey.gemspec +3 -0
- data/lib/ahoy.rb +17 -14
- data/lib/ahoy/properties.rb +42 -8
- data/lib/ahoy/version.rb +1 -1
- data/test/properties/mysql_json_test.rb +18 -0
- data/test/properties/mysql_text_test.rb +19 -0
- data/test/properties/postgresql_hstore_test.rb +18 -0
- data/test/properties/postgresql_json_test.rb +18 -0
- data/test/properties/postgresql_jsonb_test.rb +18 -0
- data/test/properties/postgresql_text_test.rb +19 -0
- data/test/test_helper.rb +95 -0
- metadata +55 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1aebb95363cb98c2b74dadb3b42f9cd04c17c421
|
4
|
+
data.tar.gz: 08785d2aa638fddb3881d4365e74ded3049cfec8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16c58280be2b7a51a4f41c837204f701a93897b509330a0ff648d06819e2b944373fcaf5e0b595009270f5b332ec1ef81626537b824deafbd2f89cca5ece4376
|
7
|
+
data.tar.gz: 2aeb6f81dd3f0fdf09d0aee20ba52ed9349903636b9b392e87782ae135161520809aa45549dca292a479d5bae95ba893c4e6f95b29e13f6d32c601a39e204aae
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -27,7 +27,7 @@ Ahoy supports a number of data stores out of the box. You can start with one of
|
|
27
27
|
|
28
28
|
- [PostgreSQL, MySQL, or SQLite](#postgresql-mysql-or-sqlite)
|
29
29
|
- [MongoDB](#mongodb)
|
30
|
-
- [Kafka](#kafka
|
30
|
+
- [Kafka](#kafka)
|
31
31
|
- [Fluentd](#fluentd)
|
32
32
|
- [RabbitMQ](#rabbitmq)
|
33
33
|
- [Amazon Kinesis Firehose](#amazon-kinesis-firehose)
|
@@ -49,7 +49,7 @@ rake db:migrate
|
|
49
49
|
rails generate ahoy:stores:mongoid
|
50
50
|
```
|
51
51
|
|
52
|
-
### Kafka
|
52
|
+
### Kafka
|
53
53
|
|
54
54
|
Add [ruby-kafka](https://github.com/zendesk/ruby-kafka) to your Gemfile.
|
55
55
|
|
@@ -489,11 +489,13 @@ The same approach also works with visitor tokens.
|
|
489
489
|
|
490
490
|
### Querying Properties
|
491
491
|
|
492
|
+
With ActiveRecord, use:
|
493
|
+
|
492
494
|
```ruby
|
493
|
-
Ahoy::Event.where_properties(
|
495
|
+
Ahoy::Event.where(name: "Viewed product").where_properties(product_id: 123).count
|
494
496
|
```
|
495
497
|
|
496
|
-
**Note:** If you get a `NoMethodError`, upgrade Ahoy and add
|
498
|
+
**Note:** If you get a `NoMethodError`, upgrade Ahoy and add `include Ahoy::Properties` to your model.
|
497
499
|
|
498
500
|
## Native Apps
|
499
501
|
|
data/ahoy_matey.gemspec
CHANGED
@@ -32,4 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_development_dependency "bundler", "~> 1.5"
|
33
33
|
spec.add_development_dependency "rake"
|
34
34
|
spec.add_development_dependency "minitest"
|
35
|
+
spec.add_development_dependency "activerecord"
|
36
|
+
spec.add_development_dependency "pg"
|
37
|
+
spec.add_development_dependency "mysql2"
|
35
38
|
end
|
data/lib/ahoy.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "active_support"
|
1
2
|
require "active_support/core_ext"
|
2
3
|
require "addressable/uri"
|
3
4
|
require "browser"
|
@@ -28,7 +29,7 @@ require "ahoy/stores/mongoid_store"
|
|
28
29
|
require "ahoy/stores/kafka_store"
|
29
30
|
require "ahoy/stores/kinesis_firehose_store"
|
30
31
|
require "ahoy/stores/bunny_store"
|
31
|
-
require "ahoy/engine"
|
32
|
+
require "ahoy/engine" if defined?(Rails)
|
32
33
|
require "ahoy/warden" if defined?(Warden)
|
33
34
|
|
34
35
|
# background jobs
|
@@ -106,19 +107,21 @@ module Ahoy
|
|
106
107
|
self.track_bots = false
|
107
108
|
end
|
108
109
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
# ensure logger silence will not be added by activerecord-session_store
|
113
|
-
# otherwise, we get SystemStackError: stack level too deep
|
114
|
-
begin
|
115
|
-
require "active_record/session_store/extension/logger_silencer"
|
116
|
-
rescue LoadError
|
117
|
-
require "ahoy/logger_silencer"
|
118
|
-
Logger.send :include, Ahoy::LoggerSilencer
|
110
|
+
if defined?(Rails)
|
111
|
+
ActionController::Base.send :include, Ahoy::Controller
|
112
|
+
ActiveRecord::Base.send(:extend, Ahoy::Model) if defined?(ActiveRecord)
|
119
113
|
|
114
|
+
# ensure logger silence will not be added by activerecord-session_store
|
115
|
+
# otherwise, we get SystemStackError: stack level too deep
|
120
116
|
begin
|
121
|
-
require "
|
122
|
-
|
123
|
-
|
117
|
+
require "active_record/session_store/extension/logger_silencer"
|
118
|
+
rescue LoadError
|
119
|
+
require "ahoy/logger_silencer"
|
120
|
+
Logger.send :include, Ahoy::LoggerSilencer
|
121
|
+
|
122
|
+
begin
|
123
|
+
require "syslog/logger"
|
124
|
+
Syslog::Logger.send :include, Ahoy::LoggerSilencer
|
125
|
+
rescue LoadError; end
|
126
|
+
end
|
124
127
|
end
|
data/lib/ahoy/properties.rb
CHANGED
@@ -6,16 +6,50 @@ module Ahoy
|
|
6
6
|
def where_properties(properties)
|
7
7
|
relation = self
|
8
8
|
column_type = columns_hash["properties"].type
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
adapter_name = connection.adapter_name.downcase
|
10
|
+
case adapter_name
|
11
|
+
when /mysql/
|
12
|
+
if column_type == :json
|
13
|
+
properties.each do |k, v|
|
14
|
+
if v.nil?
|
15
|
+
v = "null"
|
16
|
+
elsif v == true
|
17
|
+
v = "true"
|
18
|
+
end
|
19
|
+
|
20
|
+
relation = relation.where("JSON_UNQUOTE(properties -> ?) = ?", "$.#{k.to_s}", v.as_json)
|
21
|
+
end
|
22
|
+
else
|
23
|
+
properties.each do |k, v|
|
24
|
+
relation = relation.where("properties REGEXP ?", "[{,]#{{k.to_s => v}.to_json.sub(/\A\{/, "").sub(/\}\z/, "")}[,}]")
|
25
|
+
end
|
13
26
|
end
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
27
|
+
when /postgres/
|
28
|
+
if column_type == :jsonb || column_type == :json
|
29
|
+
properties.each do |k, v|
|
30
|
+
relation =
|
31
|
+
if v.nil?
|
32
|
+
relation.where("properties ->> ? IS NULL", k.to_s)
|
33
|
+
else
|
34
|
+
relation.where("properties ->> ? = ?", k.to_s, v.as_json.to_s)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
elsif column_type == :hstore
|
38
|
+
properties.each do |k, v|
|
39
|
+
relation =
|
40
|
+
if v.nil?
|
41
|
+
relation.where("properties -> ? IS NULL", k.to_s)
|
42
|
+
else
|
43
|
+
relation.where("properties -> ? = ?", k.to_s, v.to_s)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
else
|
47
|
+
properties.each do |k, v|
|
48
|
+
relation = relation.where("properties SIMILAR TO ?", "%[{,]#{{k.to_s => v}.to_json.sub(/\A\{/, "").sub(/\}\z/, "")}[,}]%")
|
49
|
+
end
|
18
50
|
end
|
51
|
+
else
|
52
|
+
raise "Adapter not supported: #{adapter_name}"
|
19
53
|
end
|
20
54
|
relation
|
21
55
|
end
|
data/lib/ahoy/version.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "../test_helper"
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection adapter: "mysql2", username: "root", database: "ahoy_test"
|
4
|
+
|
5
|
+
ActiveRecord::Migration.create_table :mysql_json_events, force: true do |t|
|
6
|
+
t.json :properties
|
7
|
+
end
|
8
|
+
|
9
|
+
class MysqlJsonEvent < MysqlBase
|
10
|
+
end
|
11
|
+
|
12
|
+
class MysqlJsonTest < Minitest::Test
|
13
|
+
include PropertiesTest
|
14
|
+
|
15
|
+
def model
|
16
|
+
MysqlJsonEvent
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "../test_helper"
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection adapter: "mysql2", username: "root", database: "ahoy_test"
|
4
|
+
|
5
|
+
ActiveRecord::Migration.create_table :mysql_text_events, force: true do |t|
|
6
|
+
t.text :properties
|
7
|
+
end
|
8
|
+
|
9
|
+
class MysqlTextEvent < MysqlBase
|
10
|
+
serialize :properties, JSON
|
11
|
+
end
|
12
|
+
|
13
|
+
class MysqlTextTest < Minitest::Test
|
14
|
+
include PropertiesTest
|
15
|
+
|
16
|
+
def model
|
17
|
+
MysqlTextEvent
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "../test_helper"
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection adapter: "postgresql", database: "ahoy_test"
|
4
|
+
|
5
|
+
ActiveRecord::Migration.create_table :postgresql_hstore_events, force: true do |t|
|
6
|
+
t.hstore :properties
|
7
|
+
end
|
8
|
+
|
9
|
+
class PostgresqlHstoreEvent < PostgresqlBase
|
10
|
+
end
|
11
|
+
|
12
|
+
class PostgresqlHstoreTest < Minitest::Test
|
13
|
+
include PropertiesTest
|
14
|
+
|
15
|
+
def model
|
16
|
+
PostgresqlHstoreEvent
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "../test_helper"
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection adapter: "postgresql", database: "ahoy_test"
|
4
|
+
|
5
|
+
ActiveRecord::Migration.create_table :postgresql_json_events, force: true do |t|
|
6
|
+
t.json :properties
|
7
|
+
end
|
8
|
+
|
9
|
+
class PostgresqlJsonEvent < PostgresqlBase
|
10
|
+
end
|
11
|
+
|
12
|
+
class PostgresqlJsonTest < Minitest::Test
|
13
|
+
include PropertiesTest
|
14
|
+
|
15
|
+
def model
|
16
|
+
PostgresqlJsonEvent
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "../test_helper"
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection adapter: "postgresql", database: "ahoy_test"
|
4
|
+
|
5
|
+
ActiveRecord::Migration.create_table :postgresql_jsonb_events, force: true do |t|
|
6
|
+
t.jsonb :properties
|
7
|
+
end
|
8
|
+
|
9
|
+
class PostgresqlJsonbEvent < PostgresqlBase
|
10
|
+
end
|
11
|
+
|
12
|
+
class PostgresqlJsonbTest < Minitest::Test
|
13
|
+
include PropertiesTest
|
14
|
+
|
15
|
+
def model
|
16
|
+
PostgresqlJsonbEvent
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "../test_helper"
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection adapter: "postgresql", database: "ahoy_test"
|
4
|
+
|
5
|
+
ActiveRecord::Migration.create_table :postgresql_text_events, force: true do |t|
|
6
|
+
t.text :properties
|
7
|
+
end
|
8
|
+
|
9
|
+
class PostgresqlTextEvent < PostgresqlBase
|
10
|
+
serialize :properties, JSON
|
11
|
+
end
|
12
|
+
|
13
|
+
class PostgresqlTextTest < Minitest::Test
|
14
|
+
include PropertiesTest
|
15
|
+
|
16
|
+
def model
|
17
|
+
PostgresqlTextEvent
|
18
|
+
end
|
19
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -2,3 +2,98 @@ require "bundler/setup"
|
|
2
2
|
Bundler.require(:default)
|
3
3
|
require "minitest/autorun"
|
4
4
|
require "minitest/pride"
|
5
|
+
require "active_record"
|
6
|
+
|
7
|
+
ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT) if ENV["VERBOSE"]
|
8
|
+
|
9
|
+
class PostgresqlBase < ActiveRecord::Base
|
10
|
+
include Ahoy::Properties
|
11
|
+
establish_connection adapter: "postgresql", database: "ahoy_test"
|
12
|
+
self.abstract_class = true
|
13
|
+
end
|
14
|
+
|
15
|
+
class MysqlBase < ActiveRecord::Base
|
16
|
+
include Ahoy::Properties
|
17
|
+
establish_connection adapter: "mysql2", username: "root", database: "ahoy_test"
|
18
|
+
self.abstract_class = true
|
19
|
+
end
|
20
|
+
|
21
|
+
module PropertiesTest
|
22
|
+
def setup
|
23
|
+
model.delete_all
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_empty
|
27
|
+
assert_equal 0, count_events({})
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_string
|
31
|
+
create_event value: "world"
|
32
|
+
assert_equal 1, count_events(value: "world")
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_number
|
36
|
+
create_event value: 1
|
37
|
+
assert_equal 1, count_events(value: 1)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_date
|
41
|
+
today = Date.today
|
42
|
+
create_event value: today
|
43
|
+
assert_equal 1, count_events(value: today)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_time
|
47
|
+
now = Time.now
|
48
|
+
create_event value: now
|
49
|
+
assert_equal 1, count_events(value: now)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_true
|
53
|
+
create_event value: true
|
54
|
+
assert_equal 1, count_events(value: true)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_false
|
58
|
+
create_event value: false
|
59
|
+
assert_equal 1, count_events(value: false)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_nil
|
63
|
+
create_event value: nil
|
64
|
+
assert_equal 1, count_events(value: nil)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_any
|
68
|
+
create_event hello: "world", prop2: "hi"
|
69
|
+
assert_equal 1, count_events(hello: "world")
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_multiple
|
73
|
+
create_event prop1: "hi", prop2: "bye"
|
74
|
+
assert_equal 1, count_events(prop1: "hi", prop2: "bye")
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_multiple_order
|
78
|
+
create_event prop2: "bye", prop1: "hi"
|
79
|
+
assert_equal 1, count_events(prop1: "hi", prop2: "bye")
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_partial
|
83
|
+
create_event hello: "world"
|
84
|
+
assert_equal 0, count_events(hello: "world", prop2: "hi")
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_prefix
|
88
|
+
create_event value: 123
|
89
|
+
assert_equal 0, count_events(value: 1)
|
90
|
+
end
|
91
|
+
|
92
|
+
def create_event(properties)
|
93
|
+
model.create(properties: properties)
|
94
|
+
end
|
95
|
+
|
96
|
+
def count_events(properties)
|
97
|
+
model.where_properties(properties).count
|
98
|
+
end
|
99
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ahoy_matey
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
@@ -192,6 +192,48 @@ dependencies:
|
|
192
192
|
- - ">="
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: activerecord
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: pg
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: mysql2
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - ">="
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '0'
|
195
237
|
description: Simple, powerful visit tracking for Rails
|
196
238
|
email:
|
197
239
|
- andrew@chartkick.com
|
@@ -264,6 +306,12 @@ files:
|
|
264
306
|
- lib/generators/ahoy/stores/templates/mongoid_event_model.rb
|
265
307
|
- lib/generators/ahoy/stores/templates/mongoid_initializer.rb
|
266
308
|
- lib/generators/ahoy/stores/templates/mongoid_visit_model.rb
|
309
|
+
- test/properties/mysql_json_test.rb
|
310
|
+
- test/properties/mysql_text_test.rb
|
311
|
+
- test/properties/postgresql_hstore_test.rb
|
312
|
+
- test/properties/postgresql_json_test.rb
|
313
|
+
- test/properties/postgresql_jsonb_test.rb
|
314
|
+
- test/properties/postgresql_text_test.rb
|
267
315
|
- test/test_helper.rb
|
268
316
|
- test/visit_properties_test.rb
|
269
317
|
- vendor/assets/javascripts/ahoy.js
|
@@ -292,5 +340,11 @@ signing_key:
|
|
292
340
|
specification_version: 4
|
293
341
|
summary: Simple, powerful visit tracking for Rails
|
294
342
|
test_files:
|
343
|
+
- test/properties/mysql_json_test.rb
|
344
|
+
- test/properties/mysql_text_test.rb
|
345
|
+
- test/properties/postgresql_hstore_test.rb
|
346
|
+
- test/properties/postgresql_json_test.rb
|
347
|
+
- test/properties/postgresql_jsonb_test.rb
|
348
|
+
- test/properties/postgresql_text_test.rb
|
295
349
|
- test/test_helper.rb
|
296
350
|
- test/visit_properties_test.rb
|