stenotype 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'securerandom'
3
2
 
4
3
  module Stenotype
5
4
  #
@@ -9,6 +8,14 @@ module Stenotype
9
8
  class EventSerializer
10
9
  attr_reader :event, :uuid_generator
11
10
 
11
+ #
12
+ # @example Serializing an event with default UUID generator
13
+ # event = Stenotype::Event.new(data, attributes, eval_context)
14
+ # serializer = Stenotype::EventSerializer.new(event)
15
+ #
16
+ # @example Serializing an event with custom UUID generator
17
+ # event = Stenotype::Event.new(data, attributes, eval_context)
18
+ # serializer = Stenotype::EventSerializer.new(event, uuid_generator: CustomUUIDGen)
12
19
  #
13
20
  # @param event {Stenotype::Event}
14
21
  # @param uuid_generator {#uuid} an object responding to [#uuid]
@@ -18,6 +25,18 @@ module Stenotype
18
25
  @uuid_generator = uuid_generator
19
26
  end
20
27
 
28
+ #
29
+ # @example Serializing an event with default uuid generator (SecureRandom)
30
+ # event = Stenotype::Event.new(data, attributes, eval_context)
31
+ # serializer = Stenotype::EventSerializer.new(event)
32
+ # serializer.serialize #=> A hash with event.data, event.options,
33
+ # # default_options and eval_context_options
34
+ #
35
+ # @example Serializing an event with custom uuid generator
36
+ # event = Stenotype::Event.new(data, attributes, eval_context)
37
+ # serializer = Stenotype::EventSerializer.new(event, uuid_generator: CustomUUIDGen)
38
+ # serializer.serialize #=> A hash with event.data, event.options,
39
+ # # default_options and eval_context_options
21
40
  #
22
41
  # @return {Hash} A hash representation of the event and its context
23
42
  #
@@ -26,7 +45,7 @@ module Stenotype
26
45
  **event_data,
27
46
  **event_options,
28
47
  **default_options,
29
- **eval_context_options
48
+ **eval_context_options,
30
49
  }
31
50
  end
32
51
 
@@ -45,16 +64,17 @@ module Stenotype
45
64
  end
46
65
 
47
66
  def eval_context_options
48
- eval_context.map do |context_name, context|
67
+ context_attributes = eval_context.map do |context_name, context|
49
68
  handler = Stenotype::ContextHandlers.known.choose(handler_name: context_name)
50
69
  handler.new(context).as_json
51
- end.reduce(:merge!) || {}
70
+ end
71
+ context_attributes.reduce(:merge!) || {}
52
72
  end
53
73
 
54
74
  def default_options
55
75
  {
56
76
  timestamp: Time.now.utc,
57
- uuid: uuid_generator.uuid
77
+ uuid: uuid_generator.uuid,
58
78
  }
59
79
  end
60
80
  end
@@ -3,6 +3,10 @@
3
3
  require "active_support/concern"
4
4
 
5
5
  module Stenotype
6
+ #
7
+ # A namespace containing extensions of various frameworks.
8
+ # For example Rails components could be extended
9
+ #
6
10
  module Frameworks
7
11
  module Rails
8
12
  #
@@ -12,11 +16,13 @@ module Stenotype
12
16
  module ActionControllerExtension
13
17
  extend ActiveSupport::Concern
14
18
 
19
+ private
20
+
15
21
  #
16
22
  # Emits and event with given data
17
23
  # @param data {Hash} Data to be sent to targets
18
24
  #
19
- def record_freshly_event(data)
25
+ def _record_freshly_event(data)
20
26
  Stenotype::Event.emit!(data, options: {}, eval_context: { controller: self })
21
27
  end
22
28
 
@@ -28,12 +34,19 @@ module Stenotype
28
34
  # Adds a before_action to each action from the passed list. A before action
29
35
  # is emitting a {Stenotype::Event}. Please note that in case track_view is
30
36
  # used several times, it will keep track of the actions which emit events.
31
- # Each time a new track_view is called it will find a symmetric difference
32
- # of two sets: set of 'used' actions and a set passed to `track_view`.
33
37
  #
34
- # @example
38
+ # @note Each time a new track_view is called it will find a symmetric difference
39
+ # of two sets: set of already tracked actions and a set passed to `track_view`.
40
+ #
41
+ # @example Tracking multiple actions with track_view
42
+ # Stenotype.configure do |config|
43
+ # config.enable_action_controller_extension = true
44
+ # config.enable_active_job_extension = true
45
+ # end
46
+ #
35
47
  # class MyController < ActionController::Base
36
- # track_view :index, :show
48
+ # track_view :index, :show # Emits an event upon calling index and show actions,
49
+ # # but does not trigger an event on create
37
50
  #
38
51
  # def index
39
52
  # # do_something
@@ -59,36 +72,36 @@ module Stenotype
59
72
  return if delta.empty?
60
73
 
61
74
  before_action only: delta do
62
- record_freshly_event(type: 'view')
75
+ _record_freshly_event(type: "view")
63
76
  end
64
77
 
65
78
  _tracked_actions.merge(delta)
66
79
  end
67
80
 
68
- # :nodoc:
69
- def _tracked_actions
70
- @_tracked_actions ||= Set.new
71
- end
72
-
73
- # Note this action will only define a symmetric difference of
74
- # the covered with events actions and the ones not used yet.
81
+ #
82
+ # @note This action will only define a symmetric difference of
83
+ # the tracked actions and the ones not tracked yet.
75
84
  # @see #track_view
76
85
  #
77
- # @example
78
- # class MyController < ActionController::Base
79
- # track_all_views
86
+ # @example Emitting an event before all actions in controller
87
+ # class UsersController < ApplicationController
88
+ # track_all_views # Emits an event before all actions in a controller
80
89
  #
81
90
  # def index
82
- # # do_something
91
+ # # do something
83
92
  # end
84
93
  #
85
94
  # def show
86
95
  # # do something
87
96
  # end
97
+ #
98
+ # def create
99
+ # # do something
100
+ # end
88
101
  # end
89
102
  #
90
103
  def track_all_views
91
- actions = self.action_methods
104
+ actions = action_methods
92
105
 
93
106
  # A symmetric difference of two sets.
94
107
  # This prevents accidental duplicating of events
@@ -97,12 +110,21 @@ module Stenotype
97
110
  return if delta.empty?
98
111
 
99
112
  before_action only: delta.to_a do
100
- record_freshly_event(type: "view")
113
+ _record_freshly_event(type: "view")
101
114
  end
102
115
 
103
116
  # merge is a mutating op
104
117
  _tracked_actions.merge(delta)
105
118
  end
119
+
120
+ private
121
+
122
+ #
123
+ # @return {Set<Symbol>} a set of tracked actions
124
+ #
125
+ def _tracked_actions
126
+ @_tracked_actions ||= Set.new
127
+ end
106
128
  end
107
129
  end
108
130
  end
@@ -29,7 +29,6 @@ module Stenotype
29
29
  # end
30
30
  # end
31
31
  #
32
- # rubocop:disable Metrics/MethodLength
33
32
  #
34
33
  def trackable_job!
35
34
  proxy = const_get(:JobExt)
@@ -37,8 +36,8 @@ module Stenotype
37
36
  define_method(:perform) do |*args, **rest_args, &block|
38
37
  Stenotype::Event.emit!(
39
38
  { type: "active_job" },
40
- options: {},
41
- eval_context: { active_job: self }
39
+ { options: {},
40
+ eval_context: { active_job: self }},
42
41
  )
43
42
  super(*args, **rest_args, &block)
44
43
  end
@@ -48,9 +47,8 @@ module Stenotype
48
47
  # super() can be chained down the ancestors
49
48
  # without changing existing ActiveJob interface
50
49
  #
51
- send(:prepend, proxy)
50
+ public_send(:prepend, proxy)
52
51
  end
53
- # rubocop:enable Metrics/MethodLength
54
52
  end
55
53
  end
56
54
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stenotype/frameworks/rails/action_controller"
4
+ require "stenotype/frameworks/rails/active_job"
5
+
6
+ module Stenotype
7
+ #
8
+ # A Railtie allowing to extend Rails component with
9
+ # Stenotype extensions for emitting event in various Rails components.
10
+ #
11
+ class Railtie < ::Rails::Railtie
12
+ Stenotype.configure do |config|
13
+ config.rails do |rails_config|
14
+ rails_config.enable_action_controller_ext = true
15
+ rails_config.enable_active_job_ext = true
16
+ end
17
+ end
18
+
19
+ config.stenotype = Stenotype.config
20
+
21
+ if config.stenotype.rails.enable_action_controller_ext
22
+ ActiveSupport.on_load(:action_controller) do
23
+ Stenotype::ContextHandlers.register Stenotype::ContextHandlers::Rails::Controller
24
+ include Stenotype::Frameworks::Rails::ActionControllerExtension
25
+ end
26
+ end
27
+
28
+ # @todo: consider using `::ActiveJob::Base.around_perform`
29
+ # or `::ActiveJob::Base.around_enqueue`
30
+ if config.stenotype.rails.enable_active_job_ext
31
+ ActiveSupport.on_load(:active_job) do
32
+ Stenotype::ContextHandlers.register Stenotype::ContextHandlers::Rails::ActiveJob
33
+ extend Stenotype::Frameworks::Rails::ActiveJobExtension
34
+ end
35
+ end
36
+ end
37
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Stenotype
4
4
  # :nodoc:
5
- VERSION = '0.1.0'
5
+ VERSION = "0.1.1"
6
6
  # :nodoc:
7
7
  end
@@ -6,42 +6,46 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
6
  require "stenotype/version"
7
7
 
8
8
  Gem::Specification.new do |spec|
9
- spec.name = 'stenotype'
9
+ spec.name = "stenotype"
10
10
  spec.version = Stenotype::VERSION
11
11
  spec.authors = ["Roman Kapitonov"]
12
12
  spec.email = ["roman.kapitonov@freshly.com"]
13
13
 
14
- spec.summary = 'Gem for emitting events and sending them to an external system.'
15
- spec.description = 'Pretty much it'
16
- spec.homepage = 'https://github.com/Freshly/stenotype'
17
- spec.license = 'MIT'
14
+ spec.summary = "Gem for emitting events and sending them to an external system."
15
+ spec.description = "Pretty much it"
16
+ spec.homepage = "https://github.com/Freshly/stenotype"
17
+ spec.license = "MIT"
18
18
 
19
- spec.metadata['homepage_uri'] = spec.homepage
20
- spec.metadata['source_code_uri'] = 'https://github.com/Freshly/stenotype'
21
- spec.metadata['changelog_uri'] = 'https://github.com/Freshly/stenotype/CHANGELOG.md'
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = "https://github.com/Freshly/stenotype"
21
+ spec.metadata["changelog_uri"] = "https://github.com/Freshly/stenotype/CHANGELOG.md"
22
22
 
23
23
  # Specify which files should be added to the gem when it is released.
24
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
25
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
26
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
27
  end
28
- spec.bindir = 'exe'
28
+ spec.bindir = "exe"
29
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
- spec.require_paths = ['lib']
31
-
32
- spec.add_dependency 'activesupport', '>= 5.0.0'
33
- spec.add_dependency 'google-cloud-pubsub', '~> 1.0.0'
34
-
35
- spec.add_development_dependency 'bundler', '~> 2.0'
36
- spec.add_development_dependency 'github-markup', '~> 3.0'
37
- spec.add_development_dependency 'rake', '~> 10.0'
38
- spec.add_development_dependency 'redcarpet', '~> 3.5'
39
- spec.add_development_dependency 'yard', '~> 0.9'
40
-
41
- spec.add_development_dependency 'pry', '~> 0.12'
42
- spec.add_development_dependency 'rails', '~> 5.2.3'
43
- spec.add_development_dependency 'rspec', '~> 3.0'
44
- spec.add_development_dependency 'rubocop', '~> 0.76'
45
- spec.add_development_dependency 'simplecov', '~> 0.17'
46
- spec.add_development_dependency 'timecop', '~> 0.9'
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_dependency "activesupport", ">= 5.0.0"
33
+ spec.add_dependency "google-cloud-pubsub", "~> 1.0.0"
34
+
35
+ spec.add_runtime_dependency "spicery", ">= 0.19.0", "< 1.0"
36
+
37
+ spec.add_development_dependency "bundler", "~> 2.0"
38
+ spec.add_development_dependency "github-markup", "~> 3.0"
39
+ spec.add_development_dependency "rake", "~> 10.0"
40
+ spec.add_development_dependency "redcarpet", "~> 3.5"
41
+ spec.add_development_dependency "yard", "~> 0.9"
42
+
43
+ spec.add_development_dependency "rspice", ">= 0.19.0", "< 1.0"
44
+ spec.add_development_dependency "spicerack-styleguide", ">= 0.19.0", "< 1.0"
45
+
46
+ spec.add_development_dependency "pry", "~> 0.12"
47
+ spec.add_development_dependency "rails", "~> 5.2.3"
48
+ spec.add_development_dependency "rspec", "~> 3.0"
49
+ spec.add_development_dependency "simplecov", "~> 0.17"
50
+ spec.add_development_dependency "timecop", "~> 0.9"
47
51
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stenotype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Kapitonov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-21 00:00:00.000000000 Z
11
+ date: 2019-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,6 +38,26 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: spicery
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.19.0
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '1.0'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 0.19.0
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.0'
41
61
  - !ruby/object:Gem::Dependency
42
62
  name: bundler
43
63
  requirement: !ruby/object:Gem::Requirement
@@ -109,61 +129,87 @@ dependencies:
109
129
  - !ruby/object:Gem::Version
110
130
  version: '0.9'
111
131
  - !ruby/object:Gem::Dependency
112
- name: pry
132
+ name: rspice
113
133
  requirement: !ruby/object:Gem::Requirement
114
134
  requirements:
115
- - - "~>"
135
+ - - ">="
116
136
  - !ruby/object:Gem::Version
117
- version: '0.12'
137
+ version: 0.19.0
138
+ - - "<"
139
+ - !ruby/object:Gem::Version
140
+ version: '1.0'
118
141
  type: :development
119
142
  prerelease: false
120
143
  version_requirements: !ruby/object:Gem::Requirement
121
144
  requirements:
122
- - - "~>"
145
+ - - ">="
123
146
  - !ruby/object:Gem::Version
124
- version: '0.12'
147
+ version: 0.19.0
148
+ - - "<"
149
+ - !ruby/object:Gem::Version
150
+ version: '1.0'
125
151
  - !ruby/object:Gem::Dependency
126
- name: rails
152
+ name: spicerack-styleguide
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: 0.19.0
158
+ - - "<"
159
+ - !ruby/object:Gem::Version
160
+ version: '1.0'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: 0.19.0
168
+ - - "<"
169
+ - !ruby/object:Gem::Version
170
+ version: '1.0'
171
+ - !ruby/object:Gem::Dependency
172
+ name: pry
127
173
  requirement: !ruby/object:Gem::Requirement
128
174
  requirements:
129
175
  - - "~>"
130
176
  - !ruby/object:Gem::Version
131
- version: 5.2.3
177
+ version: '0.12'
132
178
  type: :development
133
179
  prerelease: false
134
180
  version_requirements: !ruby/object:Gem::Requirement
135
181
  requirements:
136
182
  - - "~>"
137
183
  - !ruby/object:Gem::Version
138
- version: 5.2.3
184
+ version: '0.12'
139
185
  - !ruby/object:Gem::Dependency
140
- name: rspec
186
+ name: rails
141
187
  requirement: !ruby/object:Gem::Requirement
142
188
  requirements:
143
189
  - - "~>"
144
190
  - !ruby/object:Gem::Version
145
- version: '3.0'
191
+ version: 5.2.3
146
192
  type: :development
147
193
  prerelease: false
148
194
  version_requirements: !ruby/object:Gem::Requirement
149
195
  requirements:
150
196
  - - "~>"
151
197
  - !ruby/object:Gem::Version
152
- version: '3.0'
198
+ version: 5.2.3
153
199
  - !ruby/object:Gem::Dependency
154
- name: rubocop
200
+ name: rspec
155
201
  requirement: !ruby/object:Gem::Requirement
156
202
  requirements:
157
203
  - - "~>"
158
204
  - !ruby/object:Gem::Version
159
- version: '0.76'
205
+ version: '3.0'
160
206
  type: :development
161
207
  prerelease: false
162
208
  version_requirements: !ruby/object:Gem::Requirement
163
209
  requirements:
164
210
  - - "~>"
165
211
  - !ruby/object:Gem::Version
166
- version: '0.76'
212
+ version: '3.0'
167
213
  - !ruby/object:Gem::Dependency
168
214
  name: simplecov
169
215
  requirement: !ruby/object:Gem::Requirement
@@ -204,6 +250,7 @@ files:
204
250
  - ".rubocop.yml"
205
251
  - ".travis.yml"
206
252
  - ".yardopts"
253
+ - CHANGELOG.md
207
254
  - Gemfile
208
255
  - Gemfile.lock
209
256
  - LICENSE.txt
@@ -212,6 +259,9 @@ files:
212
259
  - TODO.md
213
260
  - bin/console
214
261
  - bin/setup
262
+ - lib/generators/USAGE
263
+ - lib/generators/stenotype/initializer/initializer_generator.rb
264
+ - lib/generators/stenotype/initializer/templates/initializer.rb.erb
215
265
  - lib/stenotype.rb
216
266
  - lib/stenotype/adapters.rb
217
267
  - lib/stenotype/adapters/base.rb
@@ -225,12 +275,12 @@ files:
225
275
  - lib/stenotype/context_handlers/rails/active_job.rb
226
276
  - lib/stenotype/context_handlers/rails/controller.rb
227
277
  - lib/stenotype/dispatcher.rb
278
+ - lib/stenotype/emitter.rb
228
279
  - lib/stenotype/event.rb
229
280
  - lib/stenotype/event_serializer.rb
230
- - lib/stenotype/exceptions.rb
231
- - lib/stenotype/frameworks/object_ext.rb
232
281
  - lib/stenotype/frameworks/rails/action_controller.rb
233
282
  - lib/stenotype/frameworks/rails/active_job.rb
283
+ - lib/stenotype/railtie.rb
234
284
  - lib/stenotype/version.rb
235
285
  - stenotype.gemspec
236
286
  homepage: https://github.com/Freshly/stenotype
@@ -255,7 +305,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
255
305
  - !ruby/object:Gem::Version
256
306
  version: '0'
257
307
  requirements: []
258
- rubygems_version: 3.0.4
308
+ rubygems_version: 3.0.3
259
309
  signing_key:
260
310
  specification_version: 4
261
311
  summary: Gem for emitting events and sending them to an external system.