magellanalytics 0.2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock ADDED
@@ -0,0 +1,193 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ actionpack (7.0.4.3)
5
+ actionview (= 7.0.4.3)
6
+ activesupport (= 7.0.4.3)
7
+ rack (~> 2.0, >= 2.2.0)
8
+ rack-test (>= 0.6.3)
9
+ rails-dom-testing (~> 2.0)
10
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
11
+ actionview (7.0.4.3)
12
+ activesupport (= 7.0.4.3)
13
+ builder (~> 3.1)
14
+ erubi (~> 1.4)
15
+ rails-dom-testing (~> 2.0)
16
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
17
+ activesupport (7.0.4.3)
18
+ concurrent-ruby (~> 1.0, >= 1.0.2)
19
+ i18n (>= 1.6, < 2)
20
+ minitest (>= 5.1)
21
+ tzinfo (~> 2.0)
22
+ addressable (2.8.4)
23
+ public_suffix (>= 2.0.2, < 6.0)
24
+ analytics-ruby (2.4.0)
25
+ ast (2.4.2)
26
+ builder (3.2.4)
27
+ concurrent-ruby (1.2.2)
28
+ crass (1.0.6)
29
+ descendants_tracker (0.0.4)
30
+ thread_safe (~> 0.3, >= 0.3.1)
31
+ diff-lcs (1.5.0)
32
+ docile (1.4.0)
33
+ erubi (1.12.0)
34
+ faraday (1.10.3)
35
+ faraday-em_http (~> 1.0)
36
+ faraday-em_synchrony (~> 1.0)
37
+ faraday-excon (~> 1.1)
38
+ faraday-httpclient (~> 1.0)
39
+ faraday-multipart (~> 1.0)
40
+ faraday-net_http (~> 1.0)
41
+ faraday-net_http_persistent (~> 1.0)
42
+ faraday-patron (~> 1.0)
43
+ faraday-rack (~> 1.0)
44
+ faraday-retry (~> 1.0)
45
+ ruby2_keywords (>= 0.0.4)
46
+ faraday-em_http (1.0.0)
47
+ faraday-em_synchrony (1.0.0)
48
+ faraday-excon (1.1.0)
49
+ faraday-httpclient (1.0.1)
50
+ faraday-multipart (1.0.4)
51
+ multipart-post (~> 2)
52
+ faraday-net_http (1.0.1)
53
+ faraday-net_http_persistent (1.2.0)
54
+ faraday-patron (1.0.0)
55
+ faraday-rack (1.0.0)
56
+ faraday-retry (1.0.3)
57
+ git (1.18.0)
58
+ addressable (~> 2.8)
59
+ rchardet (~> 1.8)
60
+ github_api (0.19.0)
61
+ addressable (~> 2.4)
62
+ descendants_tracker (~> 0.0.4)
63
+ faraday (>= 0.8, < 2)
64
+ hashie (~> 3.5, >= 3.5.2)
65
+ oauth2 (~> 1.0)
66
+ hashie (3.6.0)
67
+ highline (2.1.0)
68
+ i18n (1.12.0)
69
+ concurrent-ruby (~> 1.0)
70
+ json (2.6.3)
71
+ juwelier (2.4.9)
72
+ builder
73
+ bundler
74
+ git
75
+ github_api
76
+ highline
77
+ kamelcase (~> 0)
78
+ nokogiri
79
+ psych
80
+ rake
81
+ rdoc
82
+ semver2
83
+ jwt (2.7.0)
84
+ kamelcase (0.0.2)
85
+ semver2 (~> 3)
86
+ loofah (2.20.0)
87
+ crass (~> 1.0.2)
88
+ nokogiri (>= 1.5.9)
89
+ mini_portile2 (2.8.1)
90
+ minitest (5.18.0)
91
+ multi_json (1.15.0)
92
+ multi_xml (0.6.0)
93
+ multipart-post (2.3.0)
94
+ nokogiri (1.14.3)
95
+ mini_portile2 (~> 2.8.0)
96
+ racc (~> 1.4)
97
+ nokogiri (1.14.3-arm64-darwin)
98
+ racc (~> 1.4)
99
+ oauth2 (1.4.11)
100
+ faraday (>= 0.17.3, < 3.0)
101
+ jwt (>= 1.0, < 3.0)
102
+ multi_json (~> 1.3)
103
+ multi_xml (~> 0.5)
104
+ rack (>= 1.2, < 4)
105
+ parallel (1.23.0)
106
+ parser (3.2.2.0)
107
+ ast (~> 2.4.1)
108
+ psych (5.1.0)
109
+ stringio
110
+ public_suffix (5.0.1)
111
+ racc (1.6.2)
112
+ rack (2.2.6.4)
113
+ rack-test (2.1.0)
114
+ rack (>= 1.3)
115
+ rails-dom-testing (2.0.3)
116
+ activesupport (>= 4.2.0)
117
+ nokogiri (>= 1.6)
118
+ rails-html-sanitizer (1.5.0)
119
+ loofah (~> 2.19, >= 2.19.1)
120
+ rainbow (3.1.1)
121
+ rake (13.0.6)
122
+ rchardet (1.8.0)
123
+ rdoc (6.5.0)
124
+ psych (>= 4.0.0)
125
+ regexp_parser (2.8.0)
126
+ rexml (3.2.5)
127
+ rspec (3.12.0)
128
+ rspec-core (~> 3.12.0)
129
+ rspec-expectations (~> 3.12.0)
130
+ rspec-mocks (~> 3.12.0)
131
+ rspec-core (3.12.2)
132
+ rspec-support (~> 3.12.0)
133
+ rspec-expectations (3.12.2)
134
+ diff-lcs (>= 1.2.0, < 2.0)
135
+ rspec-support (~> 3.12.0)
136
+ rspec-mocks (3.12.5)
137
+ diff-lcs (>= 1.2.0, < 2.0)
138
+ rspec-support (~> 3.12.0)
139
+ rspec-support (3.12.0)
140
+ rubocop (1.50.2)
141
+ json (~> 2.3)
142
+ parallel (~> 1.10)
143
+ parser (>= 3.2.0.0)
144
+ rainbow (>= 2.2.2, < 4.0)
145
+ regexp_parser (>= 1.8, < 3.0)
146
+ rexml (>= 3.2.5, < 4.0)
147
+ rubocop-ast (>= 1.28.0, < 2.0)
148
+ ruby-progressbar (~> 1.7)
149
+ unicode-display_width (>= 2.4.0, < 3.0)
150
+ rubocop-ast (1.28.0)
151
+ parser (>= 3.2.1.0)
152
+ ruby-progressbar (1.13.0)
153
+ ruby2_keywords (0.0.5)
154
+ semver2 (3.4.2)
155
+ shoulda (4.0.0)
156
+ shoulda-context (~> 2.0)
157
+ shoulda-matchers (~> 4.0)
158
+ shoulda-context (2.0.0)
159
+ shoulda-matchers (4.5.1)
160
+ activesupport (>= 4.2.0)
161
+ simplecov (0.22.0)
162
+ docile (~> 1.1)
163
+ simplecov-html (~> 0.11)
164
+ simplecov_json_formatter (~> 0.1)
165
+ simplecov-html (0.12.3)
166
+ simplecov_json_formatter (0.1.4)
167
+ stringio (3.0.6)
168
+ thread_safe (0.3.6)
169
+ tzinfo (2.0.6)
170
+ concurrent-ruby (~> 1.0)
171
+ unicode-display_width (2.4.2)
172
+
173
+ PLATFORMS
174
+ arm64-darwin-22
175
+ ruby
176
+
177
+ DEPENDENCIES
178
+ actionpack (>= 7.0.4.3, < 7.1)
179
+ activesupport (>= 7.0.4.3)
180
+ analytics-ruby
181
+ bundler (~> 2.0)
182
+ juwelier (~> 2.4)
183
+ rdoc (~> 6.3, >= 6.3.1)
184
+ rspec
185
+ rubocop
186
+ shoulda
187
+ simplecov
188
+
189
+ RUBY VERSION
190
+ ruby 3.1.2p20
191
+
192
+ BUNDLED WITH
193
+ 2.2.2
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2020 Ryan Kerr
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,18 @@
1
+ = MagellAnalytics
2
+
3
+ A simple abstraction layer over Segment's `analytics-ruby` to simplify event configuration and dispatch.
4
+
5
+ == Contributing to magellanalytics
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
+ * Fork the project.
10
+ * Start a feature/bugfix branch.
11
+ * Commit and push until you are happy with your contribution.
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2020 Magellan AI. All rights reserved.
18
+ See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ warn e.message
10
+ warn 'Run `bundle install` to install missing gems'
11
+ exit e.status_code
12
+ end
13
+
14
+ require 'rake'
15
+ require 'juwelier'
16
+ require_relative 'lib/magellanalytics/version'
17
+
18
+ Juwelier::Tasks.new do |gem|
19
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
20
+ gem.name = 'magellanalytics'
21
+ gem.homepage = 'http://github.com/magellan-ai/magellanalytics'
22
+ gem.version = Magellanalytics::Version::STRING
23
+ gem.license = 'MIT'
24
+ gem.summary = "Simple abstraction layer over Segment's `analytics-ruby`"
25
+ gem.description = "Simplifies configuration and event dispatch from Segment's analytics gem for ease-of-use in Rails applications."
26
+ gem.email = 'rex@magellan.ai'
27
+ gem.authors = ['Ryan Kerr', 'William Dana', 'Gregory Nelson', 'Rex Madden']
28
+
29
+ gem.required_ruby_version = '>= 2.7'
30
+
31
+ # dependencies defined in Gemfile
32
+ end
33
+
34
+ Juwelier::RubygemsDotOrgTasks.new
35
+
36
+ require 'rspec/core/rake_task'
37
+
38
+ RSpec::Core::RakeTask.new(:spec)
39
+
40
+ desc 'Code coverage detail'
41
+ task :simplecov do
42
+ ENV['COVERAGE'] = 'true'
43
+ Rake::Task['spec'].execute
44
+ end
45
+
46
+ task default: :spec
47
+
48
+ require 'rdoc/task'
49
+
50
+ Rake::RDocTask.new do |rdoc|
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "Magellanalytics #{Magellanalytics::Version::STRING}"
53
+ rdoc.options << '--line-numbers'
54
+ rdoc.rdoc_files.include('README*')
55
+ rdoc.rdoc_files.include('lib/**/*.rb')
56
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Magellanalytics
4
+ class Configuration
5
+ attr_accessor :segment_write_key
6
+ attr_reader :track_user_check, :user_traits
7
+ attr_writer :base_integrations, :base_props
8
+
9
+ def initialize
10
+ @base_integrations = {}
11
+ @base_props = {}
12
+ @events = {}
13
+ end
14
+
15
+ def track_user_if(&block)
16
+ @track_user_check = block
17
+ end
18
+
19
+ def track_user_check?
20
+ instance_variable_defined?(:@track_user_check)
21
+ end
22
+
23
+ def event_description(name)
24
+ raise Magellanalytics::UnregisteredEvent, "Unknown event: #{name}" unless registered_events.include?(name.to_sym)
25
+
26
+ @events[name.to_sym]&.description
27
+ end
28
+
29
+ def register_event(event, description = nil)
30
+ @events[event.to_sym] = Magellanalytics::Event.new(event, description)
31
+ end
32
+
33
+ def registered_events
34
+ @events.keys
35
+ end
36
+
37
+ def user_traits?
38
+ instance_variable_defined?(:@user_traits)
39
+ end
40
+
41
+ def register_user_traits(&block)
42
+ @user_traits = block
43
+ end
44
+
45
+ def base_integrations
46
+ return @base_integrations.call if @base_integrations.respond_to?(:call)
47
+
48
+ @base_integrations
49
+ end
50
+
51
+ def base_props
52
+ return @base_props.call if @base_props.respond_to?(:call)
53
+
54
+ @base_props
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Magellanalytics
4
+ class Event
5
+ attr_accessor :name, :description
6
+
7
+ def initialize(name, description = nil)
8
+ @name = name.to_s.gsub(/\s+/, '_').underscore.to_sym
9
+ @description = description || name.to_s.humanize
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Magellanalytics
4
+ class Railtie < ::Rails::Railtie
5
+ end
6
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Magellanalytics
4
+ module Version
5
+ MAJOR = 0
6
+ MINOR = 2
7
+ PATCH = 0
8
+ BUILD = 0
9
+
10
+ STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
11
+ end
12
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/all'
4
+
5
+ require 'segment/analytics'
6
+
7
+ require 'magellanalytics/configuration'
8
+ require 'magellanalytics/event'
9
+ require 'magellanalytics/railtie' if defined?(Rails::Railtie)
10
+
11
+ module Magellanalytics
12
+ extend self
13
+
14
+ UnregisteredEvent = Class.new(StandardError)
15
+
16
+ def configure
17
+ yield config
18
+ end
19
+
20
+ def identify(user)
21
+ return unless track_user?(user)
22
+
23
+ payload = { user_id: user.id }
24
+ payload[:traits] = config.user_traits.call(user) if config.user_traits?
25
+ analytics.identify(payload)
26
+ end
27
+
28
+ def page(user, request, **opts)
29
+ return unless track_user?(user)
30
+
31
+ identify user
32
+
33
+ props = config.base_props
34
+ props[:params] = request.filtered_parameters
35
+ props[:path] = request.original_fullpath
36
+ props[:url] = request.original_url
37
+ props[:referrer] = request.referer
38
+
39
+ payload =
40
+ {
41
+ user_id: user.id,
42
+ properties: recursive_flatten(props).with_indifferent_access.merge(client_id: user.client_id),
43
+ name: "#{request.parameters['controller']}/#{request.parameters['action']}",
44
+ **opts
45
+ }
46
+ analytics.page(payload)
47
+ end
48
+
49
+ def track(user, event, properties: {}, **opts)
50
+ return unless track_user?(user)
51
+
52
+ identify user
53
+
54
+ payload =
55
+ {
56
+ user_id: user.id,
57
+ event: config.event_description(event),
58
+ properties: config.base_props.merge(properties),
59
+ **opts
60
+ }
61
+ payload[:properties][:client_id] = user.client_id
62
+ payload[:integrations] = config.base_integrations if config.base_integrations.present?
63
+
64
+ analytics.track(payload)
65
+ end
66
+
67
+ def reset_config!
68
+ @config = nil
69
+ end
70
+
71
+ private
72
+
73
+ def track_user?(user)
74
+ return true unless config.track_user_check?
75
+
76
+ config.track_user_check.call(user)
77
+ end
78
+
79
+ def analytics
80
+ @analytics ||= Segment::Analytics.new(write_key: config.segment_write_key)
81
+ end
82
+
83
+ def config
84
+ @config ||= Magellanalytics::Configuration.new
85
+ end
86
+
87
+ def recursive_flatten(to_flatten, prefix = nil, separator: '.') # rubocop:disable Metrics/PerceivedComplexity
88
+ result = {}
89
+ to_flatten = to_flatten.as_json
90
+
91
+ case to_flatten
92
+ when Hash
93
+ to_flatten.map do |k, v|
94
+ k = "#{prefix}#{separator}#{k}" if prefix.present?
95
+ result.merge!([Hash, Array].include?(v.class) ? recursive_flatten(v, k) : { k => v })
96
+ end
97
+ when Array
98
+ to_flatten.uniq.each_with_index do |o, i|
99
+ i = "#{prefix}#{separator}#{i}" if prefix.present?
100
+ result.merge!([Hash, Array].include?(o.class) ? recursive_flatten(o, i) : { i => o })
101
+ end
102
+ end
103
+
104
+ result
105
+ rescue => e
106
+ Rails.logger.error "Could not flatten hash: #{e}" if defined?(Rails) && Rails.logger
107
+ to_flatten
108
+ end
109
+ end
@@ -0,0 +1,78 @@
1
+ # Generated by juwelier
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: magellanalytics 0.2.0.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "magellanalytics".freeze
9
+ s.version = "0.2.0.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["Ryan Kerr".freeze, "William Dana".freeze, "Gregory Nelson".freeze, "Rex Madden".freeze]
14
+ s.date = "2023-11-09"
15
+ s.description = "Simplifies configuration and event dispatch from Segment's analytics gem for ease-of-use in Rails applications.".freeze
16
+ s.email = "rex@magellan.ai".freeze
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".rspec",
24
+ ".rspec_parallel",
25
+ ".rubocop.yml",
26
+ ".ruby-gemset",
27
+ ".ruby-version",
28
+ "Gemfile",
29
+ "Gemfile.lock",
30
+ "LICENSE.txt",
31
+ "README.rdoc",
32
+ "Rakefile",
33
+ "lib/magellanalytics.rb",
34
+ "lib/magellanalytics/configuration.rb",
35
+ "lib/magellanalytics/event.rb",
36
+ "lib/magellanalytics/railtie.rb",
37
+ "lib/magellanalytics/version.rb",
38
+ "magellanalytics.gemspec",
39
+ "magellanalytics.iml",
40
+ "spec/event_spec.rb",
41
+ "spec/magellanalytics_spec.rb",
42
+ "spec/spec_helper.rb"
43
+ ]
44
+ s.homepage = "http://github.com/magellan-ai/magellanalytics".freeze
45
+ s.licenses = ["MIT".freeze]
46
+ s.required_ruby_version = Gem::Requirement.new(">= 2.7".freeze)
47
+ s.rubygems_version = "3.3.7".freeze
48
+ s.summary = "Simple abstraction layer over Segment's `analytics-ruby`".freeze
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 4
52
+ end
53
+
54
+ if s.respond_to? :add_runtime_dependency then
55
+ s.add_runtime_dependency(%q<activesupport>.freeze, [">= 7.0.4.3"])
56
+ s.add_runtime_dependency(%q<analytics-ruby>.freeze, [">= 0"])
57
+ s.add_development_dependency(%q<bundler>.freeze, ["~> 2.0"])
58
+ s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.4"])
59
+ s.add_development_dependency(%q<rdoc>.freeze, ["~> 6.3", ">= 6.3.1"])
60
+ s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
61
+ s.add_development_dependency(%q<rubocop>.freeze, [">= 0"])
62
+ s.add_development_dependency(%q<shoulda>.freeze, [">= 0"])
63
+ s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
64
+ s.add_development_dependency(%q<actionpack>.freeze, [">= 7.0.4.3", "< 7.1"])
65
+ else
66
+ s.add_dependency(%q<activesupport>.freeze, [">= 7.0.4.3"])
67
+ s.add_dependency(%q<analytics-ruby>.freeze, [">= 0"])
68
+ s.add_dependency(%q<bundler>.freeze, ["~> 2.0"])
69
+ s.add_dependency(%q<juwelier>.freeze, ["~> 2.4"])
70
+ s.add_dependency(%q<rdoc>.freeze, ["~> 6.3", ">= 6.3.1"])
71
+ s.add_dependency(%q<rspec>.freeze, [">= 0"])
72
+ s.add_dependency(%q<rubocop>.freeze, [">= 0"])
73
+ s.add_dependency(%q<shoulda>.freeze, [">= 0"])
74
+ s.add_dependency(%q<simplecov>.freeze, [">= 0"])
75
+ s.add_dependency(%q<actionpack>.freeze, [">= 7.0.4.3", "< 7.1"])
76
+ end
77
+ end
78
+