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
  class VeroGenerator < Rails::Generators::Base
2
4
  class_option :heroku
3
5
  class_option :api_key
@@ -6,30 +8,27 @@ class VeroGenerator < Rails::Generators::Base
6
8
  def create_initializer_file
7
9
  type = options[:heroku] || 'standard'
8
10
 
9
- if options[:heroku].blank? && (options[:api_key].blank? || options[:api_secret].blank?)
10
- abort("You must provide an API KEY and API SECRET to proceed.")
11
- end
12
- create_file "config/initializers/vero.rb", self.send("#{type}_initializer_content".to_sym)
11
+ abort('You must provide an API KEY and API SECRET to proceed.') if options[:heroku].blank? && (options[:api_key].blank? || options[:api_secret].blank?)
12
+ create_file 'config/initializers/vero.rb', send("#{type}_initializer_content".to_sym)
13
13
  end
14
14
 
15
15
  private
16
+
16
17
  def standard_initializer_content
17
- text = <<-END_TEXT
18
- Vero::App.init do |config|
19
- config.api_key = '#{options[:api_key]}'
20
- config.secret = '#{options[:api_secret]}'
21
- end
22
- END_TEXT
23
- text
18
+ <<~END_TEXT
19
+ Vero::App.init do |config|
20
+ config.api_key = '#{options[:api_key]}'
21
+ config.secret = '#{options[:api_secret]}'
22
+ end
23
+ END_TEXT
24
24
  end
25
25
 
26
26
  def heroku_initializer_content
27
- text = <<-END_TEXT
28
- Vero::App.init do |config|
29
- config.api_key = ENV['VERO_API_KEY']
30
- config.secret = ENV['VERO_API_SECRET']
31
- end
32
- END_TEXT
33
- text
27
+ <<~END_TEXT
28
+ Vero::App.init do |config|
29
+ config.api_key = ENV['VERO_API_KEY']
30
+ config.secret = ENV['VERO_API_SECRET']
31
+ end
32
+ END_TEXT
34
33
  end
35
- end
34
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rest-client'
2
4
  require 'vero/utility/ext'
3
5
 
@@ -9,11 +11,13 @@ module Vero
9
11
  autoload :Trackable, 'vero/trackable'
10
12
  autoload :DSL, 'vero/dsl'
11
13
  autoload :Sender, 'vero/sender'
14
+ autoload :SuckerPunchWorker, 'vero/senders/sucker_punch'
12
15
  autoload :ResqueWorker, 'vero/senders/resque'
16
+ autoload :SidekiqWorker, 'vero/senders/sidekiq'
13
17
 
14
18
  module Api
15
19
  module Workers
16
- autoload :BaseAPI, 'vero/api/base_api'
20
+ autoload :BaseAPI, 'vero/api/base_api'
17
21
 
18
22
  module Events
19
23
  autoload :TrackAPI, 'vero/api/events/track_api'
@@ -24,7 +28,9 @@ module Vero
24
28
  autoload :EditAPI, 'vero/api/users/edit_api'
25
29
  autoload :EditTagsAPI, 'vero/api/users/edit_tags_api'
26
30
  autoload :UnsubscribeAPI, 'vero/api/users/unsubscribe_api'
31
+ autoload :ResubscribeAPI, 'vero/api/users/resubscribe_api'
27
32
  autoload :ReidentifyAPI, 'vero/api/users/reidentify_api'
33
+ autoload :DeleteAPI, 'vero/api/users/delete_api'
28
34
  end
29
35
  end
30
36
 
@@ -36,12 +42,13 @@ module Vero
36
42
  autoload :Base, 'vero/senders/base'
37
43
  autoload :DelayedJob, 'vero/senders/delayed_job'
38
44
  autoload :Resque, 'vero/senders/resque'
45
+ autoload :Sidekiq, 'vero/senders/sidekiq'
39
46
  autoload :Invalid, 'vero/senders/invalid'
40
- autoload :Thread, 'vero/senders/thread'
47
+ autoload :SuckerPunch, 'vero/senders/sucker_punch'
41
48
  end
42
49
 
43
50
  module Utility
44
- autoload :Logger, 'vero/utility/logger'
51
+ autoload :Logger, 'vero/utility/logger'
45
52
  end
46
53
  end
47
54
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
4
  module Api
3
5
  class Base
@@ -8,23 +10,21 @@ module Vero
8
10
  end
9
11
 
10
12
  def config
11
- self.context.config
13
+ context.config
12
14
  end
13
15
 
14
16
  def run_api(api_klass, options)
17
+ return if config.disabled
18
+
15
19
  validate_configured!
16
20
  options.merge!(config.request_params)
17
-
18
- unless config.disabled
19
- Vero::Sender.send(api_klass, config.async, config.domain, options)
20
- end
21
+ Vero::Sender.send(api_klass, config.async, config.domain, options)
21
22
  end
22
23
 
23
24
  protected
25
+
24
26
  def validate_configured!
25
- unless config.configured?
26
- raise "You must configure the 'vero' gem. Visit https://github.com/semblancesystems/vero for more details."
27
- end
27
+ raise "You must configure the 'vero' gem. Visit https://github.com/getvero/vero for more details." unless config.configured?
28
28
  end
29
29
  end
30
30
 
@@ -59,6 +59,14 @@ module Vero
59
59
  new(context).unsubscribe!(options)
60
60
  end
61
61
 
62
+ def self.resubscribe!(options, context = Vero::App.default_context)
63
+ new(context).resubscribe!(options)
64
+ end
65
+
66
+ def self.delete!(options, context = Vero::App.default_context)
67
+ new(context).delete!(options)
68
+ end
69
+
62
70
  def track!(options)
63
71
  run_api(Vero::Api::Workers::Users::TrackAPI, options)
64
72
  end
@@ -75,9 +83,17 @@ module Vero
75
83
  run_api(Vero::Api::Workers::Users::UnsubscribeAPI, options)
76
84
  end
77
85
 
86
+ def resubscribe!(options)
87
+ run_api(Vero::Api::Workers::Users::ResubscribeAPI, options)
88
+ end
89
+
78
90
  def reidentify!(options)
79
91
  run_api(Vero::Api::Workers::Users::ReidentifyAPI, options)
80
92
  end
93
+
94
+ def delete!(options)
95
+ run_api(Vero::Api::Workers::Users::DeleteAPI, options)
96
+ end
81
97
  end
82
98
  end
83
99
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'rest-client'
3
5
 
@@ -5,16 +7,17 @@ module Vero
5
7
  module Api
6
8
  module Workers
7
9
  class BaseAPI
8
- attr_accessor :domain, :options
10
+ attr_accessor :domain
11
+ attr_reader :options
9
12
 
10
13
  def self.perform(domain, options)
11
- caller = self.new(domain, options)
14
+ caller = new(domain, options)
12
15
  caller.perform
13
16
  end
14
17
 
15
18
  def initialize(domain, options)
16
19
  @domain = domain
17
- @options = options
20
+ self.options = options
18
21
  setup_logging
19
22
  end
20
23
 
@@ -28,6 +31,7 @@ module Vero
28
31
  end
29
32
 
30
33
  protected
34
+
31
35
  def setup_logging
32
36
  return unless Vero::App.logger
33
37
 
@@ -38,18 +42,16 @@ module Vero
38
42
  end
39
43
  end
40
44
 
41
- def url
42
- end
45
+ def url; end
43
46
 
44
47
  def validate!
45
48
  raise "#{self.class.name}#validate! should be overridden"
46
49
  end
47
50
 
48
- def request
49
- end
51
+ def request; end
50
52
 
51
53
  def request_content_type
52
- {:content_type => :json, :accept => :json}
54
+ { content_type: :json, accept: :json }
53
55
  end
54
56
 
55
57
  def request_params_as_json
@@ -57,12 +59,11 @@ module Vero
57
59
  end
58
60
 
59
61
  def options_with_symbolized_keys(val)
60
- val.inject({}) do |h,(k,v)|
62
+ val.each_with_object({}) do |(k, v), h|
61
63
  h[k.to_sym] = v
62
- h
63
64
  end
64
65
  end
65
66
  end
66
67
  end
67
68
  end
68
- end
69
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
4
  module Api
3
5
  module Workers
@@ -8,12 +10,12 @@ module Vero
8
10
  end
9
11
 
10
12
  def request
11
- RestClient.post(self.url, self.request_params_as_json, self.request_content_type)
13
+ RestClient.post(url, request_params_as_json, request_content_type)
12
14
  end
13
15
 
14
16
  def validate!
15
- raise ArgumentError.new("Missing :event_name") if options[:event_name].to_s.blank?
16
- raise ArgumentError.new(":data must be either nil or a Hash") unless (options[:data].nil? || options[:data].is_a?(Hash))
17
+ raise ArgumentError, 'Missing :event_name' if options[:event_name].to_s.blank?
18
+ raise ArgumentError, ':data must be either nil or a Hash' unless options[:data].nil? || options[:data].is_a?(Hash)
17
19
  end
18
20
  end
19
21
  end
@@ -0,0 +1,21 @@
1
+ module Vero
2
+ module Api
3
+ module Workers
4
+ module Users
5
+ class DeleteAPI < BaseAPI
6
+ def url
7
+ "#{@domain}/api/v2/users/delete.json"
8
+ end
9
+
10
+ def request
11
+ RestClient.post(url, @options)
12
+ end
13
+
14
+ def validate!
15
+ raise ArgumentError.new("Missing :id") if options[:id].to_s.blank?
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
4
  module Api
3
5
  module Workers
@@ -8,12 +10,12 @@ module Vero
8
10
  end
9
11
 
10
12
  def request
11
- RestClient.put(url, self.request_params_as_json, self.request_content_type)
13
+ RestClient.put(url, request_params_as_json, request_content_type)
12
14
  end
13
15
 
14
16
  def validate!
15
- raise ArgumentError.new("Missing :id or :email") if options[:id].to_s.blank? && options[:email].to_s.blank?
16
- raise ArgumentError.new(":changes must be a Hash") unless options[:changes].is_a?(Hash)
17
+ raise ArgumentError, 'Missing :id or :email' if options[:id].to_s.blank? && options[:email].to_s.blank?
18
+ raise ArgumentError, ':changes must be a Hash' unless options[:changes].is_a?(Hash)
17
19
  end
18
20
  end
19
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
4
  module Api
3
5
  module Workers
@@ -8,14 +10,14 @@ module Vero
8
10
  end
9
11
 
10
12
  def request
11
- RestClient.put(url, self.request_params_as_json, self.request_content_type)
13
+ RestClient.put(url, request_params_as_json, request_content_type)
12
14
  end
13
15
 
14
16
  def validate!
15
- raise ArgumentError.new("Missing :id or :email") if options[:id].to_s.blank? && options[:email].to_s.blank?
16
- raise ArgumentError.new(":add must an Array if present") unless options[:add].nil? || options[:add].is_a?(Array)
17
- raise ArgumentError.new(":remove must an Array if present") unless options[:remove].nil? || options[:remove].is_a?(Array)
18
- raise ArgumentError.new("Either :add or :remove must be present") if (options[:remove].nil? && options[:add].nil?)
17
+ raise ArgumentError, 'Missing :id or :email' if options[:id].to_s.blank? && options[:email].to_s.blank?
18
+ raise ArgumentError, ':add must an Array if present' unless options[:add].nil? || options[:add].is_a?(Array)
19
+ raise ArgumentError, ':remove must an Array if present' unless options[:remove].nil? || options[:remove].is_a?(Array)
20
+ raise ArgumentError, 'Either :add or :remove must be present' if options[:remove].nil? && options[:add].nil?
19
21
  end
20
22
  end
21
23
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
4
  module Api
3
5
  module Workers
@@ -8,12 +10,12 @@ module Vero
8
10
  end
9
11
 
10
12
  def request
11
- RestClient.put(url, self.request_params_as_json, self.request_content_type)
13
+ RestClient.put(url, request_params_as_json, request_content_type)
12
14
  end
13
15
 
14
16
  def validate!
15
- raise ArgumentError.new("Missing :id") if options[:id].to_s.blank?
16
- raise ArgumentError.new("Missing :new_id") if options[:new_id].to_s.blank?
17
+ raise ArgumentError, 'Missing :id' if options[:id].to_s.blank?
18
+ raise ArgumentError, 'Missing :new_id' if options[:new_id].to_s.blank?
17
19
  end
18
20
  end
19
21
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Vero
4
+ module Api
5
+ module Workers
6
+ module Users
7
+ class ResubscribeAPI < BaseAPI
8
+ def url
9
+ "#{@domain}/api/v2/users/resubscribe.json"
10
+ end
11
+
12
+ def request
13
+ RestClient.post(url, @options)
14
+ end
15
+
16
+ def validate!
17
+ raise ArgumentError, 'Missing :id or :email' if options[:id].to_s.blank? && options[:email].to_s.blank?
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
4
  module Api
3
5
  module Workers
@@ -8,12 +10,12 @@ module Vero
8
10
  end
9
11
 
10
12
  def request
11
- RestClient.post(url, self.request_params_as_json, self.request_content_type)
13
+ RestClient.post(url, request_params_as_json, request_content_type)
12
14
  end
13
15
 
14
16
  def validate!
15
- raise ArgumentError.new("Missing :id or :email") if options[:id].to_s.blank? && options[:email].to_s.blank?
16
- raise ArgumentError.new(":data must be either nil or a Hash") unless (options[:data].nil? || options[:data].is_a?(Hash))
17
+ raise ArgumentError, 'Missing :id or :email' if options[:id].to_s.blank? && options[:email].to_s.blank?
18
+ raise ArgumentError, ':data must be either nil or a Hash' unless options[:data].nil? || options[:data].is_a?(Hash)
17
19
  end
18
20
  end
19
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
4
  module Api
3
5
  module Workers
@@ -12,7 +14,7 @@ module Vero
12
14
  end
13
15
 
14
16
  def validate!
15
- raise ArgumentError.new("Missing :id or :email") if options[:id].to_s.blank? && options[:email].to_s.blank?
17
+ raise ArgumentError, 'Missing :id or :email' if options[:id].to_s.blank? && options[:email].to_s.blank?
16
18
  end
17
19
  end
18
20
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Vero
2
4
  class App
3
5
  include Vero::Utility::Logger
4
6
 
5
7
  def self.default_context
6
- @@default_context ||= Context.new
8
+ @@default_context ||= Context.new # rubocop:disable Style/ClassVars
7
9
  end
8
10
 
9
11
  def self.init(&block)
@@ -22,4 +24,4 @@ module Vero
22
24
  default_context.configured?
23
25
  end
24
26
  end
25
- end
27
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
 
3
5
  module Vero
@@ -6,39 +8,36 @@ module Vero
6
8
  attr_accessor :api_key, :secret, :development_mode, :async, :disabled, :logging
7
9
 
8
10
  def self.available_attributes
9
- [:api_key, :secret, :development_mode, :async, :disabled, :logging, :domain]
11
+ %i[api_key secret development_mode async disabled logging domain]
10
12
  end
11
13
 
12
14
  def initialize
13
- self.reset!
15
+ reset!
14
16
  end
15
17
 
16
18
  def config_params
17
- options = {:api_key => self.api_key, :secret => self.secret}
19
+ { api_key: api_key, secret: secret }
18
20
  end
19
21
 
20
22
  def request_params
21
- [:auth_token, :development_mode].inject({}) do |h, symbol|
22
- method_name = "from_#{symbol}".to_sym
23
- if respond_to?(symbol)
24
- temp = send(symbol)
25
- h[symbol] = temp unless temp.blank?
26
- end
27
- h
28
- end
23
+ {
24
+ auth_token: auth_token,
25
+ development_mode: development_mode
26
+ }.reject { |_, v| v.nil? }
29
27
  end
30
28
 
31
29
  def domain
32
30
  if @domain.blank?
33
31
  'https://api.getvero.com'
34
32
  else
35
- @domain =~ /http[s]?\:\/\/.+/ ? @domain : "http://#{@domain}"
33
+ @domain =~ %r{https?://.+} ? @domain : "http://#{@domain}"
36
34
  end
37
35
  end
38
36
 
39
37
  def auth_token
40
38
  return unless auth_token?
41
- ::Base64::encode64("#{api_key}:#{secret}").gsub(/[\n ]/, '')
39
+
40
+ ::Base64.encode64("#{api_key}:#{secret}").gsub(/[\n ]/, '')
42
41
  end
43
42
 
44
43
  def auth_token?
@@ -60,10 +59,6 @@ module Vero
60
59
  self.logging = false
61
60
  self.api_key = nil
62
61
  self.secret = nil
63
-
64
- if defined?(Rails)
65
- self.development_mode = !Rails.env.production?
66
- end
67
62
  end
68
63
 
69
64
  def update_attributes(attributes = {})
@@ -71,8 +66,8 @@ module Vero
71
66
 
72
67
  Vero::Config.available_attributes.each do |symbol|
73
68
  method_name = "#{symbol}=".to_sym
74
- self.send(method_name, attributes[symbol]) if self.respond_to?(method_name) && attributes.has_key?(symbol)
69
+ send(method_name, attributes[symbol]) if respond_to?(method_name) && attributes.key?(symbol)
75
70
  end
76
71
  end
77
72
  end
78
- end
73
+ end