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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bbc62c7f37f2569e45fa1eb3e49262d7724d9153
4
- data.tar.gz: ff4592f89c4ddea5024faf92e1ae91d7d0a02bae
3
+ metadata.gz: 6be2ccb0ce9564adc8d96d444dc6be4418c1db7c
4
+ data.tar.gz: 0d25e8548ffb56eb352e66b974630bc5851a48e3
5
5
  SHA512:
6
- metadata.gz: 6ed4818a1745adc1882e552cbcc1b93a4eef543781d029b4dbeb28120fe7d7c4e70160172880db51396240d21575edd46d9aee712d175ed862427c7cbb1df7ad
7
- data.tar.gz: 7cddc1debfcb6714179ec8d7e3b9590e16865b87901fdfacb69b72087777b39e8b0bdb1b48cd4781d6492723b740062037c617d2f19efd86a68024d70b389ffa
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
@@ -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"
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Bizness
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
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.5.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-09-27 00:00:00.000000000 Z
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: ''