policy 1.2.0 → 2.0.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 +4 -4
- data/Guardfile +4 -4
- data/README.md +177 -78
- data/config/metrics/flay.yml +1 -1
- data/config/metrics/roodi.yml +2 -2
- data/lib/policy.rb +52 -33
- data/lib/policy/base.rb +122 -0
- data/lib/policy/base/and.rb +38 -0
- data/lib/policy/base/negator.rb +52 -0
- data/lib/policy/base/node.rb +59 -0
- data/lib/policy/base/not.rb +42 -0
- data/lib/policy/base/or.rb +39 -0
- data/lib/policy/base/xor.rb +39 -0
- data/lib/policy/cli.rb +8 -3
- data/lib/policy/cli/attribute.rb +49 -0
- data/lib/policy/cli/locale.erb +1 -2
- data/lib/policy/cli/policy.erb +33 -6
- data/lib/policy/cli/spec.erb +31 -11
- data/lib/policy/follower.rb +54 -94
- data/lib/policy/follower/name_error.rb +53 -0
- data/lib/policy/follower/policies.rb +104 -0
- data/lib/policy/follower/violation_error.rb +60 -0
- data/lib/policy/version.rb +2 -2
- data/policy.gemspec +2 -3
- data/spec/support/composer.rb +28 -0
- data/spec/tests/lib/policy/base/and_spec.rb +62 -0
- data/spec/tests/lib/policy/base/negator_spec.rb +49 -0
- data/spec/tests/lib/policy/base/not_spec.rb +50 -0
- data/spec/tests/lib/policy/base/or_spec.rb +62 -0
- data/spec/tests/lib/policy/base/xor_spec.rb +73 -0
- data/spec/tests/lib/policy/base_spec.rb +123 -0
- data/spec/tests/lib/policy/cli/attribute_spec.rb +52 -0
- data/spec/tests/{policy → lib/policy}/cli_spec.rb +25 -24
- data/spec/tests/lib/policy/follower/name_error_spec.rb +51 -0
- data/spec/tests/lib/policy/follower/policies_spec.rb +156 -0
- data/spec/tests/lib/policy/follower/violation_error_spec.rb +60 -0
- data/spec/tests/lib/policy/follower_spec.rb +153 -0
- data/spec/tests/lib/policy_spec.rb +52 -0
- metadata +43 -44
- data/lib/policy/follower/followed_policies.rb +0 -45
- data/lib/policy/follower/followed_policy.rb +0 -104
- data/lib/policy/follower/names.rb +0 -29
- data/lib/policy/interface.rb +0 -48
- data/lib/policy/validations.rb +0 -28
- data/lib/policy/violation_error.rb +0 -52
- data/spec/features/follower_spec.rb +0 -95
- data/spec/tests/policy/follower/followed_policies_spec.rb +0 -87
- data/spec/tests/policy/follower/followed_policy_spec.rb +0 -117
- data/spec/tests/policy/follower/names_spec.rb +0 -19
- data/spec/tests/policy/follower_spec.rb +0 -220
- data/spec/tests/policy/interface_spec.rb +0 -83
- data/spec/tests/policy/validations_spec.rb +0 -13
- data/spec/tests/policy/violation_error_spec.rb +0 -75
- data/spec/tests/policy_spec.rb +0 -35
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Policy do
|
4
|
+
|
5
|
+
let(:one) { double :one }
|
6
|
+
let(:two) { double :two }
|
7
|
+
|
8
|
+
describe ".and" do
|
9
|
+
|
10
|
+
let(:composer) { Policy::Base::And }
|
11
|
+
|
12
|
+
it "composes policies with And composer" do
|
13
|
+
expect(composer).to receive(:new).with(one, two)
|
14
|
+
described_class.and one, two
|
15
|
+
end
|
16
|
+
|
17
|
+
end # describe .and
|
18
|
+
|
19
|
+
describe ".or" do
|
20
|
+
|
21
|
+
let(:composer) { Policy::Base::Or }
|
22
|
+
|
23
|
+
it "composes policies with Or composer" do
|
24
|
+
expect(composer).to receive(:new).with(one, two)
|
25
|
+
described_class.or one, two
|
26
|
+
end
|
27
|
+
|
28
|
+
end # describe .or
|
29
|
+
|
30
|
+
describe ".xor" do
|
31
|
+
|
32
|
+
let(:composer) { Policy::Base::Xor }
|
33
|
+
|
34
|
+
it "composes policies with Xor composer" do
|
35
|
+
expect(composer).to receive(:new).with(one, two)
|
36
|
+
described_class.xor one, two
|
37
|
+
end
|
38
|
+
|
39
|
+
end # describe .xor
|
40
|
+
|
41
|
+
describe ".not" do
|
42
|
+
|
43
|
+
let(:composer) { Policy::Base::Not }
|
44
|
+
|
45
|
+
it "composes policies with Not composer" do
|
46
|
+
expect(composer).to receive(:new).with(one)
|
47
|
+
described_class.not one
|
48
|
+
end
|
49
|
+
|
50
|
+
end # describe .not
|
51
|
+
|
52
|
+
end # describe Policy
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: policy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kozin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.1'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: adamantium
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.2'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0.2'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: hexx-cli
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,7 +31,7 @@ dependencies:
|
|
45
31
|
- - "~>"
|
46
32
|
- !ruby/object:Gem::Version
|
47
33
|
version: '0.0'
|
48
|
-
type: :
|
34
|
+
type: :development
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
@@ -66,7 +52,7 @@ dependencies:
|
|
66
52
|
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0.3'
|
69
|
-
description: A
|
55
|
+
description: A small library implementing the Policy Object pattern.
|
70
56
|
email: andrew.kozin@gmail.com
|
71
57
|
executables:
|
72
58
|
- policy
|
@@ -101,31 +87,40 @@ files:
|
|
101
87
|
- config/metrics/simplecov.yml
|
102
88
|
- config/metrics/yardstick.yml
|
103
89
|
- lib/policy.rb
|
90
|
+
- lib/policy/base.rb
|
91
|
+
- lib/policy/base/and.rb
|
92
|
+
- lib/policy/base/negator.rb
|
93
|
+
- lib/policy/base/node.rb
|
94
|
+
- lib/policy/base/not.rb
|
95
|
+
- lib/policy/base/or.rb
|
96
|
+
- lib/policy/base/xor.rb
|
104
97
|
- lib/policy/cli.rb
|
98
|
+
- lib/policy/cli/attribute.rb
|
105
99
|
- lib/policy/cli/locale.erb
|
106
100
|
- lib/policy/cli/policy.erb
|
107
101
|
- lib/policy/cli/spec.erb
|
108
102
|
- lib/policy/follower.rb
|
109
|
-
- lib/policy/follower/
|
110
|
-
- lib/policy/follower/
|
111
|
-
- lib/policy/follower/
|
112
|
-
- lib/policy/interface.rb
|
113
|
-
- lib/policy/validations.rb
|
103
|
+
- lib/policy/follower/name_error.rb
|
104
|
+
- lib/policy/follower/policies.rb
|
105
|
+
- lib/policy/follower/violation_error.rb
|
114
106
|
- lib/policy/version.rb
|
115
|
-
- lib/policy/violation_error.rb
|
116
107
|
- policy.gemspec
|
117
|
-
- spec/features/follower_spec.rb
|
118
108
|
- spec/spec_helper.rb
|
109
|
+
- spec/support/composer.rb
|
119
110
|
- spec/tests/bin/policy_spec.rb
|
120
|
-
- spec/tests/policy/
|
121
|
-
- spec/tests/policy/
|
122
|
-
- spec/tests/policy/
|
123
|
-
- spec/tests/policy/
|
124
|
-
- spec/tests/policy/
|
125
|
-
- spec/tests/policy/
|
126
|
-
- spec/tests/policy/
|
127
|
-
- spec/tests/policy/
|
128
|
-
- spec/tests/
|
111
|
+
- spec/tests/lib/policy/base/and_spec.rb
|
112
|
+
- spec/tests/lib/policy/base/negator_spec.rb
|
113
|
+
- spec/tests/lib/policy/base/not_spec.rb
|
114
|
+
- spec/tests/lib/policy/base/or_spec.rb
|
115
|
+
- spec/tests/lib/policy/base/xor_spec.rb
|
116
|
+
- spec/tests/lib/policy/base_spec.rb
|
117
|
+
- spec/tests/lib/policy/cli/attribute_spec.rb
|
118
|
+
- spec/tests/lib/policy/cli_spec.rb
|
119
|
+
- spec/tests/lib/policy/follower/name_error_spec.rb
|
120
|
+
- spec/tests/lib/policy/follower/policies_spec.rb
|
121
|
+
- spec/tests/lib/policy/follower/violation_error_spec.rb
|
122
|
+
- spec/tests/lib/policy/follower_spec.rb
|
123
|
+
- spec/tests/lib/policy_spec.rb
|
129
124
|
homepage: https://github.com/nepalez/policy
|
130
125
|
licenses:
|
131
126
|
- MIT
|
@@ -152,15 +147,19 @@ specification_version: 4
|
|
152
147
|
summary: Policy Objects for Ruby.
|
153
148
|
test_files:
|
154
149
|
- spec/spec_helper.rb
|
155
|
-
- spec/tests/policy_spec.rb
|
150
|
+
- spec/tests/lib/policy_spec.rb
|
151
|
+
- spec/tests/lib/policy/base/or_spec.rb
|
152
|
+
- spec/tests/lib/policy/base/and_spec.rb
|
153
|
+
- spec/tests/lib/policy/base/xor_spec.rb
|
154
|
+
- spec/tests/lib/policy/base/negator_spec.rb
|
155
|
+
- spec/tests/lib/policy/base/not_spec.rb
|
156
|
+
- spec/tests/lib/policy/cli_spec.rb
|
157
|
+
- spec/tests/lib/policy/follower_spec.rb
|
158
|
+
- spec/tests/lib/policy/cli/attribute_spec.rb
|
159
|
+
- spec/tests/lib/policy/base_spec.rb
|
160
|
+
- spec/tests/lib/policy/follower/violation_error_spec.rb
|
161
|
+
- spec/tests/lib/policy/follower/name_error_spec.rb
|
162
|
+
- spec/tests/lib/policy/follower/policies_spec.rb
|
156
163
|
- spec/tests/bin/policy_spec.rb
|
157
|
-
- spec/
|
158
|
-
- spec/tests/policy/follower_spec.rb
|
159
|
-
- spec/tests/policy/interface_spec.rb
|
160
|
-
- spec/tests/policy/validations_spec.rb
|
161
|
-
- spec/tests/policy/follower/followed_policies_spec.rb
|
162
|
-
- spec/tests/policy/follower/followed_policy_spec.rb
|
163
|
-
- spec/tests/policy/follower/names_spec.rb
|
164
|
-
- spec/tests/policy/violation_error_spec.rb
|
165
|
-
- spec/features/follower_spec.rb
|
164
|
+
- spec/support/composer.rb
|
166
165
|
has_rdoc:
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Policy
|
4
|
-
|
5
|
-
module Follower
|
6
|
-
|
7
|
-
# Describes the list of followed policies
|
8
|
-
#
|
9
|
-
# @api private
|
10
|
-
class FollowedPolicies < Hash
|
11
|
-
|
12
|
-
# Registers followed policy with given unique key
|
13
|
-
#
|
14
|
-
# @param [Policy::Follower::FollowedPolicy] policy
|
15
|
-
#
|
16
|
-
# @return [undefined]
|
17
|
-
def add(policy)
|
18
|
-
self[policy.name] = policy
|
19
|
-
end
|
20
|
-
|
21
|
-
# Applies to follower the policies, selected by names
|
22
|
-
#
|
23
|
-
# @param [Policy::Follower] follower
|
24
|
-
# @param [Array<#to_s>] names
|
25
|
-
#
|
26
|
-
# @raise [Policy::ViolationError]
|
27
|
-
# unless all policies are met
|
28
|
-
#
|
29
|
-
# @return [undefined]
|
30
|
-
def apply_to(follower, *names)
|
31
|
-
named_by(names).each { |policy| policy.apply_to(follower) }
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def named_by(list)
|
37
|
-
names = Names.from list
|
38
|
-
names.any? ? names.map(&method(:[])).compact : values
|
39
|
-
end
|
40
|
-
|
41
|
-
end # class FollowedPolicies
|
42
|
-
|
43
|
-
end # module Follower
|
44
|
-
|
45
|
-
end # module Policy
|
@@ -1,104 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Policy
|
4
|
-
|
5
|
-
module Follower
|
6
|
-
|
7
|
-
# Stores the policy to be applied to all instances of the follower
|
8
|
-
#
|
9
|
-
# The policy object can be set either as a constant, or by name
|
10
|
-
# in given namespace. Namespace and policy name can be set separately.
|
11
|
-
#
|
12
|
-
# The separation is used at the {Policy::Follower#apply_policies}.
|
13
|
-
#
|
14
|
-
# @example The policy can be constant
|
15
|
-
# FollowedPolicy.new nil, Foo::Bar::Baz, :baz_policy, :baz
|
16
|
-
#
|
17
|
-
# @example The policy can be name, relative to the namespace
|
18
|
-
# FollowedPolicy.new Foo::Bar, :Baz, :baz_policy, :baz
|
19
|
-
# # Foo::Bar::Baz policy object will be used
|
20
|
-
#
|
21
|
-
# @api private
|
22
|
-
class FollowedPolicy
|
23
|
-
|
24
|
-
# @!scope class
|
25
|
-
# @!method new(namespace, policy, name, *attributes)
|
26
|
-
# Creates the immutable policy to be followed by given object
|
27
|
-
#
|
28
|
-
# @param [Module] namespace
|
29
|
-
# the namespace for the policy, given by name
|
30
|
-
# @param [Class, #to_s] policy
|
31
|
-
# the class for applicable policy
|
32
|
-
# @param [#to_sym, nil] name
|
33
|
-
# the name for the policy
|
34
|
-
# @param [Array<Symbol>] attributes
|
35
|
-
# the list of follower attributes to apply the policy to
|
36
|
-
#
|
37
|
-
# @return [Policy::Follower::FollowedPolicy]
|
38
|
-
# immutable object
|
39
|
-
def initialize(namespace, policy, name, *attributes)
|
40
|
-
@policy = find_policy(namespace, policy)
|
41
|
-
@name = (name || SecureRandom.uuid).to_sym
|
42
|
-
@attributes = check_attributes attributes
|
43
|
-
end
|
44
|
-
|
45
|
-
# @!attribute [r] name
|
46
|
-
# The name for the policy
|
47
|
-
#
|
48
|
-
# @return [Symbol]
|
49
|
-
attr_reader :name
|
50
|
-
|
51
|
-
# @!attribute [r] policy
|
52
|
-
# The policy object class to be followed
|
53
|
-
#
|
54
|
-
# @return [Class]
|
55
|
-
attr_reader :policy
|
56
|
-
|
57
|
-
# @!attribute [r] attributes
|
58
|
-
# The list of follower attributes to be send to the policy object
|
59
|
-
#
|
60
|
-
# @return [Array<Symbol>]
|
61
|
-
attr_reader :attributes
|
62
|
-
|
63
|
-
# Applies the policy to follower instance
|
64
|
-
#
|
65
|
-
# @param [Policy::Follower]
|
66
|
-
# follower
|
67
|
-
#
|
68
|
-
# @raise [Policy::ViolationError]
|
69
|
-
# it the follower doesn't meet the policy
|
70
|
-
#
|
71
|
-
# @return [undefined]
|
72
|
-
def apply_to(follower)
|
73
|
-
policy.apply(*attributes_of(follower))
|
74
|
-
end
|
75
|
-
|
76
|
-
private
|
77
|
-
|
78
|
-
def find_policy(namespace, policy)
|
79
|
-
return policy if policy.instance_of?(Class)
|
80
|
-
instance_eval [namespace, policy].join("::")
|
81
|
-
end
|
82
|
-
|
83
|
-
def attributes_of(follower)
|
84
|
-
attributes.map(&follower.method(:send))
|
85
|
-
end
|
86
|
-
|
87
|
-
def check_attributes(attributes)
|
88
|
-
number = policy.members.count
|
89
|
-
return attributes if attributes.count.equal?(number)
|
90
|
-
fail wrong_number(number, attributes)
|
91
|
-
end
|
92
|
-
|
93
|
-
def wrong_number(number, attributes)
|
94
|
-
ArgumentError.new [
|
95
|
-
"#{ policy } requires #{ number } attribute(s).",
|
96
|
-
"#{ attributes } cannot be assigned."
|
97
|
-
].join(" ")
|
98
|
-
end
|
99
|
-
|
100
|
-
end # class FollowedPolicy
|
101
|
-
|
102
|
-
end # module Follower
|
103
|
-
|
104
|
-
end # module Policy
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Policy
|
4
|
-
|
5
|
-
module Follower
|
6
|
-
|
7
|
-
# Converter of items to array of unique symbols
|
8
|
-
#
|
9
|
-
# @api private
|
10
|
-
module Names
|
11
|
-
|
12
|
-
# Converts items to array of unique symbols
|
13
|
-
#
|
14
|
-
# @example
|
15
|
-
# Policy::Follower::Names.from "foo", [:foo, "bar"], "baz"
|
16
|
-
# # => [:foo, :bar, :baz]
|
17
|
-
#
|
18
|
-
# @param [Array<#to_sym>] items
|
19
|
-
#
|
20
|
-
# @return [Array<Symbol>]
|
21
|
-
def self.from(*items)
|
22
|
-
items.flatten.map(&:to_sym)
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
data/lib/policy/interface.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Policy
|
4
|
-
|
5
|
-
# Policy object interface
|
6
|
-
module Interface
|
7
|
-
|
8
|
-
# @private
|
9
|
-
def self.included(klass)
|
10
|
-
klass.extend(ClassMethods).__send__(:include, Validations)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Container for the policy class methods
|
14
|
-
module ClassMethods
|
15
|
-
|
16
|
-
# Creates and validates the policy object
|
17
|
-
#
|
18
|
-
# @param (see Policy.new)
|
19
|
-
#
|
20
|
-
# @raise (see Policy::Interface#apply)
|
21
|
-
#
|
22
|
-
# @return [undefined]
|
23
|
-
def apply(*attributes)
|
24
|
-
new(*attributes).apply
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
# Returns the list of error messages
|
30
|
-
#
|
31
|
-
# @return [Array<String>]
|
32
|
-
def messages
|
33
|
-
errors.messages.values.flatten
|
34
|
-
end
|
35
|
-
|
36
|
-
# Validates the policy object
|
37
|
-
#
|
38
|
-
# @raise [ViolationError]
|
39
|
-
# if a policy is invalid
|
40
|
-
#
|
41
|
-
# @return [undefined]
|
42
|
-
def apply
|
43
|
-
fail ViolationError.new(self) unless valid?
|
44
|
-
end
|
45
|
-
|
46
|
-
end # class Interface
|
47
|
-
|
48
|
-
end # module Policy
|
data/lib/policy/validations.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "active_model"
|
3
|
-
|
4
|
-
module Policy
|
5
|
-
|
6
|
-
# Wrapper around the ActiveModel::Validations
|
7
|
-
#
|
8
|
-
# Provides shared interface for [Policy::Inteface] and [Policy::Follower].
|
9
|
-
#
|
10
|
-
# @todo Implement it later from scratch without excessive features
|
11
|
-
#
|
12
|
-
# @example
|
13
|
-
# MyClass.include, Policy::Validations
|
14
|
-
#
|
15
|
-
# @private
|
16
|
-
module Validations
|
17
|
-
|
18
|
-
# The implementation for validations
|
19
|
-
IMPLEMENTATION = ActiveModel::Validations
|
20
|
-
|
21
|
-
# @private
|
22
|
-
def self.included(klass)
|
23
|
-
klass.__send__(:include, IMPLEMENTATION)
|
24
|
-
end
|
25
|
-
|
26
|
-
end # module Validations
|
27
|
-
|
28
|
-
end # module Policy
|