From 8650a421a65d2c485da9367b24c523a68f8df980 Mon Sep 17 00:00:00 2001 From: James Lamont <958588+jylamont@users.noreply.github.com> Date: Mon, 6 Jan 2025 18:31:10 -0500 Subject: [PATCH] improve: Zeitwerk --- lib/vero.rb | 68 ++++--------- lib/vero/api.rb | 99 ------------------- lib/vero/api/base.rb | 27 +++++ lib/vero/api/base_api.rb | 71 ------------- lib/vero/api/events.rb | 11 +++ lib/vero/api/events/track_api.rb | 24 ----- lib/vero/api/users.rb | 57 +++++++++++ lib/vero/api/users/delete_api.rb | 23 ----- lib/vero/api/users/edit_api.rb | 24 ----- lib/vero/api/users/edit_tags_api.rb | 26 ----- lib/vero/api/users/reidentify_api.rb | 24 ----- lib/vero/api/users/resubscribe_api.rb | 23 ----- lib/vero/api/users/track_api.rb | 24 ----- lib/vero/api/users/unsubscribe_api.rb | 23 ----- lib/vero/api/workers/base_api.rb | 64 ++++++++++++ lib/vero/api/workers/events/track_api.rb | 16 +++ lib/vero/api/workers/users/delete_api.rb | 15 +++ lib/vero/api/workers/users/edit_api.rb | 16 +++ lib/vero/api/workers/users/edit_tags_api.rb | 18 ++++ lib/vero/api/workers/users/reidentify_api.rb | 16 +++ lib/vero/api/workers/users/resubscribe_api.rb | 15 +++ lib/vero/api/workers/users/track_api.rb | 16 +++ lib/vero/api/workers/users/unsubscribe_api.rb | 15 +++ lib/vero/api_context.rb | 38 +++++++ lib/vero/app.rb | 34 +++---- lib/vero/config.rb | 90 ++++++++--------- lib/vero/context.rb | 65 ++++++------ lib/vero/context/api.rb | 40 -------- lib/vero/dsl.rb | 54 +++++----- lib/vero/railtie.rb | 4 +- lib/vero/resque_worker.rb | 16 +++ lib/vero/sender.rb | 2 - lib/vero/senders/base.rb | 18 ++-- lib/vero/senders/delayed_job.rb | 23 ++--- lib/vero/senders/invalid.rb | 10 +- lib/vero/senders/resque.rb | 28 +----- lib/vero/senders/sidekiq.rb | 28 +----- lib/vero/senders/sucker_punch.rb | 31 +----- lib/vero/sidekiq_worker.rb | 12 +++ lib/vero/sucker_punch_worker.rb | 19 ++++ lib/vero/trackable.rb | 3 - lib/vero/trackable/interface.rb | 22 ++--- lib/vero/utility/logger.rb | 36 +++---- spec/spec_helper.rb | 2 +- vero.gemspec | 1 + 45 files changed, 564 insertions(+), 727 deletions(-) delete mode 100644 lib/vero/api.rb create mode 100644 lib/vero/api/base.rb delete mode 100644 lib/vero/api/base_api.rb create mode 100644 lib/vero/api/events.rb delete mode 100644 lib/vero/api/events/track_api.rb create mode 100644 lib/vero/api/users.rb delete mode 100644 lib/vero/api/users/delete_api.rb delete mode 100644 lib/vero/api/users/edit_api.rb delete mode 100644 lib/vero/api/users/edit_tags_api.rb delete mode 100644 lib/vero/api/users/reidentify_api.rb delete mode 100644 lib/vero/api/users/resubscribe_api.rb delete mode 100644 lib/vero/api/users/track_api.rb delete mode 100644 lib/vero/api/users/unsubscribe_api.rb create mode 100644 lib/vero/api/workers/base_api.rb create mode 100644 lib/vero/api/workers/events/track_api.rb create mode 100644 lib/vero/api/workers/users/delete_api.rb create mode 100644 lib/vero/api/workers/users/edit_api.rb create mode 100644 lib/vero/api/workers/users/edit_tags_api.rb create mode 100644 lib/vero/api/workers/users/reidentify_api.rb create mode 100644 lib/vero/api/workers/users/resubscribe_api.rb create mode 100644 lib/vero/api/workers/users/track_api.rb create mode 100644 lib/vero/api/workers/users/unsubscribe_api.rb create mode 100644 lib/vero/api_context.rb delete mode 100644 lib/vero/context/api.rb create mode 100644 lib/vero/resque_worker.rb create mode 100644 lib/vero/sidekiq_worker.rb create mode 100644 lib/vero/sucker_punch_worker.rb diff --git a/lib/vero.rb b/lib/vero.rb index f22b2ac..8a21314 100644 --- a/lib/vero.rb +++ b/lib/vero.rb @@ -1,54 +1,24 @@ # frozen_string_literal: true +require "base64" +require "json" require "rest-client" - -module Vero - autoload :Config, "vero/config" - autoload :App, "vero/app" - autoload :Context, "vero/context" - autoload :APIContext, "vero/context/api" - autoload :Trackable, "vero/trackable" - autoload :DSL, "vero/dsl" - autoload :Sender, "vero/sender" - autoload :SuckerPunchWorker, "vero/senders/sucker_punch" - autoload :ResqueWorker, "vero/senders/resque" - autoload :SidekiqWorker, "vero/senders/sidekiq" - - module Api - module Workers - autoload :BaseAPI, "vero/api/base_api" - - module Events - autoload :TrackAPI, "vero/api/events/track_api" - end - - module Users - autoload :TrackAPI, "vero/api/users/track_api" - autoload :EditAPI, "vero/api/users/edit_api" - autoload :EditTagsAPI, "vero/api/users/edit_tags_api" - autoload :UnsubscribeAPI, "vero/api/users/unsubscribe_api" - autoload :ResubscribeAPI, "vero/api/users/resubscribe_api" - autoload :ReidentifyAPI, "vero/api/users/reidentify_api" - autoload :DeleteAPI, "vero/api/users/delete_api" - end - end - - autoload :Events, "vero/api" - autoload :Users, "vero/api" - end - - module Senders - autoload :Base, "vero/senders/base" - autoload :DelayedJob, "vero/senders/delayed_job" - autoload :Resque, "vero/senders/resque" - autoload :Sidekiq, "vero/senders/sidekiq" - autoload :Invalid, "vero/senders/invalid" - autoload :SuckerPunch, "vero/senders/sucker_punch" - end - - module Utility - autoload :Logger, "vero/utility/logger" - end -end +require "zeitwerk" + +loader = Zeitwerk::Loader.for_gem +loader.inflector.inflect( + "api_context" => "APIContext", + "dsl" => "DSL", + "base_api" => "BaseAPI", + "track_api" => "TrackAPI", + "delete_api" => "DeleteAPI", + "edit_api" => "EditAPI", + "edit_tags_api" => "EditTagsAPI", + "reidentify_api" => "ReidentifyAPI", + "resubscribe_api" => "ResubscribeAPI", + "unsubscribe_api" => "UnsubscribeAPI" +) +loader.ignore("#{__dir__}/generators") +loader.setup require "vero/railtie" if defined?(Rails) diff --git a/lib/vero/api.rb b/lib/vero/api.rb deleted file mode 100644 index ffe2302..0000000 --- a/lib/vero/api.rb +++ /dev/null @@ -1,99 +0,0 @@ -# frozen_string_literal: true - -module Vero - module Api - class Base - attr_accessor :context - - def initialize(context) - self.context = context - end - - def config - context.config - end - - def run_api(api_klass, options) - return if config.disabled - - validate_configured! - options.merge!(config.request_params) - Vero::Sender.send(api_klass, config.async, config.domain, options) - end - - protected - - def validate_configured! - raise "You must configure the 'vero' gem. Visit https://github.com/getvero/vero for more details." unless config.configured? - end - end - - class Events < Base - def self.track!(options, context = Vero::App.default_context) - new(context).track!(options) - end - - def track!(options) - run_api(Vero::Api::Workers::Events::TrackAPI, options) - end - end - - class Users < Base - def self.track!(options, context = Vero::App.default_context) - new(context).track!(options) - end - - def self.edit_user!(options, context = Vero::App.default_context) - new(context).edit_user!(options) - end - - def self.edit_user_tags!(options, context = Vero::App.default_context) - new(context).edit_user_tags!(options) - end - - def self.reidentify!(options, context = Vero::App.default_context) - new(context).reidentify!(options) - end - - def self.unsubscribe!(options, context = Vero::App.default_context) - new(context).unsubscribe!(options) - end - - def self.resubscribe!(options, context = Vero::App.default_context) - new(context).resubscribe!(options) - end - - def self.delete!(options, context = Vero::App.default_context) - new(context).delete!(options) - end - - def track!(options) - run_api(Vero::Api::Workers::Users::TrackAPI, options) - end - - def edit_user!(options) - run_api(Vero::Api::Workers::Users::EditAPI, options) - end - - def edit_user_tags!(options) - run_api(Vero::Api::Workers::Users::EditTagsAPI, options) - end - - def unsubscribe!(options) - run_api(Vero::Api::Workers::Users::UnsubscribeAPI, options) - end - - def resubscribe!(options) - run_api(Vero::Api::Workers::Users::ResubscribeAPI, options) - end - - def reidentify!(options) - run_api(Vero::Api::Workers::Users::ReidentifyAPI, options) - end - - def delete!(options) - run_api(Vero::Api::Workers::Users::DeleteAPI, options) - end - end - end -end diff --git a/lib/vero/api/base.rb b/lib/vero/api/base.rb new file mode 100644 index 0000000..ba35b44 --- /dev/null +++ b/lib/vero/api/base.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class Vero::Api::Base + attr_accessor :context + + def initialize(context) + self.context = context + end + + def config + context.config + end + + def run_api(api_klass, options) + return if config.disabled + + validate_configured! + options.merge!(config.request_params) + Vero::Sender.send(api_klass, config.async, config.domain, options) + end + + protected + + def validate_configured! + raise "You must configure the 'vero' gem. Visit https://github.com/getvero/vero for more details." unless config.configured? + end +end diff --git a/lib/vero/api/base_api.rb b/lib/vero/api/base_api.rb deleted file mode 100644 index e886e7c..0000000 --- a/lib/vero/api/base_api.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -require "json" -require "rest-client" - -module Vero - module Api - module Workers - class BaseAPI - attr_accessor :domain - attr_reader :options - - def self.perform(domain, options) - caller = new(domain, options) - caller.perform - end - - def initialize(domain, options) - @domain = domain - self.options = options - setup_logging - end - - def perform - validate! - request - end - - def options=(val) - @options = options_with_symbolized_keys(val) - end - - protected - - def setup_logging - return unless Vero::App.logger - - RestClient.log = Object.new.tap do |proxy| - def proxy.<<(message) - Vero::App.logger.info message - end - end - end - - def url - end - - def validate! - raise "#{self.class.name}#validate! should be overridden" - end - - def request - end - - def request_content_type - {content_type: :json, accept: :json} - end - - def request_params_as_json - JSON.dump(@options) - end - - def options_with_symbolized_keys(val) - val.each_with_object({}) do |(k, v), h| - h[k.to_sym] = v - end - end - end - end - end -end diff --git a/lib/vero/api/events.rb b/lib/vero/api/events.rb new file mode 100644 index 0000000..20d74ff --- /dev/null +++ b/lib/vero/api/events.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class Vero::Api::Events < Vero::Api::Base + def self.track!(options, context = Vero::App.default_context) + new(context).track!(options) + end + + def track!(options) + run_api(Vero::Api::Workers::Events::TrackAPI, options) + end +end diff --git a/lib/vero/api/events/track_api.rb b/lib/vero/api/events/track_api.rb deleted file mode 100644 index b06d482..0000000 --- a/lib/vero/api/events/track_api.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -module Vero - module Api - module Workers - module Events - class TrackAPI < BaseAPI - def url - "#{@domain}/api/v2/events/track.json" - end - - def request - RestClient.post(url, request_params_as_json, request_content_type) - end - - def validate! - raise ArgumentError, "Missing :event_name" if options[:event_name].to_s.empty? - raise ArgumentError, ":data must be either nil or a Hash" unless options[:data].nil? || options[:data].is_a?(Hash) - end - end - end - end - end -end diff --git a/lib/vero/api/users.rb b/lib/vero/api/users.rb new file mode 100644 index 0000000..ef59b1d --- /dev/null +++ b/lib/vero/api/users.rb @@ -0,0 +1,57 @@ +class Vero::Api::Users < Vero::Api::Base + def self.track!(options, context = Vero::App.default_context) + new(context).track!(options) + end + + def self.edit_user!(options, context = Vero::App.default_context) + new(context).edit_user!(options) + end + + def self.edit_user_tags!(options, context = Vero::App.default_context) + new(context).edit_user_tags!(options) + end + + def self.reidentify!(options, context = Vero::App.default_context) + new(context).reidentify!(options) + end + + def self.unsubscribe!(options, context = Vero::App.default_context) + new(context).unsubscribe!(options) + end + + def self.resubscribe!(options, context = Vero::App.default_context) + new(context).resubscribe!(options) + end + + def self.delete!(options, context = Vero::App.default_context) + new(context).delete!(options) + end + + def track!(options) + run_api(Vero::Api::Workers::Users::TrackAPI, options) + end + + def edit_user!(options) + run_api(Vero::Api::Workers::Users::EditAPI, options) + end + + def edit_user_tags!(options) + run_api(Vero::Api::Workers::Users::EditTagsAPI, options) + end + + def unsubscribe!(options) + run_api(Vero::Api::Workers::Users::UnsubscribeAPI, options) + end + + def resubscribe!(options) + run_api(Vero::Api::Workers::Users::ResubscribeAPI, options) + end + + def reidentify!(options) + run_api(Vero::Api::Workers::Users::ReidentifyAPI, options) + end + + def delete!(options) + run_api(Vero::Api::Workers::Users::DeleteAPI, options) + end +end diff --git a/lib/vero/api/users/delete_api.rb b/lib/vero/api/users/delete_api.rb deleted file mode 100644 index 23727f5..0000000 --- a/lib/vero/api/users/delete_api.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Vero - module Api - module Workers - module Users - class DeleteAPI < BaseAPI - def url - "#{@domain}/api/v2/users/delete.json" - end - - def request - RestClient.post(url, @options) - end - - def validate! - raise ArgumentError, "Missing :id" if options[:id].to_s.empty? - end - end - end - end - end -end diff --git a/lib/vero/api/users/edit_api.rb b/lib/vero/api/users/edit_api.rb deleted file mode 100644 index 54dcafb..0000000 --- a/lib/vero/api/users/edit_api.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -module Vero - module Api - module Workers - module Users - class EditAPI < BaseAPI - def url - "#{@domain}/api/v2/users/edit.json" - end - - def request - RestClient.put(url, request_params_as_json, request_content_type) - end - - def validate! - raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? - raise ArgumentError, ":changes must be a Hash" unless options[:changes].is_a?(Hash) - end - end - end - end - end -end diff --git a/lib/vero/api/users/edit_tags_api.rb b/lib/vero/api/users/edit_tags_api.rb deleted file mode 100644 index 37463d5..0000000 --- a/lib/vero/api/users/edit_tags_api.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -module Vero - module Api - module Workers - module Users - class EditTagsAPI < BaseAPI - def url - "#{@domain}/api/v2/users/tags/edit.json" - end - - def request - RestClient.put(url, request_params_as_json, request_content_type) - end - - def validate! - raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? - raise ArgumentError, ":add must an Array if present" unless options[:add].nil? || options[:add].is_a?(Array) - raise ArgumentError, ":remove must an Array if present" unless options[:remove].nil? || options[:remove].is_a?(Array) - raise ArgumentError, "Either :add or :remove must be present" if options[:remove].nil? && options[:add].nil? - end - end - end - end - end -end diff --git a/lib/vero/api/users/reidentify_api.rb b/lib/vero/api/users/reidentify_api.rb deleted file mode 100644 index 0c49949..0000000 --- a/lib/vero/api/users/reidentify_api.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -module Vero - module Api - module Workers - module Users - class ReidentifyAPI < BaseAPI - def url - "#{@domain}/api/v2/users/reidentify.json" - end - - def request - RestClient.put(url, request_params_as_json, request_content_type) - end - - def validate! - raise ArgumentError, "Missing :id" if options[:id].to_s.empty? - raise ArgumentError, "Missing :new_id" if options[:new_id].to_s.empty? - end - end - end - end - end -end diff --git a/lib/vero/api/users/resubscribe_api.rb b/lib/vero/api/users/resubscribe_api.rb deleted file mode 100644 index 8dca017..0000000 --- a/lib/vero/api/users/resubscribe_api.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Vero - module Api - module Workers - module Users - class ResubscribeAPI < BaseAPI - def url - "#{@domain}/api/v2/users/resubscribe.json" - end - - def request - RestClient.post(url, @options) - end - - def validate! - raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? - end - end - end - end - end -end diff --git a/lib/vero/api/users/track_api.rb b/lib/vero/api/users/track_api.rb deleted file mode 100644 index 8158036..0000000 --- a/lib/vero/api/users/track_api.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -module Vero - module Api - module Workers - module Users - class TrackAPI < BaseAPI - def url - "#{@domain}/api/v2/users/track.json" - end - - def request - RestClient.post(url, request_params_as_json, request_content_type) - end - - def validate! - raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? - raise ArgumentError, ":data must be either nil or a Hash" unless options[:data].nil? || options[:data].is_a?(Hash) - end - end - end - end - end -end diff --git a/lib/vero/api/users/unsubscribe_api.rb b/lib/vero/api/users/unsubscribe_api.rb deleted file mode 100644 index ba2bc1c..0000000 --- a/lib/vero/api/users/unsubscribe_api.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Vero - module Api - module Workers - module Users - class UnsubscribeAPI < BaseAPI - def url - "#{@domain}/api/v2/users/unsubscribe.json" - end - - def request - RestClient.post(url, @options) - end - - def validate! - raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? - end - end - end - end - end -end diff --git a/lib/vero/api/workers/base_api.rb b/lib/vero/api/workers/base_api.rb new file mode 100644 index 0000000..7482236 --- /dev/null +++ b/lib/vero/api/workers/base_api.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require "rest-client" + +class Vero::Api::Workers::BaseAPI + attr_accessor :domain + attr_reader :options + + def self.perform(domain, options) + caller = new(domain, options) + caller.perform + end + + def initialize(domain, options) + @domain = domain + self.options = options + setup_logging + end + + def perform + validate! + request + end + + def options=(val) + @options = options_with_symbolized_keys(val) + end + + protected + + def setup_logging + return unless Vero::App.logger + + RestClient.log = Object.new.tap do |proxy| + def proxy.<<(message) + Vero::App.logger.info message + end + end + end + + def url + end + + def validate! + raise "#{self.class.name}#validate! should be overridden" + end + + def request + end + + def request_content_type + {content_type: :json, accept: :json} + end + + def request_params_as_json + JSON.dump(@options) + end + + def options_with_symbolized_keys(val) + val.each_with_object({}) do |(k, v), h| + h[k.to_sym] = v + end + end +end diff --git a/lib/vero/api/workers/events/track_api.rb b/lib/vero/api/workers/events/track_api.rb new file mode 100644 index 0000000..001d74e --- /dev/null +++ b/lib/vero/api/workers/events/track_api.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class Vero::Api::Workers::Events::TrackAPI < Vero::Api::Workers::BaseAPI + def url + "#{@domain}/api/v2/events/track.json" + end + + def request + RestClient.post(url, request_params_as_json, request_content_type) + end + + def validate! + raise ArgumentError, "Missing :event_name" if options[:event_name].to_s.empty? + raise ArgumentError, ":data must be either nil or a Hash" unless options[:data].nil? || options[:data].is_a?(Hash) + end +end diff --git a/lib/vero/api/workers/users/delete_api.rb b/lib/vero/api/workers/users/delete_api.rb new file mode 100644 index 0000000..552496d --- /dev/null +++ b/lib/vero/api/workers/users/delete_api.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class Vero::Api::Workers::Users::DeleteAPI < Vero::Api::Workers::BaseAPI + def url + "#{@domain}/api/v2/users/delete.json" + end + + def request + RestClient.post(url, @options) + end + + def validate! + raise ArgumentError, "Missing :id" if options[:id].to_s.empty? + end +end diff --git a/lib/vero/api/workers/users/edit_api.rb b/lib/vero/api/workers/users/edit_api.rb new file mode 100644 index 0000000..508bae9 --- /dev/null +++ b/lib/vero/api/workers/users/edit_api.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class Vero::Api::Workers::Users::EditAPI < Vero::Api::Workers::BaseAPI + def url + "#{@domain}/api/v2/users/edit.json" + end + + def request + RestClient.put(url, request_params_as_json, request_content_type) + end + + def validate! + raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? + raise ArgumentError, ":changes must be a Hash" unless options[:changes].is_a?(Hash) + end +end diff --git a/lib/vero/api/workers/users/edit_tags_api.rb b/lib/vero/api/workers/users/edit_tags_api.rb new file mode 100644 index 0000000..64e6eba --- /dev/null +++ b/lib/vero/api/workers/users/edit_tags_api.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class Vero::Api::Workers::Users::EditTagsAPI < Vero::Api::Workers::BaseAPI + def url + "#{@domain}/api/v2/users/tags/edit.json" + end + + def request + RestClient.put(url, request_params_as_json, request_content_type) + end + + def validate! + raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? + raise ArgumentError, ":add must an Array if present" unless options[:add].nil? || options[:add].is_a?(Array) + raise ArgumentError, ":remove must an Array if present" unless options[:remove].nil? || options[:remove].is_a?(Array) + raise ArgumentError, "Either :add or :remove must be present" if options[:remove].nil? && options[:add].nil? + end +end diff --git a/lib/vero/api/workers/users/reidentify_api.rb b/lib/vero/api/workers/users/reidentify_api.rb new file mode 100644 index 0000000..cec0edd --- /dev/null +++ b/lib/vero/api/workers/users/reidentify_api.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class Vero::Api::Workers::Users::ReidentifyAPI < Vero::Api::Workers::BaseAPI + def url + "#{@domain}/api/v2/users/reidentify.json" + end + + def request + RestClient.put(url, request_params_as_json, request_content_type) + end + + def validate! + raise ArgumentError, "Missing :id" if options[:id].to_s.empty? + raise ArgumentError, "Missing :new_id" if options[:new_id].to_s.empty? + end +end diff --git a/lib/vero/api/workers/users/resubscribe_api.rb b/lib/vero/api/workers/users/resubscribe_api.rb new file mode 100644 index 0000000..11c4d17 --- /dev/null +++ b/lib/vero/api/workers/users/resubscribe_api.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class Vero::Api::Workers::Users::ResubscribeAPI < Vero::Api::Workers::BaseAPI + def url + "#{@domain}/api/v2/users/resubscribe.json" + end + + def request + RestClient.post(url, @options) + end + + def validate! + raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? + end +end diff --git a/lib/vero/api/workers/users/track_api.rb b/lib/vero/api/workers/users/track_api.rb new file mode 100644 index 0000000..fff7650 --- /dev/null +++ b/lib/vero/api/workers/users/track_api.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class Vero::Api::Workers::Users::TrackAPI < Vero::Api::Workers::BaseAPI + def url + "#{@domain}/api/v2/users/track.json" + end + + def request + RestClient.post(url, request_params_as_json, request_content_type) + end + + def validate! + raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? + raise ArgumentError, ":data must be either nil or a Hash" unless options[:data].nil? || options[:data].is_a?(Hash) + end +end diff --git a/lib/vero/api/workers/users/unsubscribe_api.rb b/lib/vero/api/workers/users/unsubscribe_api.rb new file mode 100644 index 0000000..b3f293b --- /dev/null +++ b/lib/vero/api/workers/users/unsubscribe_api.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class Vero::Api::Workers::Users::UnsubscribeAPI < Vero::Api::Workers::BaseAPI + def url + "#{@domain}/api/v2/users/unsubscribe.json" + end + + def request + RestClient.post(url, @options) + end + + def validate! + raise ArgumentError, "Missing :id or :email" if options[:id].to_s.empty? && options[:email].to_s.empty? + end +end diff --git a/lib/vero/api_context.rb b/lib/vero/api_context.rb new file mode 100644 index 0000000..95e0a19 --- /dev/null +++ b/lib/vero/api_context.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Vero::APIContext + def track!(event_name, event_data, extras = {}) + options = {data: event_data, event_name: event_name, identity: subject.to_vero, extras: extras} + Vero::Api::Events.track!(options, self) + end + + def identify! + identity = subject.to_vero + options = {id: identity[:id], email: identity[:email], data: identity} + Vero::Api::Users.track!(options, self) + end + + def update_user! + identity = subject.to_vero + options = {id: identity[:id], email: identity[:email], changes: identity} + Vero::Api::Users.edit_user!(options, self) + end + + def update_user_tags!(add = [], remove = []) + identity = subject.to_vero + options = {id: identity[:id], email: identity[:email], add: Array(add), remove: Array(remove)} + Vero::Api::Users.edit_user_tags!(options, self) + end + + def unsubscribe! + identity = subject.to_vero + options = {id: identity[:id], email: identity[:email]} + Vero::Api::Users.unsubscribe!(options, self) + end + + def reidentify!(previous_id) + identity = subject.to_vero + options = {id: previous_id, new_id: identity[:id]} + Vero::Api::Users.reidentify!(options, self) + end +end diff --git a/lib/vero/app.rb b/lib/vero/app.rb index 12dde8a..942eab3 100644 --- a/lib/vero/app.rb +++ b/lib/vero/app.rb @@ -1,27 +1,25 @@ # frozen_string_literal: true -module Vero - class App - include Vero::Utility::Logger +class Vero::App + include Vero::Utility::Logger - def self.default_context - @@default_context ||= Context.new # rubocop:disable Style/ClassVars - end + def self.default_context + @@default_context ||= Vero::Context.new # rubocop:disable Style/ClassVars + end - def self.init(&block) - default_context.configure(&block) if block - end + def self.init(&block) + default_context.configure(&block) if block + end - def self.reset! - default_context.reset! - end + def self.reset! + default_context.reset! + end - def self.disable_requests! - default_context.disable_requests! - end + def self.disable_requests! + default_context.disable_requests! + end - def self.configured? - default_context.configured? - end + def self.configured? + default_context.configured? end end diff --git a/lib/vero/config.rb b/lib/vero/config.rb index b14fdaa..d7ee2c7 100644 --- a/lib/vero/config.rb +++ b/lib/vero/config.rb @@ -1,63 +1,59 @@ # frozen_string_literal: true -require "base64" +class Vero::Config + attr_writer :domain + attr_accessor :tracking_api_key, :development_mode, :async, :disabled, :logging -module Vero - class Config - attr_writer :domain - attr_accessor :tracking_api_key, :development_mode, :async, :disabled, :logging - - def self.available_attributes - %i[tracking_api_key development_mode async disabled logging domain] - end + def self.available_attributes + %i[tracking_api_key development_mode async disabled logging domain] + end - def initialize - reset! - end + def initialize + reset! + end - def config_params - {tracking_api_key: tracking_api_key} - end + def config_params + {tracking_api_key: tracking_api_key} + end - def request_params - { - tracking_api_key: tracking_api_key, - development_mode: development_mode - }.compact - end + def request_params + { + tracking_api_key: tracking_api_key, + development_mode: development_mode + }.compact + end - def domain - if @domain.nil? || @domain.empty? - "https://api.getvero.com" - else - a_domain = @domain.to_s - %r{https?://.+}.match?(a_domain) ? a_domain : "http://#{a_domain}" - end + def domain + if @domain.nil? || @domain.empty? + "https://api.getvero.com" + else + a_domain = @domain.to_s + %r{https?://.+}.match?(a_domain) ? a_domain : "http://#{a_domain}" end + end - def configured? - !tracking_api_key.blank? - end + def configured? + !tracking_api_key.blank? + end - def disable_requests! - self.disabled = true - end + def disable_requests! + self.disabled = true + end - def reset! - self.disabled = false - self.development_mode = false - self.async = true - self.logging = false - self.tracking_api_key = nil - end + def reset! + self.disabled = false + self.development_mode = false + self.async = true + self.logging = false + self.tracking_api_key = nil + end - def update_attributes(attributes = {}) - return unless attributes.is_a?(Hash) + def update_attributes(attributes = {}) + return unless attributes.is_a?(Hash) - Vero::Config.available_attributes.each do |symbol| - method_name = "#{symbol}=" - send(method_name, attributes[symbol]) if respond_to?(method_name) && attributes.key?(symbol) - end + Vero::Config.available_attributes.each do |symbol| + method_name = "#{symbol}=" + send(method_name, attributes[symbol]) if respond_to?(method_name) && attributes.key?(symbol) end end end diff --git a/lib/vero/context.rb b/lib/vero/context.rb index e455d48..d0f2801 100644 --- a/lib/vero/context.rb +++ b/lib/vero/context.rb @@ -1,44 +1,43 @@ # frozen_string_literal: true -module Vero - class Context - include Vero::APIContext - attr_accessor :config, :subject - - def initialize(object = {}) - case object - when Hash - # stub - when Vero::Context - @config = object.config - @subject = object.subject - else - object = Vero::Config.available_attributes.each_with_object({}) do |symbol, hash| - hash[symbol] = object.respond_to?(symbol) ? object.send(symbol) : nil - end +class Vero::Context + include Vero::APIContext + + attr_accessor :config, :subject + + def initialize(object = {}) + case object + when Hash + # stub + when Vero::Context + @config = object.config + @subject = object.subject + else + object = Vero::Config.available_attributes.each_with_object({}) do |symbol, hash| + hash[symbol] = object.respond_to?(symbol) ? object.send(symbol) : nil end - return unless object.is_a?(Hash) - - @config = Vero::Config.new - configure(object) end + return unless object.is_a?(Hash) - def configure(hash = {}, &block) - @config.update_attributes(hash) if hash.is_a?(Hash) && hash.any? + @config = Vero::Config.new + configure(object) + end - block&.call(@config) - end + def configure(hash = {}, &block) + @config.update_attributes(hash) if hash.is_a?(Hash) && hash.any? - def reset! - @config.reset! - end + block&.call(@config) + end - def disable_requests! - @config.disable_requests! - end + def reset! + @config.reset! + end - def configured? - @config.configured? - end + def disable_requests! + @config.disable_requests! + end + + def configured? + @config.configured? end end diff --git a/lib/vero/context/api.rb b/lib/vero/context/api.rb deleted file mode 100644 index 07a3deb..0000000 --- a/lib/vero/context/api.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -module Vero - module APIContext - def track!(event_name, event_data, extras = {}) - options = {data: event_data, event_name: event_name, identity: subject.to_vero, extras: extras} - Vero::Api::Events.track!(options, self) - end - - def identify! - identity = subject.to_vero - options = {id: identity[:id], email: identity[:email], data: identity} - Vero::Api::Users.track!(options, self) - end - - def update_user! - identity = subject.to_vero - options = {id: identity[:id], email: identity[:email], changes: identity} - Vero::Api::Users.edit_user!(options, self) - end - - def update_user_tags!(add = [], remove = []) - identity = subject.to_vero - options = {id: identity[:id], email: identity[:email], add: Array(add), remove: Array(remove)} - Vero::Api::Users.edit_user_tags!(options, self) - end - - def unsubscribe! - identity = subject.to_vero - options = {id: identity[:id], email: identity[:email]} - Vero::Api::Users.unsubscribe!(options, self) - end - - def reidentify!(previous_id) - identity = subject.to_vero - options = {id: previous_id, new_id: identity[:id]} - Vero::Api::Users.reidentify!(options, self) - end - end -end diff --git a/lib/vero/dsl.rb b/lib/vero/dsl.rb index 2dfa20f..bcdcb0f 100644 --- a/lib/vero/dsl.rb +++ b/lib/vero/dsl.rb @@ -1,36 +1,34 @@ # frozen_string_literal: true -module Vero - ## - # A lightweight DSL for using the Vero API. You may find this desirable in - # your Rails controllers having decided not to mix the Vero gem directly into - # your models. - # - # Example usage: - # - # class UsersController < ApplicationController - # include Vero::DSL - # - # def update - # vero.users.track!({ ... }) - # end - # end - module DSL - def vero - @vero ||= Proxy.new - end +## +# A lightweight DSL for using the Vero API. You may find this desirable in +# your Rails controllers having decided not to mix the Vero gem directly into +# your models. +# +# Example usage: +# +# class UsersController < ApplicationController +# include Vero::DSL +# +# def update +# vero.users.track!({ ... }) +# end +# end +module Vero::DSL + def vero + @vero ||= Proxy.new + end - # :nodoc: - class Proxy - include Vero::Api + # :nodoc: + class Proxy + include Vero::Api - def users - Users - end + def users + Users + end - def events - Events - end + def events + Events end end end diff --git a/lib/vero/railtie.rb b/lib/vero/railtie.rb index 286b70b..7e0dd19 100644 --- a/lib/vero/railtie.rb +++ b/lib/vero/railtie.rb @@ -1,11 +1,9 @@ # frozen_string_literal: true -require "vero/view_helpers/javascript" - module Vero class Railtie < Rails::Railtie initializer "vero.view_helpers" do - ActionView::Base.include ViewHelpers::Javascript + ActionView::Base.include Vero::ViewHelpers::Javascript end end end diff --git a/lib/vero/resque_worker.rb b/lib/vero/resque_worker.rb new file mode 100644 index 0000000..6e8149a --- /dev/null +++ b/lib/vero/resque_worker.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require "resque" + +class Vero::ResqueWorker + @queue = :vero + + def self.perform(api_class, domain, options) + new_options = options.each_with_object({}) do |(k, v), o| + o[k.to_sym] = v + end + + api_class.constantize.new(domain, new_options).perform + Vero::App.log(self, "method: #{api_class}, options: #{options.to_json}, response: resque job queued") + end +end diff --git a/lib/vero/sender.rb b/lib/vero/sender.rb index 6321e13..839ed01 100644 --- a/lib/vero/sender.rb +++ b/lib/vero/sender.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "json" - module Vero class SenderLookup def [](key) diff --git a/lib/vero/senders/base.rb b/lib/vero/senders/base.rb index dbd8b25..217d7f7 100644 --- a/lib/vero/senders/base.rb +++ b/lib/vero/senders/base.rb @@ -1,16 +1,10 @@ # frozen_string_literal: true -require "json" - -module Vero - module Senders - class Base - def call(api_class, domain, options) - response = api_class.perform(domain, options) - options_s = JSON.dump(options) - Vero::App.log(self, "method: #{api_class.name}, options: #{options_s}, response: job performed") - response - end - end +class Vero::Senders::Base + def call(api_class, domain, options) + response = api_class.perform(domain, options) + options_s = JSON.dump(options) + Vero::App.log(self, "method: #{api_class.name}, options: #{options_s}, response: job performed") + response end end diff --git a/lib/vero/senders/delayed_job.rb b/lib/vero/senders/delayed_job.rb index ba67984..8e35f66 100644 --- a/lib/vero/senders/delayed_job.rb +++ b/lib/vero/senders/delayed_job.rb @@ -1,21 +1,16 @@ # frozen_string_literal: true -require "json" require "delayed_job" -module Vero - module Senders - class DelayedJob - def call(api_class, domain, options) - response = ::Delayed::Job.enqueue api_class.new(domain, options) - options_s = JSON.dump(options) - Vero::App.log(self, "method: #{api_class.name}, options: #{options_s}, response: delayed job queued") - response - rescue => e - 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'" +class Vero::Senders::DelayedJob + def call(api_class, domain, options) + response = ::Delayed::Job.enqueue api_class.new(domain, options) + options_s = JSON.dump(options) + Vero::App.log(self, "method: #{api_class.name}, options: #{options_s}, response: delayed job queued") + response + rescue => e + 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'" - raise e - end - end + raise e end end diff --git a/lib/vero/senders/invalid.rb b/lib/vero/senders/invalid.rb index 373a53b..bbb382f 100644 --- a/lib/vero/senders/invalid.rb +++ b/lib/vero/senders/invalid.rb @@ -1,11 +1,7 @@ # frozen_string_literal: true -module Vero - module Senders - class Invalid - def call(_api_class, _domain, _options) - 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." - end - end +class Vero::Senders::Invalid + def call(_api_class, _domain, _options) + 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." end end diff --git a/lib/vero/senders/resque.rb b/lib/vero/senders/resque.rb index 8421880..b34bcbf 100644 --- a/lib/vero/senders/resque.rb +++ b/lib/vero/senders/resque.rb @@ -1,27 +1,5 @@ -# frozen_string_literal: true - -require "json" -require "resque" - -module Vero - class ResqueWorker - @queue = :vero - - def self.perform(api_class, domain, options) - new_options = options.each_with_object({}) do |(k, v), o| - o[k.to_sym] = v - end - - api_class.constantize.new(domain, new_options).perform - Vero::App.log(self, "method: #{api_class}, options: #{options.to_json}, response: resque job queued") - end - end - - module Senders - class Resque - def call(api_class, domain, options) - ::Resque.enqueue(ResqueWorker, api_class.to_s, domain, options) - end - end +class Vero::Senders::Resque + def call(api_class, domain, options) + ::Resque.enqueue(::Vero::ResqueWorker, api_class.to_s, domain, options) end end diff --git a/lib/vero/senders/sidekiq.rb b/lib/vero/senders/sidekiq.rb index ac13933..87482c9 100644 --- a/lib/vero/senders/sidekiq.rb +++ b/lib/vero/senders/sidekiq.rb @@ -1,25 +1,7 @@ -# frozen_string_literal: true - -require "json" -require "sidekiq" - -module Vero - class SidekiqWorker - include ::Sidekiq::Worker - - def perform(api_class, domain, options) - api_class.constantize.new(domain, options).perform - Vero::App.log(self, "method: #{api_class}, options: #{options.to_json}, response: sidekiq job queued") - end - end - - module Senders - class Sidekiq - def call(api_class, domain, options) - response = ::Vero::SidekiqWorker.perform_async(api_class.to_s, domain, options) - Vero::App.log(self, "method: #{api_class.name}, options: #{options.to_json}, response: sidekiq job queued") - response - end - end +class Vero::Senders::Sidekiq + def call(api_class, domain, options) + response = ::Vero::SidekiqWorker.perform_async(api_class.to_s, domain, options) + Vero::App.log(self, "method: #{api_class.name}, options: #{options.to_json}, response: sidekiq job queued") + response end end diff --git a/lib/vero/senders/sucker_punch.rb b/lib/vero/senders/sucker_punch.rb index 22f89fd..65e5195 100644 --- a/lib/vero/senders/sucker_punch.rb +++ b/lib/vero/senders/sucker_punch.rb @@ -1,30 +1,5 @@ -# frozen_string_literal: true - -require "json" -require "sucker_punch" - -module Vero - class SuckerPunchWorker - include SuckerPunch::Job - - def perform(api_class, domain, options) - new_options = {} - options.each { |k, v| new_options[k.to_sym] = v } - - begin - api_class.new(domain, new_options).perform - Vero::App.log(self, "method: #{api_class.name}, options: #{options.to_json}, response: job performed") - rescue => e - Vero::App.log(self, "method: #{api_class.name}, options: #{options.to_json}, response: #{e.message}") - end - end - end - - module Senders - class SuckerPunch - def call(api_class, domain, options) - Vero::SuckerPunchWorker.perform_async(api_class, domain, options) - end - end +class Vero::Senders::SuckerPunch + def call(api_class, domain, options) + ::Vero::SuckerPunchWorker.perform_async(api_class, domain, options) end end diff --git a/lib/vero/sidekiq_worker.rb b/lib/vero/sidekiq_worker.rb new file mode 100644 index 0000000..827155d --- /dev/null +++ b/lib/vero/sidekiq_worker.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require "sidekiq" + +class Vero::SidekiqWorker + include ::Sidekiq::Worker + + def perform(api_class, domain, options) + api_class.constantize.new(domain, options).perform + Vero::App.log(self, "method: #{api_class}, options: #{options.to_json}, response: sidekiq job queued") + end +end diff --git a/lib/vero/sucker_punch_worker.rb b/lib/vero/sucker_punch_worker.rb new file mode 100644 index 0000000..0a6914d --- /dev/null +++ b/lib/vero/sucker_punch_worker.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require "sucker_punch" + +class Vero::SuckerPunchWorker + include SuckerPunch::Job + + def perform(api_class, domain, options) + new_options = {} + options.each { |k, v| new_options[k.to_sym] = v } + + begin + api_class.new(domain, new_options).perform + Vero::App.log(self, "method: #{api_class.name}, options: #{options.to_json}, response: job performed") + rescue => e + Vero::App.log(self, "method: #{api_class.name}, options: #{options.to_json}, response: #{e.message}") + end + end +end diff --git a/lib/vero/trackable.rb b/lib/vero/trackable.rb index 6803fbf..7ef4e50 100644 --- a/lib/vero/trackable.rb +++ b/lib/vero/trackable.rb @@ -1,8 +1,5 @@ # frozen_string_literal: true -require "vero/trackable/base" -require "vero/trackable/interface" - module Vero module Trackable include Base diff --git a/lib/vero/trackable/interface.rb b/lib/vero/trackable/interface.rb index c9ed098..4e5e8df 100644 --- a/lib/vero/trackable/interface.rb +++ b/lib/vero/trackable/interface.rb @@ -1,19 +1,15 @@ # frozen_string_literal: true -module Vero - module Trackable - module Interface - def track(event_name, event_data = {}, extras = {}) - track!(event_name, event_data, extras) - end +module Vero::Trackable::Interface + def track(event_name, event_data = {}, extras = {}) + track!(event_name, event_data, extras) + end - def track!(event_name, event_data = {}, extras = {}) - with_default_vero_context.track!(event_name, event_data, extras) - end + def track!(event_name, event_data = {}, extras = {}) + with_default_vero_context.track!(event_name, event_data, extras) + end - def identify! - with_default_vero_context.identify! - end - end + def identify! + with_default_vero_context.identify! end end diff --git a/lib/vero/utility/logger.rb b/lib/vero/utility/logger.rb index 4d75658..796cca3 100644 --- a/lib/vero/utility/logger.rb +++ b/lib/vero/utility/logger.rb @@ -1,29 +1,25 @@ # frozen_string_literal: true -module Vero - module Utility - module Logger - def self.included(base) - base.extend(ClassMethods) - end - - module ClassMethods - def log(object, message) - return unless Vero::App.default_context.config.logging && !defined?(RSpec) +module Vero::Utility::Logger + def self.included(base) + base.extend(ClassMethods) + end - message = "#{object.class.name}: #{message}" + module ClassMethods + def log(object, message) + return unless Vero::App.default_context.config.logging && !defined?(RSpec) - if (logger = self.logger) - logger.info(message) - else - puts(message) - end - end + message = "#{object.class.name}: #{message}" - def logger - Rails.logger if defined?(Rails) - end + if (logger = self.logger) + logger.info(message) + else + puts(message) end end + + def logger + Rails.logger if defined?(Rails) + end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8f7af65..05119f1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,8 +2,8 @@ require "rubygems" require "bundler/setup" + require "vero" -require "json" Dir[File.expand_path("support/**/*.rb", __dir__)].sort.each { |f| require f } diff --git a/vero.gemspec b/vero.gemspec index ef69d20..2b4758b 100644 --- a/vero.gemspec +++ b/vero.gemspec @@ -22,4 +22,5 @@ Gem::Specification.new do |spec| spec.add_dependency "json" spec.add_dependency "rest-client" + spec.add_dependency "zeitwerk" end