ruby_dci 0.2.0 → 0.3.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
- SHA256:
3
- metadata.gz: 1b8372e74de2567e52902b236b08aa68779df450995d8a7d83f1d4241d37ede3
4
- data.tar.gz: 13677405fdba528931c0f1b745d4507ac745192b218b363dbcc8a027f93b514c
2
+ SHA1:
3
+ metadata.gz: a61a836ec90dab9c17d7f88cfd866ac24fd7e4ca
4
+ data.tar.gz: 892f6b68acb2b87b6ef653c6c19860b3eac95c37
5
5
  SHA512:
6
- metadata.gz: 8f6a20d6b9de2c3eb81d18c845c34a073848dcf31e401fbe263674dbf0bd4e2a2960c21820948f3ece3cfb65d22b10ba564c53d30cb0e82315a8b2ebce423c7f
7
- data.tar.gz: 6e750cba64ddb92652af80f1364b33c2c53b5c3ee02407203de45fd39f842056ecb4bb0d327a671c98afaf52712fb23afdeba000ae4de55b4303827b35031db7
6
+ metadata.gz: 3f81879bf07b9d8d4c335f9e7c53783edaf19d0cc3e1f0b6abf5f26d11edd3f696bfacd017925778f9d7b7fb93abc3258af419e27481f7cb5d0689e8c7430277
7
+ data.tar.gz: 888c5768b1f5c9d35454173eb91103ce3ad40914cb39f99e22b4898190e3b084fd033f3703d16b5eb725f39cc79ad03fc9c3be6ae2b40cafb06b663d2b74c89b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 0.3.0 (2018-05-24)
2
+
3
+ Features:
4
+
5
+ - Renamed `DCI::Configuration` accessors. `event_routes` is now `routes`, `route_methods` is now `router`, `raise_in_event_router` is now `raise_in_router`.
6
+ - `events` is not an instance variable defined in the context anymore, but has the same access style like the `context` itself. In the role don't push events to `context.events`, but to `context_events`.
7
+
8
+ Bugfixes:
9
+
10
+ - Added specs
11
+ - Added `README.md`
12
+ - Added `CHANGELOG.md`
13
+
1
14
  ## 0.2.0 (2018-05-19)
2
15
 
3
16
  Features:
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) { |repo_name| "https://github.com/#{ repo_name }" }
4
+
5
+ gem "coveralls", require: false
4
6
 
5
7
  # Specify your gem's dependencies in ruby_dci.gemspec
6
8
  gemspec
data/Gemfile.lock CHANGED
@@ -1,13 +1,21 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby_dci (0.2.0)
4
+ ruby_dci (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  coderay (1.1.2)
10
+ coveralls (0.8.21)
11
+ json (>= 1.8, < 3)
12
+ simplecov (~> 0.14.1)
13
+ term-ansicolor (~> 1.3)
14
+ thor (~> 0.19.4)
15
+ tins (~> 1.6)
10
16
  diff-lcs (1.3)
17
+ docile (1.1.5)
18
+ json (2.1.0)
11
19
  method_source (0.9.0)
12
20
  pry (0.11.3)
13
21
  coderay (~> 1.1.0)
@@ -26,12 +34,22 @@ GEM
26
34
  diff-lcs (>= 1.2.0, < 2.0)
27
35
  rspec-support (~> 3.7.0)
28
36
  rspec-support (3.7.1)
37
+ simplecov (0.14.1)
38
+ docile (~> 1.1.0)
39
+ json (>= 1.8, < 3)
40
+ simplecov-html (~> 0.10.0)
41
+ simplecov-html (0.10.2)
42
+ term-ansicolor (1.6.0)
43
+ tins (~> 1.0)
44
+ thor (0.19.4)
45
+ tins (1.16.3)
29
46
 
30
47
  PLATFORMS
31
48
  ruby
32
49
 
33
50
  DEPENDENCIES
34
51
  bundler (~> 1.16)
52
+ coveralls
35
53
  pry (~> 0.11.3)
36
54
  rake (~> 10.0)
37
55
  rspec (~> 3.0)
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  [![Build Status](https://travis-ci.org/egze/ruby_dci.svg?branch=master)](https://travis-ci.org/egze/ruby_dci)
2
+ [![Coverage Status](https://coveralls.io/repos/github/egze/ruby_dci/badge.svg?branch=master)](https://coveralls.io/github/egze/ruby_dci?branch=master)
2
3
 
3
4
  # RubyDci
4
5
 
@@ -9,7 +10,7 @@ A classic DCI implementation for ruby with some extra sugar. I've been using DCI
9
10
  Add this line to your application's Gemfile:
10
11
 
11
12
  ```ruby
12
- gem 'ruby_dci'
13
+ gem 'ruby_dci', require: 'dci'
13
14
  ```
14
15
 
15
16
  And then execute:
@@ -43,8 +44,8 @@ I configure the gem in `config/initializers/dci_configuration.rb`.
43
44
 
44
45
  ```ruby
45
46
  DCI.configure do |config|
46
- config.event_routes = Hash.new([])
47
- config.route_methods = EventRouteStore.new
47
+ config.routes = Hash.new([])
48
+ config.router = EventRouter.new
48
49
  config.transaction_class = ApplicationRecord
49
50
  config.raise_in_event_router = !Rails.env.production?
50
51
  config.on_exception_in_router = -> (exception) {}
@@ -55,7 +56,7 @@ end
55
56
 
56
57
  Usually you want your code to run in a transaction. Either everything runs fine, or nothing is saved. This is done by wrapping the executed code in a transaction block. I use ActiveRecord, but you can use whatever you want. Your class just needs to implement a `transaction` method that takes a block. If you don't want any transactions, you can either skip `config.transaction_class` completely, or set it to `DCI::NullTransaction`.
57
58
 
58
- ### config.event_routes
59
+ ### config.routes
59
60
 
60
61
  This is your mapping of events that may happen in the context. Key is a class name, and the value is an array of method names. Example:
61
62
 
@@ -65,7 +66,7 @@ This is your mapping of events that may happen in the context. Key is a class na
65
66
  }
66
67
  ```
67
68
 
68
- The system will know that it needs to execute `send_product_added_notification` from `config.route_methods` for every event of class `DomainEvents::ProductAddedToCart`. If you don't have any actions that you need to perform after a transaction, the just skip `config.event_routes` completely or set it to `Hash.new([])`.
69
+ The system will know that it needs to execute `send_product_added_notification` from `config.route_methods` for every event of class `DomainEvents::ProductAddedToCart`. If you don't have any actions that you need to perform after a transaction, then just skip `config.event_routes` completely or set it to `Hash.new([])`.
69
70
 
70
71
  I implement events as plain ruby Structs. Example:
71
72
 
@@ -79,12 +80,12 @@ end
79
80
 
80
81
  Why do I do it like this? It makes it easier to add other callbacks later. I can do it in one place instead of searching through hundreds of files. Also makes testing easier.
81
82
 
82
- ### config.route_methods
83
+ ### config.router
83
84
 
84
- This is a class that implements the methods for the `config.event_routes` mapping. Example:
85
+ This is a class that implements the methods for the `config.routes` mapping. Example:
85
86
 
86
87
  ```ruby
87
- class EventRouteStore
88
+ class EventRouter
88
89
 
89
90
  def send_product_added_notification(event)
90
91
  AddedToCartNotificationJob.perform_later(id: event.product.id)
@@ -106,7 +107,7 @@ config.raise_in_event_router = !Rails.env.production?
106
107
  In case there is an exception in the event router, you can provide a handler for the exception. It should be a lambda that receives an exception as a parameter. You can use it to log the exception. If you don't need any logging, just skip `config.on_exception_in_router` completely, or assign an empty lambda.
107
108
 
108
109
  ```ruby
109
- config.logger = -> (exception) { Rails.logger.error(exception) }
110
+ config.on_exception_in_router = -> (exception) { Rails.logger.error(exception) }
110
111
  ```
111
112
 
112
113
 
@@ -142,7 +143,7 @@ Couple of thigs to keep in mind:
142
143
 
143
144
  ### Role
144
145
 
145
- In a Rails app I put my roles in `app/roles`. Roles are plain ruby modules. You define a role by including `DCI::Role`.
146
+ In a Rails app I put my roles in `app/roles`. Roles are plain ruby modules. You define a role by including `DCI::Role`. A role has access to the `context` and to the `context_events` methods. You can push events to `context_events` to process them after the transaction.
146
147
 
147
148
  ```ruby
148
149
  module Customer
@@ -153,7 +154,7 @@ module Customer
153
154
  # do your thing
154
155
 
155
156
  # add event to the context
156
- context.events << DomainEvents::ProductAddedToCart.new(product)
157
+ context_events << DomainEvents::ProductAddedToCart.new(product)
157
158
  end
158
159
 
159
160
  end
data/lib/dci/accessor.rb CHANGED
@@ -5,5 +5,9 @@ module DCI
5
5
  Thread.current[:context]
6
6
  end
7
7
 
8
+ def context_events
9
+ Thread.current[:context_events]
10
+ end
11
+
8
12
  end
9
13
  end
@@ -1,17 +1,19 @@
1
1
  module DCI
2
2
  class Configuration
3
+
3
4
  attr_accessor :transaction_class,
4
- :event_routes,
5
- :route_methods,
6
- :raise_in_event_router,
7
- :on_exception_in_router
5
+ :routes,
6
+ :router,
7
+ :on_exception_in_router,
8
+ :raise_in_router
8
9
 
9
10
  def initialize
10
11
  @transaction_class = NullTransaction
11
- @event_routes = Hash.new([])
12
- @route_methods = nil
13
- @raise_in_event_router = false
14
- @on_exception_in_router = -> (exception) { }
12
+ @routes = Hash.new([])
13
+ @router = nil
14
+ @raise_in_router = false
15
+ @on_exception_in_router = -> (exception) {}
15
16
  end
17
+
16
18
  end
17
19
  end
data/lib/dci/context.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  module DCI
2
-
3
2
  module Context
4
3
 
5
4
  include EventRouter
@@ -16,8 +15,10 @@ module DCI
16
15
 
17
16
  def perform_in_transaction
18
17
  old_context = context
19
- @events = init_context_events
18
+ old_context_events = context_events
19
+
20
20
  self.context = self
21
+ self.context_events = []
21
22
 
22
23
  res = nil
23
24
 
@@ -25,33 +26,40 @@ module DCI
25
26
  res = call
26
27
  end
27
28
 
28
- route_events!(events)
29
+ route_events!(context_events)
29
30
  res
30
31
  ensure
31
32
  self.context = old_context
32
- self.events.clear
33
+ self.context_events = old_context_events
33
34
  end
34
35
 
35
36
  def context=(ctx)
36
37
  Thread.current[:context] = ctx
37
38
  end
38
39
 
40
+ def context_events=(ctx_events = [])
41
+ Thread.current[:context_events] = Array(ctx_events).compact.flatten
42
+ end
43
+
39
44
  def call
40
45
  raise NotImplementedError.new("implement me")
41
46
  end
42
47
 
43
48
  private
49
+
44
50
  def init_context_events
45
51
  []
46
52
  end
53
+
47
54
  end
48
55
 
49
56
  module ClassMethods
57
+
50
58
  def call(*args)
51
59
  new(*args).perform_in_transaction
52
60
  end
61
+
53
62
  end
54
63
 
55
64
  end
56
-
57
65
  end
@@ -1,5 +1,4 @@
1
1
  module DCI
2
-
3
2
  module EventRouter
4
3
 
5
4
  def route_events!(events)
@@ -7,10 +6,11 @@ module DCI
7
6
  end
8
7
 
9
8
  private
9
+
10
10
  def route_event!(event)
11
- DCI.configuration.event_routes[event.class].each do |callback|
11
+ DCI.configuration.routes[event.class].each do |callback|
12
12
  dispatch_catching_standard_errors do
13
- DCI.configuration.route_methods.send(callback, event)
13
+ DCI.configuration.router.send(callback, event)
14
14
  end
15
15
  end
16
16
  end
@@ -21,10 +21,9 @@ module DCI
21
21
  rescue StandardError => exception
22
22
  DCI.configuration.on_exception_in_router.call(exception) rescue nil
23
23
 
24
- raise exception if DCI.configuration.raise_in_event_router
24
+ raise exception if DCI.configuration.raise_in_router
25
25
  end
26
26
  end
27
27
 
28
28
  end
29
-
30
29
  end
@@ -1,7 +1,9 @@
1
1
  module DCI
2
2
  class NullTransaction
3
+
3
4
  def self.transaction
4
5
  yield
5
6
  end
7
+
6
8
  end
7
9
  end
data/lib/dci/version.rb CHANGED
@@ -1,3 +1,5 @@
1
1
  module DCI
2
- VERSION = "0.2.0"
2
+
3
+ VERSION = "0.3.0".freeze
4
+
3
5
  end
data/lib/dci.rb CHANGED
@@ -7,8 +7,11 @@ require "dci/context"
7
7
  require "dci/role"
8
8
 
9
9
  module DCI
10
+
10
11
  class << self
11
- attr_accessor :configuration
12
+
13
+ #attr_accessor :configuration
14
+
12
15
  end
13
16
 
14
17
  def self.configuration
@@ -22,4 +25,5 @@ module DCI
22
25
  def self.configure
23
26
  yield(configuration)
24
27
  end
28
+
25
29
  end
data/ruby_dci.gemspec CHANGED
@@ -13,7 +13,6 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/egze/ruby_dci"
14
14
  spec.license = "MIT"
15
15
 
16
-
17
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
17
  f.match(%r{^(test|spec|features)/})
19
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_dci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksandr Lossenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-19 00:00:00.000000000 Z
11
+ date: 2018-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -115,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
115
  version: '0'
116
116
  requirements: []
117
117
  rubyforge_project:
118
- rubygems_version: 2.7.3
118
+ rubygems_version: 2.6.13
119
119
  signing_key:
120
120
  specification_version: 4
121
121
  summary: Opinionated DCI implementation for ruby.