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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES.md +11 -8
  3. data/Gemfile +15 -1
  4. data/Gemfile.lock +142 -81
  5. data/README.markdown +148 -119
  6. data/lib/generators/vero_generator.rb +18 -19
  7. data/lib/vero.rb +10 -3
  8. data/lib/vero/api.rb +24 -8
  9. data/lib/vero/api/base_api.rb +12 -11
  10. data/lib/vero/api/events/track_api.rb +5 -3
  11. data/lib/vero/api/users/delete_api.rb +21 -0
  12. data/lib/vero/api/users/edit_api.rb +5 -3
  13. data/lib/vero/api/users/edit_tags_api.rb +7 -5
  14. data/lib/vero/api/users/reidentify_api.rb +5 -3
  15. data/lib/vero/api/users/resubscribe_api.rb +23 -0
  16. data/lib/vero/api/users/track_api.rb +5 -3
  17. data/lib/vero/api/users/unsubscribe_api.rb +3 -1
  18. data/lib/vero/app.rb +4 -2
  19. data/lib/vero/config.rb +14 -19
  20. data/lib/vero/context.rb +9 -11
  21. data/lib/vero/context/api.rb +9 -7
  22. data/lib/vero/dsl.rb +3 -1
  23. data/lib/vero/railtie.rb +5 -3
  24. data/lib/vero/sender.rb +12 -30
  25. data/lib/vero/senders/base.rb +3 -1
  26. data/lib/vero/senders/delayed_job.rb +7 -7
  27. data/lib/vero/senders/invalid.rb +5 -3
  28. data/lib/vero/senders/resque.rb +8 -8
  29. data/lib/vero/senders/sidekiq.rb +25 -0
  30. data/lib/vero/senders/{thread.rb → sucker_punch.rb} +5 -3
  31. data/lib/vero/trackable.rb +4 -2
  32. data/lib/vero/trackable/base.rb +10 -9
  33. data/lib/vero/trackable/interface.rb +3 -1
  34. data/lib/vero/utility/ext.rb +3 -1
  35. data/lib/vero/utility/logger.rb +4 -6
  36. data/lib/vero/version.rb +3 -1
  37. data/lib/vero/view_helpers/javascript.rb +20 -20
  38. data/spec/lib/api/base_api_spec.rb +11 -9
  39. data/spec/lib/api/events/track_api_spec.rb +30 -30
  40. data/spec/lib/api/users/delete_api_spec.rb +33 -0
  41. data/spec/lib/api/users/edit_api_spec.rb +14 -16
  42. data/spec/lib/api/users/edit_tags_api_spec.rb +28 -31
  43. data/spec/lib/api/users/reidentify_spec.rb +20 -22
  44. data/spec/lib/api/users/resubscribe_api_spec.rb +35 -0
  45. data/spec/lib/api/users/track_api_spec.rb +26 -28
  46. data/spec/lib/api/users/unsubscribe_api_spec.rb +14 -16
  47. data/spec/lib/api_spec.rb +59 -57
  48. data/spec/lib/app_spec.rb +21 -19
  49. data/spec/lib/config_spec.rb +77 -59
  50. data/spec/lib/context_spec.rb +27 -25
  51. data/spec/lib/dsl_spec.rb +4 -2
  52. data/spec/lib/sender_spec.rb +12 -23
  53. data/spec/lib/senders/sidekiq_spec.rb +32 -0
  54. data/spec/lib/trackable_spec.rb +125 -151
  55. data/spec/lib/view_helpers_spec.rb +13 -9
  56. data/spec/spec_helper.rb +10 -4
  57. data/spec/support/base_config_shared_examples.rb +11 -0
  58. data/spec/support/user_support.rb +15 -7
  59. data/spec/support/vero_user_support.rb +4 -2
  60. data/vero.gemspec +14 -29
  61. metadata +47 -138
@@ -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.inject({}) do |hash, symbol|
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
- if object.is_a?(Hash)
21
- @config = Vero::Config.new
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
@@ -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 = {:data => event_data, :event_name => event_name, :identity => subject.to_vero, :extras => extras}
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 = {:id => identity[:id], :email => identity[:email], :data => identity}
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 = {:id => identity[:id], :email => identity[:email], :changes => identity}
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 = {:id => identity[:id], :email => identity[:email], :add => Array(add), :remove => Array(remove)}
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 = {:id => identity[:id], :email => identity[:email]}
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 = {:id => previous_id, :new_id => identity[:id]}
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
@@ -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
- @_vero_proxy ||= Proxy.new
20
+ @vero ||= Proxy.new
19
21
  end
20
22
 
21
23
  # :nodoc:
@@ -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 "vero.view_helpers" do
6
- ActionView::Base.send :include, ViewHelpers::Javascript
7
+ initializer 'vero.view_helpers' do
8
+ ActionView::Base.include ViewHelpers::Javascript
7
9
  end
8
10
  end
9
- end
11
+ end
@@ -1,48 +1,30 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  module Vero
4
- class SenderHash < ::Hash
6
+ class SenderLookup
5
7
  def [](key)
6
- if self.has_key?(key)
7
- super
8
- else
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
- t = Vero::SenderHash.new
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
- sender_class = if self.senders[sender_strategy]
38
- self.senders[sender_strategy]
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(self.new, "method: #{api_class.name}, options: #{options_s}, error: #{e.message}")
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  module Vero
@@ -11,4 +13,4 @@ module Vero
11
13
  end
12
14
  end
13
15
  end
14
- end
16
+ end
@@ -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
- raise "To send ratings asynchronously, you must configure delayed_job. Run `rails generate delayed_job:active_record` then `rake db:migrate`."
15
- else
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
@@ -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(api_class, domain, options)
5
- 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
+ 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
@@ -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(api_class_name, domain, options)
9
- api_class = eval(api_class_name)
10
- new_options = {}
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.name}, options: #{options.to_json}, response: resque job queued")
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 Thread
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
@@ -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
@@ -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
- when Array then (@vero_trackable_map << args).flatten
13
- else
14
- args
15
- end
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.inject({}) do |hash, symbol|
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.reject! { |i| !(i.is_a?(Hash) && i.has_key?(:extras)) }
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.has_key?(:email_address)
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
4
  module Trackable
3
5
  module Interface
@@ -14,4 +16,4 @@ module Vero
14
16
  end
15
17
  end
16
18
  end
17
- end
19
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Object
2
4
  def blank?
3
5
  respond_to?(:empty?) ? empty? : !self
4
6
  end
5
- end
7
+ end
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
- VERSION = '0.7.0'
4
+ VERSION = '0.10.0'
3
5
  end
@@ -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 "" unless context.configured?
7
+ return '' unless context.configured?
8
+
6
9
  config = context.config
7
10
 
8
- unless [:default, :mixpanel, :kissmetrics].include?(method)
9
- method = :default
10
- end
11
+ method = :default unless %i[default mixpanel kissmetrics].include?(method)
11
12
 
12
- method_name = method.to_s + "_vero_javascript_tag"
13
- self.send(method_name.to_sym, config.config_params)
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, {:type => "text/javascript"} do
19
- result = "var _veroq = _veroq || [];" +
20
- "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);" +
21
- "_veroq.push(['init', {" +
22
- options_to_string(options) +
23
- "}]);" +
24
- "(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);})();"
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.kind_of?(Hash)
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