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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f3a81162866c03a621491abb0194ebe878a7f48
4
- data.tar.gz: 050571dcc31a26851ee56da2b373503507d3547c
3
+ metadata.gz: 1aebb95363cb98c2b74dadb3b42f9cd04c17c421
4
+ data.tar.gz: 08785d2aa638fddb3881d4365e74ded3049cfec8
5
5
  SHA512:
6
- metadata.gz: 7259821c2286af301fcc08ca16fa6b9ef284668740d5d4e7c136adc27c250521458da9a97a859c0ecf724ab2e469a78ff4670459333e08c594af658abb6b4707
7
- data.tar.gz: 918d05e4515f41a79991324a93bb240965bb60d685279fcb53893228a87a6954c1dfd1ae4dbe162e5366d8d270fd5625546d2656795f4d51f0f839af0c6d8c85
6
+ metadata.gz: 16c58280be2b7a51a4f41c837204f701a93897b509330a0ff648d06819e2b944373fcaf5e0b595009270f5b332ec1ef81626537b824deafbd2f89cca5ece4376
7
+ data.tar.gz: 2aeb6f81dd3f0fdf09d0aee20ba52ed9349903636b9b392e87782ae135161520809aa45549dca292a479d5bae95ba893c4e6f95b29e13f6d32c601a39e204aae
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 1.4.2
2
+
3
+ - Fixed issues with `where_properties`
4
+
1
5
  ## 1.4.1
2
6
 
3
7
  - Added `where_properties` method
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in ahoy.gemspec
4
4
  gemspec
5
+
6
+ gem "rails", "~> 5.0.0.rc1"
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-master) [master]
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 [master]
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(store_id: 1).count
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 to your model `include Ahoy::Properties`.
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
- ActionController::Base.send :include, Ahoy::Controller
110
- ActiveRecord::Base.send(:extend, Ahoy::Model) if defined?(ActiveRecord)
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 "syslog/logger"
122
- Syslog::Logger.send :include, Ahoy::LoggerSilencer
123
- rescue LoadError; end
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
@@ -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
- case column_type
10
- when :jsonb, :json
11
- properties.each do |k, v|
12
- relation = relation.where("properties ->> ? = ?", k, v)
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
- else
15
- properties.each do |k, v|
16
- # not 100%, but will do
17
- relation = relation.where("properties LIKE ?", "%#{{k => v}.to_json.sub(/\A\{/, "").sub(/\}\z/, "")}%")
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
@@ -1,3 +1,3 @@
1
1
  module Ahoy
2
- VERSION = "1.4.1"
2
+ VERSION = "1.4.2"
3
3
  end
@@ -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.1
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