active_delivery 0.0.1 → 0.1.0

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 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: