vero 0.7.0 → 0.10.0
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 +7 -0
- data/CHANGES.md +11 -8
- data/Gemfile +15 -1
- data/Gemfile.lock +142 -81
- data/README.markdown +148 -119
- data/lib/generators/vero_generator.rb +18 -19
- data/lib/vero.rb +10 -3
- data/lib/vero/api.rb +24 -8
- data/lib/vero/api/base_api.rb +12 -11
- data/lib/vero/api/events/track_api.rb +5 -3
- data/lib/vero/api/users/delete_api.rb +21 -0
- data/lib/vero/api/users/edit_api.rb +5 -3
- data/lib/vero/api/users/edit_tags_api.rb +7 -5
- data/lib/vero/api/users/reidentify_api.rb +5 -3
- data/lib/vero/api/users/resubscribe_api.rb +23 -0
- data/lib/vero/api/users/track_api.rb +5 -3
- data/lib/vero/api/users/unsubscribe_api.rb +3 -1
- data/lib/vero/app.rb +4 -2
- data/lib/vero/config.rb +14 -19
- data/lib/vero/context.rb +9 -11
- data/lib/vero/context/api.rb +9 -7
- data/lib/vero/dsl.rb +3 -1
- data/lib/vero/railtie.rb +5 -3
- data/lib/vero/sender.rb +12 -30
- data/lib/vero/senders/base.rb +3 -1
- data/lib/vero/senders/delayed_job.rb +7 -7
- data/lib/vero/senders/invalid.rb +5 -3
- data/lib/vero/senders/resque.rb +8 -8
- data/lib/vero/senders/sidekiq.rb +25 -0
- data/lib/vero/senders/{thread.rb → sucker_punch.rb} +5 -3
- data/lib/vero/trackable.rb +4 -2
- data/lib/vero/trackable/base.rb +10 -9
- data/lib/vero/trackable/interface.rb +3 -1
- data/lib/vero/utility/ext.rb +3 -1
- data/lib/vero/utility/logger.rb +4 -6
- data/lib/vero/version.rb +3 -1
- data/lib/vero/view_helpers/javascript.rb +20 -20
- data/spec/lib/api/base_api_spec.rb +11 -9
- data/spec/lib/api/events/track_api_spec.rb +30 -30
- data/spec/lib/api/users/delete_api_spec.rb +33 -0
- data/spec/lib/api/users/edit_api_spec.rb +14 -16
- data/spec/lib/api/users/edit_tags_api_spec.rb +28 -31
- data/spec/lib/api/users/reidentify_spec.rb +20 -22
- data/spec/lib/api/users/resubscribe_api_spec.rb +35 -0
- data/spec/lib/api/users/track_api_spec.rb +26 -28
- data/spec/lib/api/users/unsubscribe_api_spec.rb +14 -16
- data/spec/lib/api_spec.rb +59 -57
- data/spec/lib/app_spec.rb +21 -19
- data/spec/lib/config_spec.rb +77 -59
- data/spec/lib/context_spec.rb +27 -25
- data/spec/lib/dsl_spec.rb +4 -2
- data/spec/lib/sender_spec.rb +12 -23
- data/spec/lib/senders/sidekiq_spec.rb +32 -0
- data/spec/lib/trackable_spec.rb +125 -151
- data/spec/lib/view_helpers_spec.rb +13 -9
- data/spec/spec_helper.rb +10 -4
- data/spec/support/base_config_shared_examples.rb +11 -0
- data/spec/support/user_support.rb +15 -7
- data/spec/support/vero_user_support.rb +4 -2
- data/vero.gemspec +14 -29
- metadata +47 -138
data/lib/vero/context.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vero
|
2
4
|
class Context
|
3
5
|
include Vero::APIContext
|
@@ -6,27 +8,23 @@ module Vero
|
|
6
8
|
def initialize(object = {})
|
7
9
|
case object
|
8
10
|
when Hash
|
9
|
-
#stub
|
11
|
+
# stub
|
10
12
|
when Vero::Context
|
11
13
|
@config = object.config
|
12
14
|
@subject = object.subject
|
13
15
|
else
|
14
|
-
object = Vero::Config.available_attributes.
|
16
|
+
object = Vero::Config.available_attributes.each_with_object({}) do |symbol, hash|
|
15
17
|
hash[symbol] = object.respond_to?(symbol) ? object.send(symbol) : nil
|
16
|
-
hash
|
17
18
|
end
|
18
19
|
end
|
20
|
+
return unless object.is_a?(Hash)
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
self.configure(object)
|
23
|
-
end
|
22
|
+
@config = Vero::Config.new
|
23
|
+
configure(object)
|
24
24
|
end
|
25
25
|
|
26
26
|
def configure(hash = {}, &block)
|
27
|
-
if hash.is_a?(Hash) && hash.any?
|
28
|
-
@config.update_attributes(hash)
|
29
|
-
end
|
27
|
+
@config.update_attributes(hash) if hash.is_a?(Hash) && hash.any?
|
30
28
|
|
31
29
|
block.call(@config) if block_given?
|
32
30
|
end
|
@@ -43,4 +41,4 @@ module Vero
|
|
43
41
|
@config.configured?
|
44
42
|
end
|
45
43
|
end
|
46
|
-
end
|
44
|
+
end
|
data/lib/vero/context/api.rb
CHANGED
@@ -1,38 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vero
|
2
4
|
module APIContext
|
3
5
|
def track!(event_name, event_data, extras = {})
|
4
|
-
options = {:
|
6
|
+
options = { data: event_data, event_name: event_name, identity: subject.to_vero, extras: extras }
|
5
7
|
Vero::Api::Events.track!(options, self)
|
6
8
|
end
|
7
9
|
|
8
10
|
def identify!
|
9
11
|
identity = subject.to_vero
|
10
|
-
options = {:
|
12
|
+
options = { id: identity[:id], email: identity[:email], data: identity }
|
11
13
|
Vero::Api::Users.track!(options, self)
|
12
14
|
end
|
13
15
|
|
14
16
|
def update_user!
|
15
17
|
identity = subject.to_vero
|
16
|
-
options = {:
|
18
|
+
options = { id: identity[:id], email: identity[:email], changes: identity }
|
17
19
|
Vero::Api::Users.edit_user!(options, self)
|
18
20
|
end
|
19
21
|
|
20
22
|
def update_user_tags!(add = [], remove = [])
|
21
23
|
identity = subject.to_vero
|
22
|
-
options = {:
|
24
|
+
options = { id: identity[:id], email: identity[:email], add: Array(add), remove: Array(remove) }
|
23
25
|
Vero::Api::Users.edit_user_tags!(options, self)
|
24
26
|
end
|
25
27
|
|
26
28
|
def unsubscribe!
|
27
29
|
identity = subject.to_vero
|
28
|
-
options = {:
|
30
|
+
options = { id: identity[:id], email: identity[:email] }
|
29
31
|
Vero::Api::Users.unsubscribe!(options, self)
|
30
32
|
end
|
31
33
|
|
32
34
|
def reidentify!(previous_id)
|
33
35
|
identity = subject.to_vero
|
34
|
-
options = {:
|
36
|
+
options = { id: previous_id, new_id: identity[:id] }
|
35
37
|
Vero::Api::Users.reidentify!(options, self)
|
36
38
|
end
|
37
39
|
end
|
38
|
-
end
|
40
|
+
end
|
data/lib/vero/dsl.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vero
|
2
4
|
##
|
3
5
|
# A lightweight DSL for using the Vero API. You may find this desirable in
|
@@ -15,7 +17,7 @@ module Vero
|
|
15
17
|
# end
|
16
18
|
module DSL
|
17
19
|
def vero
|
18
|
-
@
|
20
|
+
@vero ||= Proxy.new
|
19
21
|
end
|
20
22
|
|
21
23
|
# :nodoc:
|
data/lib/vero/railtie.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'vero/view_helpers/javascript'
|
2
4
|
|
3
5
|
module Vero
|
4
6
|
class Railtie < Rails::Railtie
|
5
|
-
initializer
|
6
|
-
ActionView::Base.
|
7
|
+
initializer 'vero.view_helpers' do
|
8
|
+
ActionView::Base.include ViewHelpers::Javascript
|
7
9
|
end
|
8
10
|
end
|
9
|
-
end
|
11
|
+
end
|
data/lib/vero/sender.rb
CHANGED
@@ -1,48 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module Vero
|
4
|
-
class
|
6
|
+
class SenderLookup
|
5
7
|
def [](key)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
klass_name = key.to_s.split("_").map(&:capitalize).join
|
8
|
+
klass_name = key.to_s.split('_').map(&:capitalize).join
|
9
|
+
|
10
|
+
if Vero::Senders.const_defined?(klass_name)
|
10
11
|
Vero::Senders.const_get(klass_name)
|
12
|
+
else
|
13
|
+
Vero::Senders::Base
|
11
14
|
end
|
12
15
|
end
|
13
16
|
end
|
14
17
|
|
15
18
|
class Sender
|
16
19
|
def self.senders
|
17
|
-
|
18
|
-
|
19
|
-
t.merge!({
|
20
|
-
true => Vero::Senders::Invalid,
|
21
|
-
false => Vero::Senders::Base,
|
22
|
-
:none => Vero::Senders::Base,
|
23
|
-
:thread => Vero::Senders::Invalid
|
24
|
-
})
|
25
|
-
|
26
|
-
if RUBY_VERSION !~ /1\.8\./
|
27
|
-
t.merge!(
|
28
|
-
true => Vero::Senders::Thread,
|
29
|
-
:thread => Vero::Senders::Thread
|
30
|
-
)
|
31
|
-
end
|
32
|
-
|
33
|
-
t
|
20
|
+
@senders ||= Vero::SenderLookup.new
|
34
21
|
end
|
35
22
|
|
36
23
|
def self.send(api_class, sender_strategy, domain, options)
|
37
|
-
|
38
|
-
|
39
|
-
else
|
40
|
-
self.senders[false]
|
41
|
-
end
|
42
|
-
(sender_class.new).call(api_class, domain, options)
|
43
|
-
rescue => e
|
24
|
+
senders[sender_strategy].new.call(api_class, domain, options)
|
25
|
+
rescue StandardError => e
|
44
26
|
options_s = JSON.dump(options)
|
45
|
-
Vero::App.log(
|
27
|
+
Vero::App.log(new, "method: #{api_class.name}, options: #{options_s}, error: #{e.message}")
|
46
28
|
raise e
|
47
29
|
end
|
48
30
|
end
|
data/lib/vero/senders/base.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
require 'delayed_job'
|
3
5
|
|
@@ -9,13 +11,11 @@ module Vero
|
|
9
11
|
options_s = JSON.dump(options)
|
10
12
|
Vero::App.log(self, "method: #{api_class.name}, options: #{options_s}, response: delayed job queued")
|
11
13
|
response
|
12
|
-
rescue => e
|
13
|
-
if e.message == "Could not find table 'delayed_jobs'"
|
14
|
-
|
15
|
-
|
16
|
-
raise e
|
17
|
-
end
|
14
|
+
rescue StandardError => e
|
15
|
+
raise 'To send ratings asynchronously, you must configure delayed_job. Run `rails generate delayed_job:active_record` then `rake db:migrate`.' if e.message == "Could not find table 'delayed_jobs'"
|
16
|
+
|
17
|
+
raise e
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
21
|
+
end
|
data/lib/vero/senders/invalid.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vero
|
2
4
|
module Senders
|
3
5
|
class Invalid
|
4
|
-
def call(
|
5
|
-
raise
|
6
|
+
def call(_api_class, _domain, _options)
|
7
|
+
raise 'Vero sender not supported by your version of Ruby. Please change `config.async` to a valid sender. See https://github.com/getvero/vero for more information.'
|
6
8
|
end
|
7
9
|
end
|
8
10
|
end
|
9
|
-
end
|
11
|
+
end
|
data/lib/vero/senders/resque.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
require 'resque'
|
3
5
|
|
@@ -5,15 +7,13 @@ module Vero
|
|
5
7
|
class ResqueWorker
|
6
8
|
@queue = :vero
|
7
9
|
|
8
|
-
def self.perform(
|
9
|
-
|
10
|
-
|
11
|
-
options.each do |k,v|
|
12
|
-
new_options[k.to_sym] = v
|
10
|
+
def self.perform(api_class, domain, options)
|
11
|
+
new_options = options.each_with_object({}) do |(k, v), o|
|
12
|
+
o[k.to_sym] = v
|
13
13
|
end
|
14
14
|
|
15
|
-
api_class.new(domain, new_options).perform
|
16
|
-
Vero::App.log(self, "method: #{api_class
|
15
|
+
api_class.constantize.new(domain, new_options).perform
|
16
|
+
Vero::App.log(self, "method: #{api_class}, options: #{options.to_json}, response: resque job queued")
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -24,4 +24,4 @@ module Vero
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
27
|
-
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'sidekiq'
|
5
|
+
|
6
|
+
module Vero
|
7
|
+
class SidekiqWorker
|
8
|
+
include ::Sidekiq::Worker
|
9
|
+
|
10
|
+
def perform(api_class, domain, options)
|
11
|
+
api_class.constantize.new(domain, options).perform
|
12
|
+
Vero::App.log(self, "method: #{api_class}, options: #{options.to_json}, response: sidekiq job queued")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Senders
|
17
|
+
class Sidekiq
|
18
|
+
def call(api_class, domain, options)
|
19
|
+
response = ::Vero::SidekiqWorker.perform_async(api_class.to_s, domain, options)
|
20
|
+
Vero::App.log(self, "method: #{api_class.name}, options: #{options.to_json}, response: sidekiq job queued")
|
21
|
+
response
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
require 'sucker_punch'
|
3
5
|
|
@@ -7,19 +9,19 @@ module Vero
|
|
7
9
|
|
8
10
|
def perform(api_class, domain, options)
|
9
11
|
new_options = {}
|
10
|
-
options.each { |k,v| new_options[k.to_sym] = v }
|
12
|
+
options.each { |k, v| new_options[k.to_sym] = v }
|
11
13
|
|
12
14
|
begin
|
13
15
|
api_class.new(domain, new_options).perform
|
14
16
|
Vero::App.log(self, "method: #{api_class.name}, options: #{options.to_json}, response: job performed")
|
15
|
-
rescue => e
|
17
|
+
rescue StandardError => e
|
16
18
|
Vero::App.log(self, "method: #{api_class.name}, options: #{options.to_json}, response: #{e.message}")
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
23
|
module Senders
|
22
|
-
class
|
24
|
+
class SuckerPunch
|
23
25
|
def call(api_class, domain, options)
|
24
26
|
Vero::SuckerPunchWorker.new.async.perform(api_class, domain, options)
|
25
27
|
end
|
data/lib/vero/trackable.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'vero/trackable/base'
|
2
4
|
require 'vero/trackable/interface'
|
3
5
|
|
4
6
|
module Vero
|
5
|
-
module Trackable
|
7
|
+
module Trackable
|
6
8
|
include Base
|
7
9
|
include Interface
|
8
10
|
|
@@ -11,4 +13,4 @@ module Vero
|
|
11
13
|
base.extend(Base::ClassMethods)
|
12
14
|
end
|
13
15
|
end
|
14
|
-
end
|
16
|
+
end
|
data/lib/vero/trackable/base.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vero
|
2
4
|
module Trackable
|
3
5
|
module Base
|
@@ -9,10 +11,10 @@ module Vero
|
|
9
11
|
module ClassMethods
|
10
12
|
def trackable(*args)
|
11
13
|
@vero_trackable_map = case @vero_trackable_map
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
when Array then (@vero_trackable_map << args).flatten
|
15
|
+
else
|
16
|
+
args
|
17
|
+
end
|
16
18
|
end
|
17
19
|
|
18
20
|
def trackable_map
|
@@ -27,15 +29,14 @@ module Vero
|
|
27
29
|
def to_vero
|
28
30
|
klass = self.class
|
29
31
|
symbols, other = klass.trackable_map.partition { |i| i.is_a?(Symbol) }
|
30
|
-
|
31
|
-
result = symbols.
|
32
|
+
|
33
|
+
result = symbols.each_with_object({}) do |symbol, hash|
|
32
34
|
t = respond_to?(symbol) ? send(symbol) : nil
|
33
35
|
hash[symbol] = t unless t.nil?
|
34
|
-
hash
|
35
36
|
end
|
36
37
|
|
37
38
|
if other.is_a?(Array) && !other.empty?
|
38
|
-
other.
|
39
|
+
other.select! { |i| (i.is_a?(Hash) && i.key?(:extras)) }
|
39
40
|
other.each do |h|
|
40
41
|
symbol = h[:extras]
|
41
42
|
t = respond_to?(symbol, true) ? send(symbol) : nil
|
@@ -43,7 +44,7 @@ module Vero
|
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
46
|
-
result[:email] = result.delete(:email_address) if result.
|
47
|
+
result[:email] = result.delete(:email_address) if result.key?(:email_address)
|
47
48
|
result[:_user_type] = self.class.name
|
48
49
|
result
|
49
50
|
end
|
data/lib/vero/utility/ext.rb
CHANGED
data/lib/vero/utility/logger.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vero
|
2
4
|
module Utility
|
3
5
|
module Logger
|
@@ -19,13 +21,9 @@ module Vero
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def logger
|
22
|
-
if defined?(Rails)
|
23
|
-
Rails.logger
|
24
|
-
else
|
25
|
-
nil
|
26
|
-
end
|
24
|
+
Rails.logger if defined?(Rails)
|
27
25
|
end
|
28
26
|
end
|
29
27
|
end
|
30
28
|
end
|
31
|
-
end
|
29
|
+
end
|
data/lib/vero/version.rb
CHANGED
@@ -1,43 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vero
|
2
4
|
module ViewHelpers
|
3
5
|
module Javascript
|
4
6
|
def vero_javascript_tag(method = :default, context = Vero::App.default_context)
|
5
|
-
return
|
7
|
+
return '' unless context.configured?
|
8
|
+
|
6
9
|
config = context.config
|
7
10
|
|
8
|
-
unless [
|
9
|
-
method = :default
|
10
|
-
end
|
11
|
+
method = :default unless %i[default mixpanel kissmetrics].include?(method)
|
11
12
|
|
12
|
-
method_name = method
|
13
|
-
|
13
|
+
method_name = "#{method}_vero_javascript_tag"
|
14
|
+
send(method_name.to_sym, config.config_params)
|
14
15
|
end
|
15
16
|
|
16
17
|
private
|
18
|
+
|
17
19
|
def default_vero_javascript_tag(options = {})
|
18
|
-
content_tag :script, {:
|
19
|
-
result =
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
content_tag :script, { type: 'text/javascript' } do
|
21
|
+
result = 'var _veroq = _veroq || [];' \
|
22
|
+
'setTimeout(function(){if(typeof window.Semblance=="undefined"){console.log("Vero did not load in time.");for(var i=0;i<_veroq.length;i++){a=_veroq[i];if(a.length==3&&typeof a[2]=="function")a[2](null,false);}}},3000);' \
|
23
|
+
"_veroq.push(['init', {" +
|
24
|
+
options_to_string(options) +
|
25
|
+
'}]);' \
|
26
|
+
"(function() {var ve = document.createElement('script'); ve.type = 'text/javascript'; ve.async = true; ve.src = '//getvero.com/assets/m.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ve, s);})();"
|
25
27
|
result.html_safe
|
26
28
|
end.html_safe
|
27
29
|
end
|
28
30
|
|
29
|
-
def mixpanel_vero_javascript_tag(options = {})
|
30
|
-
end
|
31
|
+
def mixpanel_vero_javascript_tag(options = {}); end
|
31
32
|
|
32
|
-
def kissmetrics_vero_javascript_tag(options = {})
|
33
|
-
end
|
33
|
+
def kissmetrics_vero_javascript_tag(options = {}); end
|
34
34
|
|
35
35
|
def options_to_string(options)
|
36
|
-
options = {} unless options.
|
36
|
+
options = {} unless options.is_a?(Hash)
|
37
37
|
|
38
38
|
keys = options.keys.map(&:to_s)
|
39
|
-
keys.sort.map { |k| "\"#{k}\": \"#{options[k.to_sym]}\"" }.join(
|
39
|
+
keys.sort.map { |k| "\"#{k}\": \"#{options[k.to_sym]}\"" }.join(', ')
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
|
-
end
|
43
|
+
end
|