active_delivery 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '035688fbd824e8e5d02dd88db1e6efca8bdb208383143692b4fd12e1b0d39590'
4
- data.tar.gz: 7be86b0fb03ec57dfcd6c60ec32354d4ba11980b8a960117489ca4be133d2181
3
+ metadata.gz: 49196fc041ea378e47c1a43a527d555b9822398570553d094b5d4ac051fe215b
4
+ data.tar.gz: ad331e02883c5e9bd8c7b07f9acdd531d7aa64cbec0a589dc24ac5ed2f30ad74
5
5
  SHA512:
6
- metadata.gz: 41d29416af71eac7bb70d22c2f4118dfa47ca15d4ba80a6059c1b4c8769c7c07be791b38fc0235aceec1da28f6456bd4c5150fb0bdaa9f3c4d8e4775ce20f836
7
- data.tar.gz: ac251a726f3aafec70461dff4c52646bc3d25c388ec8146d8484957d37f454950e94b756295d8e9f1f59342aa48ade25674287cbb368cf04a1eaf28a3cb6b5ba
6
+ metadata.gz: 2c9f5f9cd717c0bba343c2f2ec2f82390c680a6c5df1561e70ef4e6e913f6dd7204456f0238e0a2c60df25274bf09bd55b2081a5441e793ff9e39c22f40b2fc5
7
+ data.tar.gz: 0c423ef6827bb61f279f18094a9f4e57033086bc8aaac067e8a0c11a71f81e8005d7084b15d263f3d25908bccabdcee302dcec8f427927bc8c3bb27169788a72
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ Gemfile.lock
10
+ Gemfile.local
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --format documentation
2
2
  --color
3
- --require spec_helper
data/.rubocop.yml CHANGED
@@ -1,2 +1,26 @@
1
+ require:
2
+ - standard/cop/semantic_blocks
3
+
1
4
  inherit_gem:
2
- common-rubocop: config/base.yml
5
+ standard: config/base.yml
6
+
7
+ AllCops:
8
+ Exclude:
9
+ - 'bin/*'
10
+ - 'tmp/**/*'
11
+ - 'Gemfile'
12
+ - 'node_modules/**/*'
13
+ - 'vendor/**/*'
14
+ DisplayCopNames: true
15
+
16
+ Standard/SemanticBlocks:
17
+ Enabled: false
18
+
19
+ Style/TrailingCommaInArrayLiteral:
20
+ EnforcedStyleForMultiline: no_comma
21
+
22
+ Style/TrailingCommaInHashLiteral:
23
+ EnforcedStyleForMultiline: no_comma
24
+
25
+ Layout/AlignParameters:
26
+ EnforcedStyle: with_first_parameter
data/.travis.yml ADDED
@@ -0,0 +1,26 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+
6
+ notifications:
7
+ email: false
8
+
9
+ matrix:
10
+ fast_finish: true
11
+ include:
12
+ - rvm: ruby-head
13
+ gemfile: gemfiles/railsmaster.gemfile
14
+ - rvm: 2.5.1
15
+ gemfile: Gemfile
16
+ - rvm: 2.5.1
17
+ gemfile: Gemfile
18
+ env:
19
+ - NO_RAILS=1
20
+ - rvm: 2.4.3
21
+ gemfile: Gemfile
22
+ - rvm: 2.3.1
23
+ gemfile: gemfiles/rails42.gemfile
24
+ allow_failures:
25
+ - rvm: ruby-head
26
+ gemfile: gemfiles/railsmaster.gemfile
data/Gemfile CHANGED
@@ -2,4 +2,12 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem "common-rubocop", path: "../common-rubocop"
5
+ gem "pry-byebug"
6
+
7
+ local_gemfile = File.join(__dir__, "Gemfile.local")
8
+
9
+ if File.exist?(local_gemfile)
10
+ eval(File.read(local_gemfile)) # rubocop:disable Security/Eval
11
+ else
12
+ gem "rails", "~> 5.2"
13
+ end
data/README.md CHANGED
@@ -1,7 +1,49 @@
1
+ [![Gem Version](https://badge.fury.io/rb/active_delivery.svg)](https://badge.fury.io/rb/active_delivery)
2
+ [![Build Status](https://travis-ci.org/palkan/active_delivery.svg?branch=master)](https://travis-ci.org/palkan/active_delivery)
3
+
1
4
  # Active Delivery
2
5
 
3
6
  Framework providing an entrypoint (single _interface_) for all types of notifications: mailers, push notifications, whatever you want.
4
7
 
8
+ <a href="https://evilmartians.com/?utm_source=action_policy">
9
+ <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
10
+
11
+ Requirements:
12
+ - Ruby ~> 2.3
13
+
14
+ **NOTE**: although most of the examples in this readme are Rails-specific, this gem could be used without Rails/ActiveSupport.
15
+
16
+ ## The problem
17
+
18
+ We need a way to handle different notifications _channel_ (mail, push) in one place.
19
+
20
+ From the business-logic point of view we want to _notify_ a user, hence we need a _separate abstraction layer_ as an entrypoint to different types of notifications.
21
+
22
+ ## The solution
23
+
24
+ Here comes the _Active Delivery_.
25
+
26
+ In the simplest case when we have only mailers Active Delivery is just a wrapper for Mailer with (possibly) some additional logic provided (e.g. preventing emails to unsubscribed users).
27
+
28
+ Motivations behind Active Delivery:
29
+ - organize notifications related logic:
30
+
31
+ ```ruby
32
+ # Before
33
+ def after_some_action
34
+ MyMailer.with(user: user).some_action.deliver_later if user.receive_emails?
35
+ NotifyService.send_notification(user, "action") if whatever_else?
36
+ end
37
+
38
+ # After
39
+ def after_some_action
40
+ MyDelivery.with(user: user).notify(:some_action)
41
+ end
42
+ ```
43
+
44
+ - better testability (see [Testing](#testing)).
45
+
46
+
5
47
  ## Usage
6
48
 
7
49
  _Delivery_ class is used to trigger notifications. It describes how to notify a user (e.g. via email or via push notification or both):
@@ -43,6 +85,59 @@ PostsMailer.with(user: user).published(post)
43
85
 
44
86
  See [Rails docs](https://api.rubyonrails.org/classes/ActionMailer/Parameterized.html) for more information on parameterized mailers.
45
87
 
88
+ ## Callbacks support
89
+
90
+ **NOTE:** callbacks are only available if ActiveSupport is present in the app's env.
91
+
92
+ ```ruby
93
+ # Run method before delivering notification
94
+ # NOTE: when `false` is returned the executation is halted
95
+ before_notify :do_something
96
+
97
+ # You can specify a notification method (to run callback only for that method)
98
+ before_notify :do_mail_something, on: :mailer
99
+
100
+ # after_ and around_ callbacks are also supported
101
+ after_notify :cleanup
102
+
103
+ around_notify :set_context
104
+ ```
105
+
106
+ ## Testing
107
+
108
+ **NOTE:** RSpec only for the time being.
109
+
110
+ Active Delivery provides an elegant way to test deliveries in your code (i.e. when you want to test whether a notification has been sent) through a `have_delivered_to` matcher:
111
+
112
+ ```ruby
113
+ it "delivers notification" do
114
+ expect { subject }.to have_delivered_to(Community::EventsDelivery, :modified, event)
115
+ .with(profile: profile)
116
+ ```
117
+
118
+ You can also use such RSpec features as [compound expectations](https://relishapp.com/rspec/rspec-expectations/docs/compound-expectations) and [composed matchers](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/composing-matchers):
119
+
120
+ ```ruby
121
+ it "delivers to rsvped members via .notify" do
122
+ expect { subject }.
123
+ to have_delivered_to(Community::EventsDelivery, :canceled, an_instance_of(event)).with(
124
+ a_hash_including(profile: another_profile)
125
+ ).and have_delivered_to(Community::EventsDelivery, :canceled, event).with(
126
+ profile: profile
127
+ )
128
+ end
129
+ ```
130
+
131
+ If you want to test that no notification is deliver you can use negation:
132
+
133
+ ```ruby
134
+ specify "when event is not found" do
135
+ expect do
136
+ described_class.perform_now(profile.id, "123", "one_hour_before")
137
+ end.not_to have_delivered_to(Community::EventsDelivery)
138
+ end
139
+ ```
140
+
46
141
  ## Contributing
47
142
 
48
143
  Bug reports and pull requests are welcome on GitHub at https://github.com/palkan/active_delivery.
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
+ require "rubocop/rake_task"
3
4
 
5
+ RuboCop::RakeTask.new
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: [:rubocop, :spec]
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  lib = File.expand_path("../lib", __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -14,17 +15,11 @@ Gem::Specification.new do |spec|
14
15
  spec.homepage = "https://github.com/palkan/active_delivery"
15
16
  spec.license = "MIT"
16
17
 
17
- # Specify which files should be added to the gem when it is released.
18
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
- end
22
-
23
- spec.bindir = "exe"
24
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
19
  spec.require_paths = ["lib"]
26
20
 
27
21
  spec.add_development_dependency "bundler", "~> 1.16"
28
22
  spec.add_development_dependency "rake", "~> 10.0"
29
23
  spec.add_development_dependency "rspec", "~> 3.0"
24
+ spec.add_development_dependency "standard", "~> 0.0.12"
30
25
  end
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activesupport", "~> 4.2"
4
+ gem "actionmailer", "~> 4.2"
5
+
6
+ gemspec path: ".."
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", github: "rails/rails"
4
+ gem "rubocop", github: "rubocop-hq/rubocop"
5
+
6
+ gemspec path: ".."
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveDelivery
4
+ # Base class for deliveries.
5
+ #
6
+ # Delivery object describes how to notify a user about
7
+ # an event (e.g. via email or via push notification or both).
8
+ #
9
+ # Delivery class acts like a proxy in front of the different delivery channels
10
+ # (i.e. mailers, notifiers). That means that calling a method on delivery class invokes the
11
+ # same method on the corresponding class, e.g.:
12
+ #
13
+ # EventsDelivery.notify(:one_hour_before, profile, event)
14
+ #
15
+ # # under the hood it calls
16
+ # EventsMailer.one_hour_before(profile, event).deliver_later
17
+ #
18
+ # # and
19
+ # EventsNotifier.one_hour_before(profile, event).notify_later
20
+ #
21
+ # Delivery also supports _parameterized_ calling:
22
+ #
23
+ # EventsDelivery.with(profile: profile).notify(:canceled, event)
24
+ #
25
+ # The parameters could be accessed through `params` instance method (e.g.
26
+ # to implement guard-like logic).
27
+ #
28
+ # When params are presents the parametrized mailer is used, i.e.:
29
+ #
30
+ # EventsMailer.with(profile: profile).canceled(event)
31
+ #
32
+ # See https://api.rubyonrails.org/classes/ActionMailer/Parameterized.html
33
+ class Base
34
+ class << self
35
+ alias with new
36
+
37
+ # Enqueues delivery (i.e. uses #deliver_later for mailers)
38
+ def notify(*args)
39
+ new.notify(*args)
40
+ end
41
+
42
+ # The same as .notify but delivers synchronously
43
+ # (i.e. #deliver_now for mailers)
44
+ def notify!(mid, *args, **hargs)
45
+ notify(mid, *args, **hargs, sync: true)
46
+ end
47
+
48
+ def delivery_lines
49
+ @lines ||= begin
50
+ if superclass.respond_to?(:delivery_lines)
51
+ superclass.delivery_lines.each_with_object({}) do |(key, val), acc|
52
+ acc[key] = val.dup_for(self)
53
+ end
54
+ else
55
+ {}
56
+ end
57
+ end
58
+ end
59
+
60
+ def register_line(line_id, line_class, **options)
61
+ delivery_lines[line_id] = line_class.new(id: line_id, owner: self, **options)
62
+
63
+ instance_eval <<~CODE, __FILE__, __LINE__ + 1
64
+ def #{line_id}(val)
65
+ delivery_lines[:#{line_id}].handler_class = val
66
+ end
67
+
68
+ def #{line_id}_class
69
+ delivery_lines[:#{line_id}].handler_class
70
+ end
71
+ CODE
72
+ end
73
+ end
74
+
75
+ attr_reader :params
76
+
77
+ def initialize(**params)
78
+ @params = params
79
+ @params.freeze
80
+ end
81
+
82
+ # Enqueues delivery (i.e. uses #deliver_later for mailers)
83
+ def notify(mid, *args, sync: false)
84
+ delivery_lines.each do |type, line|
85
+ next if line.handler_class.nil?
86
+ next unless line.notify?(mid)
87
+
88
+ notify_line(type, mid, *args, params: params, sync: sync)
89
+ end
90
+ end
91
+
92
+ # The same as .notify but delivers synchronously
93
+ # (i.e. #deliver_now for mailers)
94
+ def notify!(mid, *args, **hargs)
95
+ notify(mid, *args, **hargs, sync: true)
96
+ end
97
+
98
+ private
99
+
100
+ def notify_line(type, mid, *args)
101
+ delivery_lines[type].notify(mid, *args)
102
+ end
103
+
104
+ def delivery_lines
105
+ self.class.delivery_lines
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/version"
4
+ require "active_support/callbacks"
5
+ require "active_support/concern"
6
+
7
+ module ActiveDelivery
8
+ # Add callbacks support to Active Delivery (requires ActiveSupport::Callbacks)
9
+ #
10
+ # # Run method before delivering notification
11
+ # # NOTE: when `false` is returned the executation is halted
12
+ # before_notify :do_something
13
+ #
14
+ # # You can specify a notification method (to run callback only for that method)
15
+ # before_notify :do_mail_something, on: :mail
16
+ #
17
+ # # or for push notifications
18
+ # before_notify :do_mail_something, on: :push
19
+ #
20
+ # # after_ and around_ callbacks are also supported
21
+ # after_notify :cleanup
22
+ #
23
+ # around_notify :set_context
24
+ module Callbacks
25
+ extend ActiveSupport::Concern
26
+
27
+ include ActiveSupport::Callbacks
28
+
29
+ CALLBACK_TERMINATOR = if ::ActiveSupport::VERSION::MAJOR >= 5
30
+ ->(_target, result) { result.call == false }
31
+ else
32
+ ->(_target, result) { result == false }
33
+ end
34
+
35
+ included do
36
+ # Define "global" callbacks
37
+ define_line_callbacks :notify
38
+
39
+ prepend InstanceExt
40
+ singleton_class.prepend SingltonExt
41
+ end
42
+
43
+ module InstanceExt
44
+ def notify(*)
45
+ run_callbacks(:notify) { super }
46
+ end
47
+
48
+ def notify_line(type, *)
49
+ run_callbacks(type) { super }
50
+ end
51
+ end
52
+
53
+ module SingltonExt
54
+ def register_line(line_id, *args)
55
+ super
56
+ define_line_callbacks line_id
57
+ end
58
+ end
59
+
60
+ class_methods do
61
+ def define_line_callbacks(name)
62
+ define_callbacks name,
63
+ terminator: CALLBACK_TERMINATOR,
64
+ skip_after_callbacks_if_terminated: true
65
+ end
66
+
67
+ def before_notify(method_name, on: :notify)
68
+ set_callback on, :before, method_name
69
+ end
70
+
71
+ def after_notify(method_name, on: :notify)
72
+ set_callback on, :after, method_name
73
+ end
74
+
75
+ def around_notify(method_name, on: :notify)
76
+ set_callback on, :around, method_name
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ ActiveDelivery::Base.include ActiveDelivery::Callbacks
@@ -0,0 +1,55 @@
1
+ module ActiveDelivery
2
+ module Lines
3
+ class Base
4
+ attr_reader :id, :options
5
+ attr_accessor :owner
6
+ attr_writer :handler_class
7
+
8
+ def initialize(id:, owner:, **options)
9
+ @id = id
10
+ @owner = owner
11
+ @options = options.tap(&:freeze)
12
+ end
13
+
14
+ def dup_for(new_owner)
15
+ self.class.new(id: id, **options, owner: new_owner)
16
+ end
17
+
18
+ def resolve_class(name)
19
+ end
20
+
21
+ def notify?(method_name)
22
+ handler_class.respond_to?(method_name)
23
+ end
24
+
25
+ def notify_now(handler, mid, *args)
26
+ end
27
+
28
+ def notify_later(handler, mid, *args)
29
+ end
30
+
31
+ def notify(mid, *args, params:, sync:)
32
+ clazz = params.empty? ? handler_class : handler_class.with(params)
33
+ sync ? notify_now(clazz, mid, *args) : notify_later(clazz, mid, *args)
34
+ end
35
+
36
+ def handler_class
37
+ return @handler_class if instance_variable_defined?(:@handler_class)
38
+
39
+ @handler_class = resolve_class(owner.name) ||
40
+ superclass_handler
41
+ end
42
+
43
+ private
44
+
45
+ def superclass_handler
46
+ handler_method = "#{id}_class"
47
+
48
+ return if ActiveDelivery::Base == owner.superclass
49
+ return unless owner.superclass.respond_to?(handler_method)
50
+
51
+ owner.superclass.public_send(handler_method)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,25 @@
1
+ module ActiveDelivery
2
+ module Lines
3
+ class Mailer < Base
4
+ alias mailer_class handler_class
5
+
6
+ def resolve_class(name)
7
+ name.gsub(/Delivery$/, "Mailer").safe_constantize
8
+ end
9
+
10
+ def notify?(method_name)
11
+ mailer_class.action_methods.include?(method_name.to_s)
12
+ end
13
+
14
+ def notify_now(mailer, mid, *args)
15
+ mailer.public_send(mid, *args).deliver_now
16
+ end
17
+
18
+ def notify_later(mailer, mid, *args)
19
+ mailer.public_send(mid, *args).deliver_later
20
+ end
21
+ end
22
+
23
+ ActiveDelivery::Base.register_line :mailer, Mailer
24
+ end
25
+ end
@@ -0,0 +1,154 @@
1
+ module ActiveDelivery
2
+ class HaveDeliveredTo < RSpec::Matchers::BuiltIn::BaseMatcher
3
+ attr_reader :delivery_class, :event, :args, :params, :sync_value
4
+
5
+ def initialize(delivery_class, event = nil, *args)
6
+ @delivery_class = delivery_class
7
+ @event = event
8
+ @args = args
9
+ set_expected_number(:exactly, 1)
10
+ end
11
+
12
+ def with(params)
13
+ @params = params
14
+ self
15
+ end
16
+
17
+ def synchronously
18
+ @sync_value = true
19
+ self
20
+ end
21
+
22
+ def exactly(count)
23
+ set_expected_number(:exactly, count)
24
+ self
25
+ end
26
+
27
+ def at_least(count)
28
+ set_expected_number(:at_least, count)
29
+ self
30
+ end
31
+
32
+ def at_most(count)
33
+ set_expected_number(:at_most, count)
34
+ self
35
+ end
36
+
37
+ def times
38
+ self
39
+ end
40
+
41
+ def once
42
+ exactly(:once)
43
+ end
44
+
45
+ def twice
46
+ exactly(:twice)
47
+ end
48
+
49
+ def thrice
50
+ exactly(:thrice)
51
+ end
52
+
53
+ def supports_block_expectations?
54
+ true
55
+ end
56
+
57
+ def matches?(proc)
58
+ raise ArgumentError, "have_delivered_to only supports block expectations" unless Proc === proc
59
+
60
+ TestDelivery.enable { proc.call }
61
+
62
+ actual_deliveries = TestDelivery.store
63
+
64
+ @matching_deliveries, @unmatching_deliveries =
65
+ actual_deliveries.partition do |(delivery, actual_event, actual_args, options)|
66
+ next false unless delivery_class === delivery
67
+
68
+ next false unless event.nil? || event == actual_event
69
+ next false unless params.nil? || params === delivery.params
70
+
71
+ next false unless args.each.with_index.all? do |arg, i|
72
+ arg === actual_args[i]
73
+ end
74
+
75
+ next false if !sync_value.nil? && (options.fetch(:sync, false) != sync_value)
76
+
77
+ true
78
+ end
79
+
80
+ @matching_count = @matching_deliveries.size
81
+
82
+ case @expectation_type
83
+ when :exactly then @expected_number == @matching_count
84
+ when :at_most then @expected_number >= @matching_count
85
+ when :at_least then @expected_number <= @matching_count
86
+ end
87
+ end
88
+
89
+ def failure_message
90
+ (+"expected to deliver").tap do |msg|
91
+ msg << " :#{event} notification" if event
92
+ msg << " via #{delivery_class}#{sync_value ? " (sync)" : ""} with:"
93
+ msg << "\n - params: #{params_description(params)}" if params
94
+ msg << "\n - args: #{args.present? ? args : "<none>"}"
95
+ msg << "\n#{message_expectation_modifier}, but"
96
+
97
+ if @unmatching_deliveries.any?
98
+ msg << " delivered the following notifications:"
99
+ @unmatching_deliveries.each do |(delivery, event, args, options)|
100
+ msg << "\n :#{event} via #{delivery.class}" \
101
+ "#{options[:sync] ? " (sync)" : ""}" \
102
+ " with:" \
103
+ "\n - params: #{delivery.params.present? ? delivery.params.to_s : "<none>"}" \
104
+ "\n - args: #{args}"
105
+ end
106
+ else
107
+ msg << " haven't delivered anything"
108
+ end
109
+ end
110
+ end
111
+
112
+ private
113
+
114
+ def set_expected_number(relativity, count)
115
+ @expectation_type = relativity
116
+ @expected_number =
117
+ case count
118
+ when :once then 1
119
+ when :twice then 2
120
+ when :thrice then 3
121
+ else Integer(count)
122
+ end
123
+ end
124
+
125
+ def failure_message_when_negated
126
+ "expected not to deliver #{event ? " :#{event} notification" : ""} via #{delivery_class}"
127
+ end
128
+
129
+ def message_expectation_modifier
130
+ number_modifier = @expected_number == 1 ? "once" : "#{@expected_number} times"
131
+ case @expectation_type
132
+ when :exactly then "exactly #{number_modifier}"
133
+ when :at_most then "at most #{number_modifier}"
134
+ when :at_least then "at least #{number_modifier}"
135
+ end
136
+ end
137
+
138
+ def params_description(data)
139
+ if data.is_a?(RSpec::Matchers::Composable)
140
+ data.description
141
+ else
142
+ data
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ RSpec.configure do |config|
149
+ config.include(Module.new do
150
+ def have_delivered_to(*args)
151
+ ActiveDelivery::HaveDeliveredTo.new(*args)
152
+ end
153
+ end)
154
+ end
@@ -0,0 +1,46 @@
1
+ module ActiveDelivery
2
+ module TestDelivery
3
+ class << self
4
+ def enable
5
+ raise ArgumentError, "block is reauired" unless block_given?
6
+ begin
7
+ clear
8
+ Thread.current[:active_delivery_testing] = true
9
+ yield
10
+ ensure
11
+ Thread.current[:active_delivery_testing] = false
12
+ end
13
+ end
14
+
15
+ def enabled?
16
+ Thread.current[:active_delivery_testing] == true
17
+ end
18
+
19
+ def track(delivery, event, args, options)
20
+ store << [delivery, event, args, options]
21
+ end
22
+
23
+ def store
24
+ @store ||= []
25
+ end
26
+
27
+ def clear
28
+ store.clear
29
+ end
30
+ end
31
+
32
+ def notify(event, *args, **options)
33
+ return super unless test?
34
+ TestDelivery.track(self, event, args, options)
35
+ nil
36
+ end
37
+
38
+ def test?
39
+ TestDelivery.enabled?
40
+ end
41
+ end
42
+ end
43
+
44
+ ActiveDelivery::Base.prepend ActiveDelivery::TestDelivery
45
+
46
+ require "active_delivery/testing/rspec" if defined?(RSpec)
@@ -1,3 +1,3 @@
1
1
  module ActiveDelivery
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,5 +1,8 @@
1
1
  require "active_delivery/version"
2
+ require "active_delivery/base"
3
+ require "active_delivery/callbacks" if defined?(ActiveSupport)
2
4
 
3
- module ActiveDelivery
4
- # Your code goes here...
5
- end
5
+ require "active_delivery/lines/base"
6
+ require "active_delivery/lines/mailer" if defined?(ActionMailer)
7
+
8
+ require "active_delivery/testing" if ENV["RACK_ENV"] == "test" || ENV["RAILS_ENV"] == "test"
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_delivery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
11
  date: 2018-12-20 00:00:00.000000000 Z
12
12
  dependencies:
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: standard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.12
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.12
55
69
  description: Rails framework for managing all types of notifications in one place
56
70
  email:
57
71
  - dementiev.vm@gmail.com
@@ -62,6 +76,7 @@ files:
62
76
  - ".gitignore"
63
77
  - ".rspec"
64
78
  - ".rubocop.yml"
79
+ - ".travis.yml"
65
80
  - Gemfile
66
81
  - LICENSE.txt
67
82
  - README.md
@@ -69,7 +84,15 @@ files:
69
84
  - active_delivery.gemspec
70
85
  - bin/console
71
86
  - bin/setup
87
+ - gemfiles/rails42.gemfile
88
+ - gemfiles/railsmaster.gemfile
72
89
  - lib/active_delivery.rb
90
+ - lib/active_delivery/base.rb
91
+ - lib/active_delivery/callbacks.rb
92
+ - lib/active_delivery/lines/base.rb
93
+ - lib/active_delivery/lines/mailer.rb
94
+ - lib/active_delivery/testing.rb
95
+ - lib/active_delivery/testing/rspec.rb
73
96
  - lib/active_delivery/version.rb
74
97
  homepage: https://github.com/palkan/active_delivery
75
98
  licenses: