activenotifier 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4e3734829275bc8aeead72f512c54f2f231107cc
4
+ data.tar.gz: 89a57be90341fffa93dde5330a720674cefb7fb8
5
+ SHA512:
6
+ metadata.gz: 6e9c2ffb89b32befa95b9b9266b1bb1a50480fd4c9336cdb5ee8500db084a16b868e0646d81e9dbba0529a0039faf223b89997dd2d927a0fc2a7593bfe33bbcf
7
+ data.tar.gz: 96ff4fd29d4dc8df0e44ec2e09ad1a0e4c91a88a7d48c320d651483b1842d4839cd19342371d49f82b12e08f599a8452e875fb98984d267f75bf272118e2c955
data/Gemfile ADDED
@@ -0,0 +1,24 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "activesupport", "~> 4.0"
4
+
5
+ group :development do
6
+ gem "rspec", "~> 3.0"
7
+ gem "yard", "~> 0.7"
8
+ gem "rdoc", "~> 3.12"
9
+ gem "bundler", "~> 1.0"
10
+ gem "jeweler", "~> 2.0.1"
11
+ gem "simplecov", ">= 0"
12
+
13
+
14
+ # Testing :email channel
15
+ gem "actionmailer", "~> 4.0"
16
+
17
+ # Testing :push channel
18
+ gem "active_model_serializers", "~> 0.9.3"
19
+ gem "pushmeup", "~> 0.3.0"
20
+ gem "activejob", "~> 4.0"
21
+
22
+ gem "guard", "~> 2.0"
23
+ gem "guard-rspec", "~> 4.5.0", require: false
24
+ end
@@ -0,0 +1,190 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (4.2.1)
5
+ actionpack (= 4.2.1)
6
+ actionview (= 4.2.1)
7
+ activejob (= 4.2.1)
8
+ mail (~> 2.5, >= 2.5.4)
9
+ rails-dom-testing (~> 1.0, >= 1.0.5)
10
+ actionpack (4.2.1)
11
+ actionview (= 4.2.1)
12
+ activesupport (= 4.2.1)
13
+ rack (~> 1.6)
14
+ rack-test (~> 0.6.2)
15
+ rails-dom-testing (~> 1.0, >= 1.0.5)
16
+ rails-html-sanitizer (~> 1.0, >= 1.0.1)
17
+ actionview (4.2.1)
18
+ activesupport (= 4.2.1)
19
+ builder (~> 3.1)
20
+ erubis (~> 2.7.0)
21
+ rails-dom-testing (~> 1.0, >= 1.0.5)
22
+ rails-html-sanitizer (~> 1.0, >= 1.0.1)
23
+ active_model_serializers (0.9.3)
24
+ activemodel (>= 3.2)
25
+ activejob (4.2.1)
26
+ activesupport (= 4.2.1)
27
+ globalid (>= 0.3.0)
28
+ activemodel (4.2.1)
29
+ activesupport (= 4.2.1)
30
+ builder (~> 3.1)
31
+ activesupport (4.2.1)
32
+ i18n (~> 0.7)
33
+ json (~> 1.7, >= 1.7.7)
34
+ minitest (~> 5.1)
35
+ thread_safe (~> 0.3, >= 0.3.4)
36
+ tzinfo (~> 1.1)
37
+ addressable (2.3.8)
38
+ builder (3.2.2)
39
+ celluloid (0.16.0)
40
+ timers (~> 4.0.0)
41
+ coderay (1.1.0)
42
+ descendants_tracker (0.0.4)
43
+ thread_safe (~> 0.3, >= 0.3.1)
44
+ diff-lcs (1.2.5)
45
+ docile (1.1.5)
46
+ erubis (2.7.0)
47
+ faraday (0.9.1)
48
+ multipart-post (>= 1.2, < 3)
49
+ ffi (1.9.8)
50
+ formatador (0.2.5)
51
+ git (1.2.9.1)
52
+ github_api (0.12.3)
53
+ addressable (~> 2.3)
54
+ descendants_tracker (~> 0.0.4)
55
+ faraday (~> 0.8, < 0.10)
56
+ hashie (>= 3.3)
57
+ multi_json (>= 1.7.5, < 2.0)
58
+ nokogiri (~> 1.6.3)
59
+ oauth2
60
+ globalid (0.3.5)
61
+ activesupport (>= 4.1.0)
62
+ guard (2.12.5)
63
+ formatador (>= 0.2.4)
64
+ listen (~> 2.7)
65
+ lumberjack (~> 1.0)
66
+ nenv (~> 0.1)
67
+ notiffany (~> 0.0)
68
+ pry (>= 0.9.12)
69
+ shellany (~> 0.0)
70
+ thor (>= 0.18.1)
71
+ guard-compat (1.2.1)
72
+ guard-rspec (4.5.0)
73
+ guard (~> 2.1)
74
+ guard-compat (~> 1.1)
75
+ rspec (>= 2.99.0, < 4.0)
76
+ hashie (3.4.1)
77
+ highline (1.7.2)
78
+ hitimes (1.2.2)
79
+ httparty (0.13.3)
80
+ json (~> 1.8)
81
+ multi_xml (>= 0.5.2)
82
+ i18n (0.7.0)
83
+ jeweler (2.0.1)
84
+ builder
85
+ bundler (>= 1.0)
86
+ git (>= 1.2.5)
87
+ github_api
88
+ highline (>= 1.6.15)
89
+ nokogiri (>= 1.5.10)
90
+ rake
91
+ rdoc
92
+ json (1.8.2)
93
+ jwt (1.5.0)
94
+ listen (2.10.0)
95
+ celluloid (~> 0.16.0)
96
+ rb-fsevent (>= 0.9.3)
97
+ rb-inotify (>= 0.9)
98
+ loofah (2.0.1)
99
+ nokogiri (>= 1.5.9)
100
+ lumberjack (1.0.9)
101
+ mail (2.6.3)
102
+ mime-types (>= 1.16, < 3)
103
+ method_source (0.8.2)
104
+ mime-types (2.4.3)
105
+ mini_portile (0.6.2)
106
+ minitest (5.6.0)
107
+ multi_json (1.11.0)
108
+ multi_xml (0.5.5)
109
+ multipart-post (2.0.0)
110
+ nenv (0.2.0)
111
+ nokogiri (1.6.6.2)
112
+ mini_portile (~> 0.6.0)
113
+ notiffany (0.0.6)
114
+ nenv (~> 0.1)
115
+ shellany (~> 0.0)
116
+ oauth2 (1.0.0)
117
+ faraday (>= 0.8, < 0.10)
118
+ jwt (~> 1.0)
119
+ multi_json (~> 1.3)
120
+ multi_xml (~> 0.5)
121
+ rack (~> 1.2)
122
+ pry (0.10.1)
123
+ coderay (~> 1.1.0)
124
+ method_source (~> 0.8.1)
125
+ slop (~> 3.4)
126
+ pushmeup (0.3.0)
127
+ httparty
128
+ json
129
+ rack (1.6.1)
130
+ rack-test (0.6.3)
131
+ rack (>= 1.0)
132
+ rails-deprecated_sanitizer (1.0.3)
133
+ activesupport (>= 4.2.0.alpha)
134
+ rails-dom-testing (1.0.6)
135
+ activesupport (>= 4.2.0.beta, < 5.0)
136
+ nokogiri (~> 1.6.0)
137
+ rails-deprecated_sanitizer (>= 1.0.1)
138
+ rails-html-sanitizer (1.0.2)
139
+ loofah (~> 2.0)
140
+ rake (10.4.2)
141
+ rb-fsevent (0.9.4)
142
+ rb-inotify (0.9.5)
143
+ ffi (>= 0.5.0)
144
+ rdoc (3.12.2)
145
+ json (~> 1.4)
146
+ rspec (3.2.0)
147
+ rspec-core (~> 3.2.0)
148
+ rspec-expectations (~> 3.2.0)
149
+ rspec-mocks (~> 3.2.0)
150
+ rspec-core (3.2.3)
151
+ rspec-support (~> 3.2.0)
152
+ rspec-expectations (3.2.1)
153
+ diff-lcs (>= 1.2.0, < 2.0)
154
+ rspec-support (~> 3.2.0)
155
+ rspec-mocks (3.2.1)
156
+ diff-lcs (>= 1.2.0, < 2.0)
157
+ rspec-support (~> 3.2.0)
158
+ rspec-support (3.2.2)
159
+ shellany (0.0.1)
160
+ simplecov (0.10.0)
161
+ docile (~> 1.1.0)
162
+ json (~> 1.8)
163
+ simplecov-html (~> 0.10.0)
164
+ simplecov-html (0.10.0)
165
+ slop (3.6.0)
166
+ thor (0.19.1)
167
+ thread_safe (0.3.5)
168
+ timers (4.0.1)
169
+ hitimes
170
+ tzinfo (1.2.2)
171
+ thread_safe (~> 0.1)
172
+ yard (0.8.7.6)
173
+
174
+ PLATFORMS
175
+ ruby
176
+
177
+ DEPENDENCIES
178
+ actionmailer (~> 4.0)
179
+ active_model_serializers (~> 0.9.3)
180
+ activejob (~> 4.0)
181
+ activesupport (~> 4.0)
182
+ bundler (~> 1.0)
183
+ guard (~> 2.0)
184
+ guard-rspec (~> 4.5.0)
185
+ jeweler (~> 2.0.1)
186
+ pushmeup (~> 0.3.0)
187
+ rdoc (~> 3.12)
188
+ rspec (~> 3.0)
189
+ simplecov
190
+ yard (~> 0.7)
@@ -0,0 +1,77 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features)
6
+
7
+ ## Uncomment to clear the screen before every task
8
+ # clearing :on
9
+
10
+ ## Guard internally checks for changes in the Guardfile and exits.
11
+ ## If you want Guard to automatically start up again, run guard in a
12
+ ## shell loop, e.g.:
13
+ ##
14
+ ## $ while bundle exec guard; do echo "Restarting Guard..."; done
15
+ ##
16
+ ## Note: if you are using the `directories` clause above and you are not
17
+ ## watching the project directory ('.'), then you will want to move
18
+ ## the Guardfile to a watched dir and symlink it back, e.g.
19
+ #
20
+ # $ mkdir config
21
+ # $ mv Guardfile config/
22
+ # $ ln -s config/Guardfile .
23
+ #
24
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
25
+
26
+ # Note: The cmd option is now required due to the increasing number of ways
27
+ # rspec may be run, below are examples of the most common uses.
28
+ # * bundler: 'bundle exec rspec'
29
+ # * bundler binstubs: 'bin/rspec'
30
+ # * spring: 'bin/rspec' (This will use spring if running and you have
31
+ # installed the spring binstubs per the docs)
32
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
33
+ # * 'just' rspec: 'rspec'
34
+
35
+ guard :rspec, cmd: "bundle exec rspec", failed_mode: :keep do
36
+ require "guard/rspec/dsl"
37
+ dsl = Guard::RSpec::Dsl.new(self)
38
+
39
+ # Feel free to open issues for suggestions and improvements
40
+
41
+ # RSpec files
42
+ rspec = dsl.rspec
43
+ watch(rspec.spec_helper) { rspec.spec_dir }
44
+ watch(rspec.spec_support) { rspec.spec_dir }
45
+ watch(rspec.spec_files)
46
+
47
+ # Ruby files
48
+ ruby = dsl.ruby
49
+ dsl.watch_spec_files_for(ruby.lib_files)
50
+
51
+ # Rails files
52
+ rails = dsl.rails(view_extensions: %w(erb haml slim))
53
+ dsl.watch_spec_files_for(rails.app_files)
54
+ dsl.watch_spec_files_for(rails.views)
55
+
56
+ watch(rails.controllers) do |m|
57
+ [
58
+ rspec.spec.("routing/#{m[1]}_routing"),
59
+ rspec.spec.("controllers/#{m[1]}_controller"),
60
+ rspec.spec.("acceptance/#{m[1]}")
61
+ ]
62
+ end
63
+
64
+ # Rails config changes
65
+ watch(rails.spec_helper) { rspec.spec_dir }
66
+ watch(rails.routes) { "#{rspec.spec_dir}/routing" }
67
+ watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
68
+
69
+ # Capybara features specs
70
+ watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
71
+
72
+ # Turnip features and steps
73
+ watch(%r{^spec/acceptance/(.+)\.feature$})
74
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
75
+ Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
76
+ end
77
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2015 Skalar AS
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.
@@ -0,0 +1,144 @@
1
+ [![Codeship](https://img.shields.io/codeship/8c098d90-da0a-0132-b325-528f3b81d645.svg?style=plastic)](https://codeship.com/projects/79171)
2
+
3
+ # ActiveNotifier
4
+
5
+ ActiveNotifier makes it easy to send notifications to your end user through
6
+ different channels (push notifications, websockets, email etc).
7
+
8
+
9
+ ## Dependencies
10
+
11
+ ActiveNotifier is queue agnostic by utilizing [ActiveJob][activejob].
12
+
13
+ It does not depend on Rails, so it should be possible to use the gem in other
14
+ ruby projects.
15
+
16
+
17
+ ## Usage
18
+
19
+ This notifier will attempt to deliver a payload via push or direct e-mail:
20
+
21
+ ```ruby
22
+ class LikesController < ApplicationController
23
+ def create
24
+ @like = Like.create(like_params)
25
+ if @like.persisted?
26
+ LikeNotifier.deliver_later({
27
+ recipient: @like.recipient,
28
+ like: @like,
29
+ channels: [:push, :email] # attempts to delivery through push, then email if not possible
30
+ })
31
+ end
32
+ respond_with @like
33
+ end
34
+ end
35
+ ```
36
+
37
+ ```ruby
38
+ # app/notifiers/like_notifier.rb
39
+ class LikeNotifier < ActiveNotifier::Base
40
+ queue_as :like_notifications # default is :notifications
41
+
42
+ attr_accessor :like
43
+
44
+ deliver_through :email do |config|
45
+ config.email_attribute :email_address # defaults to :email
46
+ config.subject "You just received a like"
47
+ end
48
+
49
+ deliver_through :push do |config|
50
+ config.network_attribute :device_network
51
+ config.token_attribute :device_token
52
+ config.serializer Notifiers::LikeSerializer
53
+ end
54
+ end
55
+ ```
56
+
57
+ ```erb
58
+ <!-- app/views/notifiers/like/email.html.erb -->
59
+ Hi <%= @recipient.name %>!
60
+
61
+ You just received a like.
62
+ <%= link_to 'View this', like_path(@paylod) %>
63
+ ```
64
+
65
+ ```ruby
66
+ # app/serializers/notifiers/like_serializer.rb
67
+ class LikeSerializer < ApplicationSerializer
68
+ attributes :alert, :badge
69
+
70
+ def alert
71
+ "You've just received a like!"
72
+ end
73
+
74
+ def badge
75
+ object.like.recipient.likes.unread.count
76
+ end
77
+ end
78
+ ```
79
+
80
+
81
+ ## Concepts
82
+
83
+ ### Recipient
84
+
85
+ The recipient of the message. This object should respond to different methods,
86
+ depending on what transports should be supported.
87
+
88
+ ### Channels
89
+
90
+ A way to communicate with your user. ActiveNotifier ships with transports that
91
+ lets you deliver through email and push (given some dependencies are present).
92
+
93
+ #### Email
94
+
95
+ This channel will be available if the `actionmailer` gem is available.
96
+
97
+ ```ruby
98
+ deliver_through :email do |config|
99
+ config.email_attribute :email_address # defaults to :email
100
+ config.subject "You just received a like"
101
+ end
102
+ ```
103
+
104
+ If you want to use another library for sending e-mails, you have to define a
105
+ custom transport. See below.
106
+
107
+ #### Push
108
+
109
+ This channel will be available if the `pushmeup` gem is available.
110
+
111
+ ```ruby
112
+ deliver_through :push do |config|
113
+ config.network_attribute :device_network
114
+ config.token_attribute :device_token
115
+ end
116
+ ```
117
+
118
+
119
+ ### Transports
120
+
121
+ A transport represents a communication channel and a way of delivering a message
122
+ to your user.
123
+
124
+ ActiveNotifier ships with 2 transports
125
+
126
+ * `ActiveNotifier::Transports::ActionMailer`
127
+ * `ActiveNotifier::Transports::Pushmeup`
128
+
129
+
130
+ ## Contributing to active-notifier
131
+
132
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
133
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
134
+ * Fork the project.
135
+ * Start a feature/bugfix branch.
136
+ * Commit and push until you are happy with your contribution.
137
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
138
+ * 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.
139
+
140
+ ## Copyright
141
+
142
+ Copyright (c) 2015 Skalar. See LICENSE.txt for further details.
143
+
144
+ [activejob]: https://github.com/rails/rails/blob/master/activejob
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
17
+ gem.name = "activenotifier"
18
+ gem.homepage = "http://github.com/Skalar/activenotifier"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Library for sending notifications to users}
21
+ gem.description = %Q{Simplifies sending notifications to your end users through multiple channels}
22
+ gem.email = "tt@skalar.no"
23
+ gem.authors = ["Theodor Tonum"]
24
+ gem.files = FileList['*']+FileList['lib/**/*.rb']
25
+ # dependencies defined in Gemfile
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ desc "Code coverage detail"
36
+ task :simplecov do
37
+ ENV['COVERAGE'] = "true"
38
+ Rake::Task['spec'].execute
39
+ end
40
+
41
+ task :default => :spec
42
+
43
+ require 'yard'
44
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,90 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: activenotifier 0.0.1 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "activenotifier"
9
+ s.version = "0.0.1"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Theodor Tonum"]
14
+ s.date = "2015-05-11"
15
+ s.description = "Simplifies sending notifications to your end users through multiple channels"
16
+ s.email = "tt@skalar.no"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "Guardfile",
25
+ "LICENSE.txt",
26
+ "README.md",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "activenotifier.gemspec",
30
+ "lib/active_notifier.rb",
31
+ "lib/active_notifier/base.rb",
32
+ "lib/active_notifier/delivery_impossible.rb",
33
+ "lib/active_notifier/transports.rb",
34
+ "lib/active_notifier/transports/action_mailer.rb",
35
+ "lib/active_notifier/transports/pushmeup.rb"
36
+ ]
37
+ s.homepage = "http://github.com/Skalar/activenotifier"
38
+ s.licenses = ["MIT"]
39
+ s.rubygems_version = "2.4.6"
40
+ s.summary = "Library for sending notifications to users"
41
+
42
+ if s.respond_to? :specification_version then
43
+ s.specification_version = 4
44
+
45
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<activesupport>, ["~> 4.0"])
47
+ s.add_development_dependency(%q<rspec>, ["~> 3.0"])
48
+ s.add_development_dependency(%q<yard>, ["~> 0.7"])
49
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
50
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
51
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
52
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
53
+ s.add_development_dependency(%q<actionmailer>, ["~> 4.0"])
54
+ s.add_development_dependency(%q<active_model_serializers>, ["~> 0.9.3"])
55
+ s.add_development_dependency(%q<pushmeup>, ["~> 0.3.0"])
56
+ s.add_development_dependency(%q<activejob>, ["~> 4.0"])
57
+ s.add_development_dependency(%q<guard>, ["~> 2.0"])
58
+ s.add_development_dependency(%q<guard-rspec>, ["~> 4.5.0"])
59
+ else
60
+ s.add_dependency(%q<activesupport>, ["~> 4.0"])
61
+ s.add_dependency(%q<rspec>, ["~> 3.0"])
62
+ s.add_dependency(%q<yard>, ["~> 0.7"])
63
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
64
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
65
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
66
+ s.add_dependency(%q<simplecov>, [">= 0"])
67
+ s.add_dependency(%q<actionmailer>, ["~> 4.0"])
68
+ s.add_dependency(%q<active_model_serializers>, ["~> 0.9.3"])
69
+ s.add_dependency(%q<pushmeup>, ["~> 0.3.0"])
70
+ s.add_dependency(%q<activejob>, ["~> 4.0"])
71
+ s.add_dependency(%q<guard>, ["~> 2.0"])
72
+ s.add_dependency(%q<guard-rspec>, ["~> 4.5.0"])
73
+ end
74
+ else
75
+ s.add_dependency(%q<activesupport>, ["~> 4.0"])
76
+ s.add_dependency(%q<rspec>, ["~> 3.0"])
77
+ s.add_dependency(%q<yard>, ["~> 0.7"])
78
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
79
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
80
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
81
+ s.add_dependency(%q<simplecov>, [">= 0"])
82
+ s.add_dependency(%q<actionmailer>, ["~> 4.0"])
83
+ s.add_dependency(%q<active_model_serializers>, ["~> 0.9.3"])
84
+ s.add_dependency(%q<pushmeup>, ["~> 0.3.0"])
85
+ s.add_dependency(%q<activejob>, ["~> 4.0"])
86
+ s.add_dependency(%q<guard>, ["~> 2.0"])
87
+ s.add_dependency(%q<guard-rspec>, ["~> 4.5.0"])
88
+ end
89
+ end
90
+
@@ -0,0 +1,11 @@
1
+ require 'active_support'
2
+
3
+ module ActiveNotifier
4
+ extend ActiveSupport::Autoload
5
+
6
+ mattr_accessor :logger
7
+
8
+ autoload :Base
9
+ autoload :Transports
10
+ autoload :DeliveryImpossible
11
+ end
@@ -0,0 +1,92 @@
1
+ module ActiveNotifier
2
+ class Base
3
+ attr_accessor :recipient, :channels
4
+
5
+ def initialize(attributes={})
6
+ attributes.each do |(key, value)|
7
+ self.public_send("#{key}=", value)
8
+ end
9
+ end
10
+
11
+ delegate :deliver_now, to: :deliverable
12
+
13
+ def deliver_now
14
+ delivered = false
15
+
16
+ until channels.empty? || delivered
17
+ channel = channels.shift
18
+ begin
19
+ deliverable(channel).deliver_now
20
+ delivered = true
21
+ rescue ActiveNotifier::DeliveryImpossible => e
22
+ delivered = false
23
+ msg = "Unable to deliver to channel #{channel}"
24
+ ActiveNotifier.logger && ActiveNotifier.logger.warn(msg)
25
+ end
26
+ end
27
+ end
28
+
29
+ class << self
30
+ attr_accessor :configurations
31
+
32
+ def deliver_now(attributes)
33
+ new(attributes).deliver_now
34
+ end
35
+
36
+ def deliver_through(channel, &blk)
37
+ self.configurations ||= {}
38
+ config = Configuration.new.tap(&blk)
39
+ configurations[channel] = config
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def deliverable(channel)
46
+ configuration = self.class.configurations[channel]
47
+ transport = ActiveNotifier::Transports.for(channel, configuration, self)
48
+ transport.deliverable(self)
49
+ end
50
+
51
+ class Configuration
52
+ attr_accessor :data
53
+
54
+ def initialize
55
+ @data = {
56
+ from: nil,
57
+ email_attribute: nil,
58
+ subject: nil,
59
+ superclass: ActionMailer::Base
60
+ }
61
+ end
62
+
63
+ delegate :[], to: :data
64
+
65
+ def method_missing(*args, &blk)
66
+ attribute, value = args
67
+ if value.present?
68
+ @data[attribute] = value
69
+ elsif block_given?
70
+ @data[attribute] = blk
71
+ else
72
+ @data.fetch attribute do
73
+ super
74
+ end
75
+ end
76
+ end
77
+
78
+ def respond_to?(*args, &blk)
79
+ attribute, value = args
80
+ if value.present?
81
+ true
82
+ elsif block_given?
83
+ true
84
+ else
85
+ @data.fetch attribute do
86
+ super
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,4 @@
1
+ module ActiveNotifier
2
+ class DeliveryImpossible < StandardError
3
+ end
4
+ end
@@ -0,0 +1,18 @@
1
+ module ActiveNotifier
2
+ module Transports
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :ActionMailer
6
+ autoload :Pushmeup
7
+
8
+ def self.for(channel, configuration, notifier)
9
+ transport_klass = self.constants.map do |klass_name|
10
+ self.const_get(klass_name)
11
+ end.detect do |klass|
12
+ klass.channel == channel
13
+ end || fail("No transport defined for channel '#{channel}'")
14
+
15
+ transport_klass.new(configuration, notifier)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,47 @@
1
+ module ActiveNotifier
2
+ module Transports
3
+ class ActionMailer
4
+ attr_accessor :configuration
5
+ cattr_accessor :channel
6
+
7
+ self.channel = :email
8
+
9
+ def initialize(configuration, notifier)
10
+ self.configuration = configuration
11
+ end
12
+
13
+ def deliverable(notifier)
14
+ email_attribute = configuration.email_attribute
15
+ to = notifier.recipient.public_send(email_attribute)
16
+ if to.blank?
17
+ raise ActiveNotifier::DeliveryImpossible.new("Recipient email not present.")
18
+ end
19
+
20
+ mailer_class(notifier).notification({
21
+ to: to
22
+ })
23
+ end
24
+
25
+ private
26
+ def mailer_class(notifier)
27
+ Class.new(configuration.superclass) do
28
+ cattr_accessor :_template_name, :_from, :_subject
29
+
30
+ def notification(options)
31
+ options.merge!({
32
+ template_path: 'notifiers',
33
+ template_name: _template_name,
34
+ from: _from,
35
+ subject: _subject
36
+ })
37
+ mail(options)
38
+ end
39
+ end.tap do |klass|
40
+ klass._template_name = notifier.class.name.underscore.gsub(/_notifier$/, '')
41
+ klass._from = configuration.from
42
+ klass._subject = configuration.subject
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,93 @@
1
+ require 'active_job'
2
+ require 'delegate'
3
+
4
+ module ActiveNotifier
5
+ module Transports
6
+ class Pushmeup
7
+ attr_accessor :configuration
8
+ cattr_accessor :channel
9
+
10
+ self.channel = :push
11
+
12
+ def initialize(configuration, notifier)
13
+ self.configuration = configuration
14
+ end
15
+
16
+ def deliverable(notifier)
17
+ if configuration[:device_list_attribute]
18
+ devices = notifier.recipient.public_send(configuration[:device_list_attribute])
19
+ else
20
+ devices = Array(notifier.recipient)
21
+ end
22
+
23
+ deliverables = devices.map do |device|
24
+ token_attribute = configuration.token_attribute
25
+ token = device.public_send(token_attribute)
26
+ if token.blank?
27
+ raise ActiveNotifier::DeliveryImpossible.new("Recipient mobile token not present.")
28
+ end
29
+
30
+ network_attribute = configuration.network_attribute
31
+ network = device.public_send(network_attribute)
32
+ if token.blank?
33
+ raise ActiveNotifier::DeliveryImpossible.new("Recipient network token not present.")
34
+ end
35
+
36
+ payload = configuration.serializer.new(notifier).as_json(root: false)
37
+
38
+ Deliverable.new(token, payload, network)
39
+ end
40
+ MultipleDeliverables.new(deliverables)
41
+ end
42
+
43
+ def self.deliver(tokens, payload, network)
44
+ case network
45
+ when 'apns'
46
+ APNS.send_notification(tokens, payload)
47
+ when 'gcm'
48
+ GCM.send_notification(tokens, payload)
49
+ else
50
+ fail "Unrecognized network"
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ class PushNotificationJob < ActiveJob::Base
57
+ queue_as :push_notifications
58
+
59
+ def perform(tokens, payload, network)
60
+ ActiveNotifier::Transports::Pushmeup.deliver(token, payload, network)
61
+ end
62
+ end
63
+
64
+ class Deliverable
65
+ attr_accessor :payload, :tokens, :network
66
+
67
+ def initialize(tokens, payload, network)
68
+ @payload = payload
69
+ @tokens = tokens
70
+ @network = network
71
+ end
72
+
73
+ def deliver_now
74
+ ActiveNotifier::Transports::Pushmeup.deliver(tokens, payload, network)
75
+ end
76
+
77
+ def deliver_later
78
+ PushNotificationJob.perform_later(tokens, payload, network)
79
+ end
80
+ end
81
+
82
+ class MultipleDeliverables < SimpleDelegator
83
+ def deliver_now
84
+ each(&:deliver_now)
85
+ end
86
+
87
+ def deliver_later
88
+ each(&:deliver_now)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
metadata ADDED
@@ -0,0 +1,241 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activenotifier
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Theodor Tonum
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: yard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rdoc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.12'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.12'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: jeweler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.0.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.0.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: actionmailer
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '4.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '4.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: active_model_serializers
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.9.3
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.9.3
139
+ - !ruby/object:Gem::Dependency
140
+ name: pushmeup
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.3.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.3.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: activejob
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '4.0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '4.0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: guard
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '2.0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '2.0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: guard-rspec
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: 4.5.0
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: 4.5.0
195
+ description: Simplifies sending notifications to your end users through multiple channels
196
+ email: tt@skalar.no
197
+ executables: []
198
+ extensions: []
199
+ extra_rdoc_files:
200
+ - LICENSE.txt
201
+ - README.md
202
+ files:
203
+ - Gemfile
204
+ - Gemfile.lock
205
+ - Guardfile
206
+ - LICENSE.txt
207
+ - README.md
208
+ - Rakefile
209
+ - VERSION
210
+ - activenotifier.gemspec
211
+ - lib/active_notifier.rb
212
+ - lib/active_notifier/base.rb
213
+ - lib/active_notifier/delivery_impossible.rb
214
+ - lib/active_notifier/transports.rb
215
+ - lib/active_notifier/transports/action_mailer.rb
216
+ - lib/active_notifier/transports/pushmeup.rb
217
+ homepage: http://github.com/Skalar/activenotifier
218
+ licenses:
219
+ - MIT
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: '0'
235
+ requirements: []
236
+ rubyforge_project:
237
+ rubygems_version: 2.4.6
238
+ signing_key:
239
+ specification_version: 4
240
+ summary: Library for sending notifications to users
241
+ test_files: []