bizness 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +57 -0
- data/bizness.gemspec +1 -0
- data/lib/bizness.rb +2 -0
- data/lib/bizness/policy.rb +76 -0
- data/lib/bizness/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6be2ccb0ce9564adc8d96d444dc6be4418c1db7c
|
4
|
+
data.tar.gz: 0d25e8548ffb56eb352e66b974630bc5851a48e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a634804e9296927f0d8e339845d793178ee708e86b631a389178f2c7f03cddcf77b742c177451080e1324fbbfd8280df8e7d2f8501bb9ac39ae06f3d6e146d83
|
7
|
+
data.tar.gz: 25b120fc67cf176b01b002db976eda1c3e254030d75d14fa3d1ba1a38b74e0585be33cebef77524f4d6eea84b4a95bb41f1a5a451e02b659e578bf86a5a79747
|
data/README.md
CHANGED
@@ -84,6 +84,63 @@ op.successful? # True if error is nil
|
|
84
84
|
op.to_h
|
85
85
|
```
|
86
86
|
|
87
|
+
### The Policy module
|
88
|
+
|
89
|
+
Operations are expected to run to completion, otherwise a runtime error should be raised. Before executing an operation, you should generally ensure that the object or objects being operated against pass a certain set of criteria.
|
90
|
+
|
91
|
+
We typically wrap this set of criteria in a Policy object, and if the object passes the policy we kick off the operation. You can call this policy during input validation and return the violations to the end user. However, we also like to use the policy object inside the operation as a final guard before running the operation. If the policy fails, we raise a runtime exception containing the list of violations.
|
92
|
+
|
93
|
+
Since this is such a common pattern, we created the `Bizness::Policy` module. Here's an example:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
class StringFormatPolicy
|
97
|
+
include Bizness::Policy
|
98
|
+
|
99
|
+
attr_reader :string
|
100
|
+
|
101
|
+
def initialize(string:)
|
102
|
+
@string = string
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def alphanumeric?
|
108
|
+
string.match(/^[[:alpha:]]+$/)
|
109
|
+
end
|
110
|
+
|
111
|
+
def all_caps?
|
112
|
+
string == string.upcase
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
policy = StringFormatPolicy.new(string: "abc123")
|
117
|
+
policy.successful?
|
118
|
+
#=> false
|
119
|
+
|
120
|
+
policy.violations
|
121
|
+
#=> ["String must be alphanumeric", "Characters must be all uppercase"]
|
122
|
+
```
|
123
|
+
|
124
|
+
By including the module, the object gets the `successful?` method which does the following when called:
|
125
|
+
|
126
|
+
1. Introspects all private predicate methods (methods that end with a question mark) and executes them
|
127
|
+
2. If the method returns false, it looks for a translation in an I18n YAML file
|
128
|
+
3. It composes an 118n key using the policy's class and method name (without the question mark). For example: `policies.mock_policy.violations.all_caps`
|
129
|
+
4. It adds the result of the translation to the list of `violations`
|
130
|
+
5. It returns false if any violations are found
|
131
|
+
|
132
|
+
An example I18n translation file looks like this:
|
133
|
+
|
134
|
+
```
|
135
|
+
# en.yml
|
136
|
+
en:
|
137
|
+
policies:
|
138
|
+
mock_policy:
|
139
|
+
violations:
|
140
|
+
all_caps: "Characters must be all uppercase"
|
141
|
+
alphanumeric: "String must be alphanumeric"
|
142
|
+
```
|
143
|
+
|
87
144
|
### Pubsub
|
88
145
|
|
89
146
|
#### Publishing
|
data/bizness.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "activerecord"
|
22
|
+
spec.add_dependency "i18n"
|
22
23
|
spec.add_dependency "hey-pubsub", "~> 0.2.0"
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.10"
|
24
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
data/lib/bizness.rb
CHANGED
@@ -2,6 +2,7 @@ require "bizness/version"
|
|
2
2
|
require "active_record"
|
3
3
|
require "forwardable"
|
4
4
|
require "hey"
|
5
|
+
require "i18n"
|
5
6
|
|
6
7
|
module Bizness
|
7
8
|
def self.configure
|
@@ -24,6 +25,7 @@ end
|
|
24
25
|
|
25
26
|
require "bizness/configuration"
|
26
27
|
require "bizness/operation"
|
28
|
+
require "bizness/policy"
|
27
29
|
require "bizness/subscriber"
|
28
30
|
require "bizness/filters/base_filter"
|
29
31
|
require "bizness/filters/active_record_transaction_filter"
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Adds convenience methods for defining a policy object and recording its violations. To take use this module, do the
|
2
|
+
# following:
|
3
|
+
#
|
4
|
+
# 1. Write one or more private predicate methods that define your policies requirements
|
5
|
+
# 2. Define violation messages in your corresponding I18n locale YAML files
|
6
|
+
#
|
7
|
+
# -- string_format_policy.rb
|
8
|
+
#
|
9
|
+
# class StringFormatPolicy
|
10
|
+
# include Bizness::Policy
|
11
|
+
#
|
12
|
+
# def initialize(string)
|
13
|
+
# @string = string
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# private
|
17
|
+
#
|
18
|
+
# attr_reader :string
|
19
|
+
#
|
20
|
+
# def all_caps?
|
21
|
+
# string.upcase == string
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# -- en.yml
|
26
|
+
#
|
27
|
+
# en:
|
28
|
+
# policies:
|
29
|
+
# string_format_policy:
|
30
|
+
# violations:
|
31
|
+
# all_caps: "Must be an uppercase string"
|
32
|
+
#
|
33
|
+
# Example usage:
|
34
|
+
#
|
35
|
+
# policy = StringFormatPolicy.new("abcd")
|
36
|
+
# policy.successful?
|
37
|
+
# => false
|
38
|
+
#
|
39
|
+
# policy.violations
|
40
|
+
# => ["Must be an uppercase string"]
|
41
|
+
#
|
42
|
+
module Bizness::Policy
|
43
|
+
def self.included(base)
|
44
|
+
base.extend(ClassMethods)
|
45
|
+
end
|
46
|
+
|
47
|
+
def violations
|
48
|
+
@violations || []
|
49
|
+
end
|
50
|
+
|
51
|
+
def successful?
|
52
|
+
self.violations = []
|
53
|
+
self.class.__requirements__.each do |m|
|
54
|
+
self.violations << self.class.violation_message(m) unless send(m)
|
55
|
+
end
|
56
|
+
violations.empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
module ClassMethods
|
60
|
+
def violation_message(method)
|
61
|
+
policy = self.name.gsub(/(.)([A-Z])/,'\1_\2').downcase
|
62
|
+
message_key = "policies.#{policy}.violations.#{method.to_s.delete("?")}"
|
63
|
+
I18n.t(message_key)
|
64
|
+
end
|
65
|
+
|
66
|
+
def __requirements__
|
67
|
+
@__requirements__ ||= begin
|
68
|
+
private_instance_methods(false).select { |m| m.to_s[/\?$/] }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
attr_writer :violations
|
76
|
+
end
|
data/lib/bizness/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bizness
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ShippingEasy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: i18n
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: hey-pubsub
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,6 +131,7 @@ files:
|
|
117
131
|
- lib/bizness/filters/base_filter.rb
|
118
132
|
- lib/bizness/filters/event_filter.rb
|
119
133
|
- lib/bizness/operation.rb
|
134
|
+
- lib/bizness/policy.rb
|
120
135
|
- lib/bizness/subscriber.rb
|
121
136
|
- lib/bizness/version.rb
|
122
137
|
homepage: ''
|