noticent 0.0.1.pre.pre
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.
- checksums.yaml +7 -0
- data/.gitignore +51 -0
- data/.rubocop.yml +7 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +2 -0
- data/.vscode/settings.json +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +124 -0
- data/README.md +391 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/generators/noticent/noticent.rb +36 -0
- data/lib/generators/noticent/templates/create_opt_ins.rb +15 -0
- data/lib/generators/noticent/templates/noticent_initializer.rb +17 -0
- data/lib/generators/noticent/templates/opt_in.rb +14 -0
- data/lib/noticent/active_record_opt_in_provider.rb +37 -0
- data/lib/noticent/channel.rb +75 -0
- data/lib/noticent/config.rb +209 -0
- data/lib/noticent/definitions/alert.rb +64 -0
- data/lib/noticent/definitions/channel.rb +43 -0
- data/lib/noticent/definitions/hooks.rb +38 -0
- data/lib/noticent/definitions/product.rb +16 -0
- data/lib/noticent/definitions/product_group.rb +44 -0
- data/lib/noticent/definitions/scope.rb +52 -0
- data/lib/noticent/dispatcher.rb +76 -0
- data/lib/noticent/errors.rb +17 -0
- data/lib/noticent/opt_in.rb +18 -0
- data/lib/noticent/proc_map.rb +35 -0
- data/lib/noticent/version.rb +5 -0
- data/lib/noticent/view.rb +82 -0
- data/lib/noticent.rb +9 -0
- data/noticent.gemspec +36 -0
- data/testing/channels/boo.rb +15 -0
- data/testing/channels/email.rb +20 -0
- data/testing/channels/foo.rb +12 -0
- data/testing/channels/slack.rb +10 -0
- data/testing/channels/webhook.rb +10 -0
- data/testing/models/receipient.rb +10 -0
- data/testing/payloads/comment_payload.rb +8 -0
- data/testing/payloads/payload.rb +9 -0
- data/testing/payloads/post_payload.rb +21 -0
- data/testing/views/email/some_event.html.erb +6 -0
- data/testing/views/email/some_event.txt.erb +6 -0
- data/testing/views/layouts/layout.html.erb +5 -0
- metadata +241 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Noticent
|
4
|
+
class Error < StandardError; end
|
5
|
+
class BadConfiguration < Error; end
|
6
|
+
class InvalidPayload < Error; end
|
7
|
+
class InvalidScope < Error; end
|
8
|
+
class InvalidAlert < Error; end
|
9
|
+
class NoCurrentUser < Error; end
|
10
|
+
class ViewNotFound < Error; end
|
11
|
+
|
12
|
+
class MissingConfiguration < Error
|
13
|
+
def initialize
|
14
|
+
super('Configuration for noticent missing. Do you have noticent initializer?')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
module Noticent
|
6
|
+
class OptIn < ActiveRecord::Base
|
7
|
+
# scope: is the type of domain object that opt-in applies to. For example
|
8
|
+
# it could be post or comment
|
9
|
+
# entity_id: is the ID of the scope (post id or comment id)
|
10
|
+
# channel_name: is the name of the channel opted into. email or slack are examples
|
11
|
+
# alert_name: is the name of the alert: new_user or comment_posted
|
12
|
+
# user_id: is the name of the user who's opted into this
|
13
|
+
|
14
|
+
self.table_name = :opt_ins
|
15
|
+
|
16
|
+
validates_presence_of :scope, :entity_id, :channel_name, :alert_name, :recipient_id
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Noticent
|
4
|
+
class ProcMap
|
5
|
+
def initialize(config)
|
6
|
+
@map = {}
|
7
|
+
@config = config
|
8
|
+
end
|
9
|
+
|
10
|
+
def use(symbol, proc)
|
11
|
+
raise Noticent::BadConfiguration, 'should provide a proc' unless proc.is_a?(Proc)
|
12
|
+
raise Noticent::BadConfiguration, "invalid number of parameters for 'use' in '#{symbol}'" if proc.arity != 1
|
13
|
+
|
14
|
+
@map[symbol] = proc
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch(symbol)
|
18
|
+
raise Noticent::Error, "no map found for '#{symbol}'" if @map[symbol].nil?
|
19
|
+
|
20
|
+
@map[symbol]
|
21
|
+
end
|
22
|
+
|
23
|
+
def count
|
24
|
+
@map.count
|
25
|
+
end
|
26
|
+
|
27
|
+
def values
|
28
|
+
@map
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
attr_reader :config
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Noticent
|
6
|
+
class View
|
7
|
+
# these are the attributes we should use in most cases
|
8
|
+
attr_reader :data # frontmatter in hash form with symbolized keys
|
9
|
+
attr_reader :content # content rendered
|
10
|
+
|
11
|
+
# these are mostly for debug and testing purposes
|
12
|
+
attr_reader :view_content # contents of the view itself
|
13
|
+
attr_reader :filename # view filename
|
14
|
+
attr_reader :template_content # contents of the template
|
15
|
+
attr_reader :raw_content # content in their raw (pre render) format
|
16
|
+
attr_reader :raw_data # frontmatter in their raw (pre render) format
|
17
|
+
attr_reader :rendered_data # frontmatter rendered in string format
|
18
|
+
|
19
|
+
def initialize(filename, template_filename: '', channel:)
|
20
|
+
raise ViewNotFound, "view #{filename} not found" unless File.exist?(filename)
|
21
|
+
raise ViewNotFound, "template #{template_filename} not found" if template_filename != '' && !File.exist?(template_filename)
|
22
|
+
raise ArgumentError, 'channel is nil' if channel.nil?
|
23
|
+
|
24
|
+
@filename = filename
|
25
|
+
@view_content = File.read(filename)
|
26
|
+
@template_content = template_filename != '' ? File.read(template_filename) : '<%= yield %>'
|
27
|
+
@template_filename = template_filename != '' ? template_filename : ''
|
28
|
+
@channel = channel
|
29
|
+
end
|
30
|
+
|
31
|
+
def process
|
32
|
+
parse
|
33
|
+
render_content
|
34
|
+
render_data
|
35
|
+
read_data
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def render_content
|
41
|
+
@content = @channel.render_within_context(@template_content, @view_content)
|
42
|
+
end
|
43
|
+
|
44
|
+
def render_data
|
45
|
+
if @raw_data.nil?
|
46
|
+
@rendered_data = nil
|
47
|
+
return
|
48
|
+
end
|
49
|
+
|
50
|
+
@rendered_data = @channel.render_within_context(nil, @raw_data)
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse
|
54
|
+
result = {}
|
55
|
+
|
56
|
+
# is there front matter?
|
57
|
+
match = FRONTMATTER.match(@view_content)
|
58
|
+
if !match.nil?
|
59
|
+
result[:frontmatter] = match[1]
|
60
|
+
result[:content] = match[2]
|
61
|
+
else
|
62
|
+
result[:content] = @view_content
|
63
|
+
end
|
64
|
+
|
65
|
+
@raw_data = result[:frontmatter]
|
66
|
+
@raw_content = result[:content]
|
67
|
+
end
|
68
|
+
|
69
|
+
def read_data
|
70
|
+
if @raw_data.nil?
|
71
|
+
@data = nil
|
72
|
+
else
|
73
|
+
raise ArgumentError, 'read_data was called before rendering' if @rendered_data.nil?
|
74
|
+
|
75
|
+
data = ::YAML.safe_load(@rendered_data)
|
76
|
+
@data = data.deep_symbolize_keys
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
FRONTMATTER = Regexp.new(/([\s\S]*)^---\s*$([\s\S]*)/)
|
81
|
+
end
|
82
|
+
end
|
data/lib/noticent.rb
ADDED
data/noticent.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'noticent/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'noticent'
|
9
|
+
spec.version = Noticent::VERSION
|
10
|
+
spec.authors = ['Khash Sajadi']
|
11
|
+
spec.email = ['khash@cloud66.com']
|
12
|
+
|
13
|
+
spec.summary = 'Act as Notified is a flexible framework to add notifications to a Rails application'
|
14
|
+
|
15
|
+
# Specify which files should be added to the gem when it is released.
|
16
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
17
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
18
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
end
|
20
|
+
spec.bindir = 'exe'
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_dependency 'activerecord', '~> 5.2'
|
25
|
+
spec.add_dependency 'activesupport', '~> 5.2'
|
26
|
+
|
27
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
28
|
+
spec.add_development_dependency 'factory_bot', '~> 5.0'
|
29
|
+
spec.add_development_dependency 'generator_spec', '~> 0.9'
|
30
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
31
|
+
spec.add_development_dependency 'rspec', '~> 3.8'
|
32
|
+
spec.add_development_dependency 'rubocop', '~> 0.69'
|
33
|
+
spec.add_development_dependency 'rubocop-performance', '~> 1.3'
|
34
|
+
spec.add_development_dependency 'rufo', '~> 0.7'
|
35
|
+
spec.add_development_dependency 'sqlite3', '~> 1.4'
|
36
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Noticent
|
2
|
+
module Testing
|
3
|
+
class Email < ::Noticent::Channel
|
4
|
+
|
5
|
+
def new_signup
|
6
|
+
# NOTE: This is only for testing
|
7
|
+
{ recipients: recipients, payload: payload }
|
8
|
+
end
|
9
|
+
|
10
|
+
def some_event
|
11
|
+
render
|
12
|
+
end
|
13
|
+
|
14
|
+
def foo
|
15
|
+
render
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'payload'
|
2
|
+
|
3
|
+
module Noticent
|
4
|
+
module Testing
|
5
|
+
# this is an example payload for post as scope
|
6
|
+
class PostPayload < Noticent::Testing::Payload
|
7
|
+
attr_accessor :some_attribute
|
8
|
+
attr_accessor :_users
|
9
|
+
attr_accessor :post_id
|
10
|
+
|
11
|
+
def users
|
12
|
+
@_users
|
13
|
+
end
|
14
|
+
|
15
|
+
def owners
|
16
|
+
[]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,241 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: noticent
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.pre.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Khash Sajadi
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: factory_bot
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: generator_spec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.9'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.9'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.8'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.8'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.69'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.69'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-performance
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.3'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.3'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rufo
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.7'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.7'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: sqlite3
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '1.4'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '1.4'
|
167
|
+
description:
|
168
|
+
email:
|
169
|
+
- khash@cloud66.com
|
170
|
+
executables: []
|
171
|
+
extensions: []
|
172
|
+
extra_rdoc_files: []
|
173
|
+
files:
|
174
|
+
- ".gitignore"
|
175
|
+
- ".rubocop.yml"
|
176
|
+
- ".ruby-gemset"
|
177
|
+
- ".ruby-version"
|
178
|
+
- ".vscode/settings.json"
|
179
|
+
- Gemfile
|
180
|
+
- Gemfile.lock
|
181
|
+
- README.md
|
182
|
+
- Rakefile
|
183
|
+
- bin/console
|
184
|
+
- bin/setup
|
185
|
+
- lib/generators/noticent/noticent.rb
|
186
|
+
- lib/generators/noticent/templates/create_opt_ins.rb
|
187
|
+
- lib/generators/noticent/templates/noticent_initializer.rb
|
188
|
+
- lib/generators/noticent/templates/opt_in.rb
|
189
|
+
- lib/noticent.rb
|
190
|
+
- lib/noticent/active_record_opt_in_provider.rb
|
191
|
+
- lib/noticent/channel.rb
|
192
|
+
- lib/noticent/config.rb
|
193
|
+
- lib/noticent/definitions/alert.rb
|
194
|
+
- lib/noticent/definitions/channel.rb
|
195
|
+
- lib/noticent/definitions/hooks.rb
|
196
|
+
- lib/noticent/definitions/product.rb
|
197
|
+
- lib/noticent/definitions/product_group.rb
|
198
|
+
- lib/noticent/definitions/scope.rb
|
199
|
+
- lib/noticent/dispatcher.rb
|
200
|
+
- lib/noticent/errors.rb
|
201
|
+
- lib/noticent/opt_in.rb
|
202
|
+
- lib/noticent/proc_map.rb
|
203
|
+
- lib/noticent/version.rb
|
204
|
+
- lib/noticent/view.rb
|
205
|
+
- noticent.gemspec
|
206
|
+
- testing/channels/boo.rb
|
207
|
+
- testing/channels/email.rb
|
208
|
+
- testing/channels/foo.rb
|
209
|
+
- testing/channels/slack.rb
|
210
|
+
- testing/channels/webhook.rb
|
211
|
+
- testing/models/receipient.rb
|
212
|
+
- testing/payloads/comment_payload.rb
|
213
|
+
- testing/payloads/payload.rb
|
214
|
+
- testing/payloads/post_payload.rb
|
215
|
+
- testing/views/email/some_event.html.erb
|
216
|
+
- testing/views/email/some_event.txt.erb
|
217
|
+
- testing/views/layouts/layout.html.erb
|
218
|
+
homepage:
|
219
|
+
licenses: []
|
220
|
+
metadata: {}
|
221
|
+
post_install_message:
|
222
|
+
rdoc_options: []
|
223
|
+
require_paths:
|
224
|
+
- lib
|
225
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
231
|
+
requirements:
|
232
|
+
- - ">"
|
233
|
+
- !ruby/object:Gem::Version
|
234
|
+
version: 1.3.1
|
235
|
+
requirements: []
|
236
|
+
rubyforge_project:
|
237
|
+
rubygems_version: 2.7.6.2
|
238
|
+
signing_key:
|
239
|
+
specification_version: 4
|
240
|
+
summary: Act as Notified is a flexible framework to add notifications to a Rails application
|
241
|
+
test_files: []
|