pathway 0.0.17 → 0.0.18

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
  SHA1:
3
- metadata.gz: 0f7e4c097fd9029a04f2a89b3cd08f5cc1bf1d04
4
- data.tar.gz: 8ba11ece82c8df606d7a2550fd107c8738ed595a
3
+ metadata.gz: 51bd7ec68ed98d860f4f2703fd052a0649060c3b
4
+ data.tar.gz: 7431743f7a87a6a477520f65a9df64b4702959a8
5
5
  SHA512:
6
- metadata.gz: bbe7728807988d4312337795ab6cb8d203b47541cc210dd3e18e34eb279aa2332a2f48b779312878fb00042ea0339386db5374d9d0ca527b6d8dd6df30a48131
7
- data.tar.gz: 0de4b1d09b9753a8bfb5c6002b789b65d8e28248082c91c43aa6b78b12e857967cb3c2d20d238896068b72dc0bec0a3b349ddf2c63d03a580858f8dbf6f24cb9
6
+ metadata.gz: bca57cec6205c20f2868cda4a35fa764bb1debe0496e76e72cfd00669b2ae6dd19a8d7ee279d37786f3aa61e9f623a6518504c2e7da357d9c380167ea34933d4
7
+ data.tar.gz: 4c62b4c47cf3337f87366032219f9937ef16b7683664fe191067787ebac964b8947c4d278fe86b1b26e32fd4e0427b215cbac81748e267b5e455ea91477baf30
data/README.md CHANGED
@@ -4,9 +4,7 @@
4
4
  [![CircleCI](https://circleci.com/gh/pabloh/pathway/tree/master.svg?style=shield)](https://circleci.com/gh/pabloh/pathway/tree/master)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/pabloh/pathway/badge.svg?branch=master)](https://coveralls.io/github/pabloh/pathway?branch=master)
6
6
 
7
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/pathway`. To experiment with that code, run `bin/console` for an interactive prompt.
8
-
9
- TODO: Delete this and the text above, and describe your gem
7
+ Pathway allows you to encapsulate your app's business logic into operation objects (also known as application services on the DDD lingo).
10
8
 
11
9
  ## Installation
12
10
 
@@ -24,9 +22,113 @@ Or install it yourself as:
24
22
 
25
23
  $ gem install pathway
26
24
 
25
+ ## Introduction
26
+
27
+ Pathway helps you separate your business logic from the rest of your application; regardless if is an HTTP backend, a background processing daemon, etc.
28
+ The main concept Pathway relies upon to build domain logic modules is the operation, this important concept will be explained in detail in the following sections.
29
+
30
+
31
+ Pathway also aims to be easy to use, stay lightweight and modular, avoid unnecessary heavy dependencies, keep the core classes clean from monkey patching and help yielding an organized and uniform codebase.
32
+
27
33
  ## Usage
28
34
 
29
- TODO: Write usage instructions here
35
+ ### Core API and concepts
36
+
37
+ As mentioned earlier the operation is a crucial concept Pathway leverages upon. Operations not only structure your code (using steps as will be explained latter) but also express meaningful business actions. Operations can be thought as use cases too: they represent an activity -to be perform by an actor interacting with the system- which should be understandable by anyone familiar with the business regardless of their technical expertise.
38
+
39
+
40
+ Operations should ideally don't contain any business rules but instead orchestrate and delegate to other more specific subsystems and services. The only logic present then should be glue code or any adaptations required to make interactions with the inner system layers possible.
41
+
42
+ #### Function object protocol (the `call` method)
43
+
44
+ Operations works as function objects, they are callable and hold no state, as such, any object that responds to `call` and returns a result object can be a valid operation and that's the minimal protocol they needs to follow.
45
+ The result object must follow its own protocol as well (and a helper class is provided for that end) but we'll talk about that in a minute.
46
+
47
+ Let's see an example:
48
+
49
+ ```ruby
50
+ class MyFirstOperation
51
+ def call(params)
52
+ result = Repository.create(params)
53
+
54
+ if result.valid?
55
+ Pathway::Result.success(result)
56
+ else
57
+ Pathway::Result.failure(:create_error)
58
+ end
59
+ end
60
+ end
61
+
62
+ result = MyFirstOperation.new.call(foo: 'foobar')
63
+ if result.success?
64
+ puts result.value.inspect
65
+ else
66
+ puts "Error: #{result.error}"
67
+ end
68
+
69
+ ```
70
+
71
+ Note first we are not inheriting from any class nor including any module. This won't be the case in general as `pathway` provides classes to help build your operations, but it serves to illustrate how little is needed to implement one.
72
+
73
+ Also, let's ignore the specifics about `Repository.create(...)`, we just need to know that is some backend service which can return a value.
74
+
75
+
76
+ We now provide a `call` method for our class. It will just check if the result is available and then wrap it into a successful `Result` object when is ok, or a failing one when is not.
77
+ And that's it, you can then call the operation object, check whether it was completed correctly with `success?` and get the resulting value.
78
+
79
+ By following this protocol, you will be able to uniformly apply the same pattern on every HTTP endpoint (or whatever means your app has to communicates with the outside world). The upper layer of the application is now offloading all the domain logic to the operation and only needs to focus on the data transmission details.
80
+
81
+ Maintaining always the same operation protocol will also be very useful when composing them.
82
+
83
+
84
+ #### Operation result
85
+
86
+ As should be evident by now an operation should always return either a successful or failed result. This concepts are represented by following a simple protocol, which `Pathway::Result` subclasses comply.
87
+
88
+ As we seen before, by querying `success?` on the result we can see if the operation we just ran went well, you can also call to `failure?` for a negated version.
89
+
90
+ The actual result value produced by the operation is be accessible at the `value` method and the error description (if there's any) at `error` when the operation fails.
91
+
92
+ To return wrapped values or errors from your operation you can must call to `Pathway::Result.success(value)` or `Pathway::Result.failure(error)`.
93
+
94
+
95
+ It is worth mentioning that when you inherit from `Pathway::Operation` you'll have helper methods at your disposal to create result objects easier, for instance the previous section's example could be written as follows:
96
+
97
+
98
+ ```ruby
99
+ class MyFirstOperation < Pathway::Operation
100
+ def call(params)
101
+ result = Repository.create(params)
102
+
103
+ result.valid? ? success(result) : failure(:create_error)
104
+ end
105
+ end
106
+ ```
107
+
108
+ #### Error objects
109
+ #### Initialization and context
110
+ #### Steps
111
+
112
+ Finally the steps, these are the heart of the `Operation` class and the main reason you will want to inherit your own classes from `Pathway::Operation`.
113
+
114
+ #### Execution process state
115
+ #### Alternative invocation syntaxes and pattern matching DSL
116
+
117
+ ### Plugins
118
+ #### Plugin architecture
119
+
120
+ #### `SimpleAuth` plugin
121
+ #### `DryValidation` plugin
122
+ #### `SequelModels` plugin
123
+ #### `Responder` plugin
124
+
125
+ ### Testing tools
126
+ #### Rspec config
127
+ #### Rspec matchers
128
+
129
+ ## Best practices
130
+ ### Operation object design and organization
131
+ ### Testing recomendations
30
132
 
31
133
  ## Development
32
134
 
@@ -24,7 +24,7 @@ module Pathway
24
24
  module ClassMethods
25
25
  attr_accessor :model_class, :search_field
26
26
 
27
- def model(model_class, search_by: :id, set_result_key: true)
27
+ def model(model_class, search_by: model_class.primary_key, set_result_key: true)
28
28
  self.model_class = model_class
29
29
  self.search_field = search_by
30
30
  self.result_key = Inflecto.underscore(model_class.name.split('::').last).to_sym if set_result_key
@@ -1,3 +1,3 @@
1
1
  module Pathway
2
- VERSION = '0.0.17'
2
+ VERSION = '0.0.18'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pathway
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.17
4
+ version: 0.0.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Herrero
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-25 00:00:00.000000000 Z
11
+ date: 2017-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inflecto