ahoy_matey 1.4.1 → 1.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|