tram-policy 1.0.0 → 2.1.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
- SHA1:
3
- metadata.gz: 54f65bae74cb48be0cc7d481cb3abd8528f43749
4
- data.tar.gz: 4a100e49ec40986bc4f8781304169e6ecd2d5baf
2
+ SHA256:
3
+ metadata.gz: 3bf029c2eff265f0a29f13d7f1c44b8f8a1a9d5a336a61a9804c9740142eba17
4
+ data.tar.gz: ccee1509e523eeb4e55208b357e561f03100844d32ec3a14d879ad6991b8f538
5
5
  SHA512:
6
- metadata.gz: 107d99cdd79742b7ae85b5b1f8783f5eb6114c864cbfb7732251c2a4542261effec81ec171d61dbc0da6787ca576efc581dae43f76f75ef4a16d2d7934edea9f
7
- data.tar.gz: 3dc2b45735369a9097b525b1681ea8dee24ed84675bc8cfde67b1f87394647f345abedd45db4c12d3725d3cd56df8193e70b8c92e5ec62e9e1c14970097c6ee8
6
+ metadata.gz: d193c0d20344f0ab8c2b015e7a5eee330ef4fec64182c298ad750b06081894d6d8f51d89c064bc8aa7561e7f8d68ccd3f03f55a4378677781ba0bdf4e8376cd0
7
+ data.tar.gz: 0b0214db5420f51dadb31028d1a75b2cb54b762ccf013d6948a6eb47fb2b6ca4825dfe747921b80aa732de0b27e89faf74a353a005a5c0237c0267df8681a421
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
  /tmp/
10
10
  /*.gem
11
11
  .rspec_status
12
+ .idea/
data/.travis.yml CHANGED
@@ -8,18 +8,15 @@ script:
8
8
  - bundle exec rubocop
9
9
  rvm:
10
10
  - 2.3.0
11
- - 2.4.0
11
+ - 2.6.2
12
12
  - ruby-head
13
- - jruby-9.1.0.0
14
- - rbx-3
13
+ - jruby-9.2.7.0
14
+ - truffleruby
15
15
  env:
16
16
  global:
17
17
  - JRUBY_OPTS='--dev -J-Xmx1024M'
18
18
  matrix:
19
19
  allow_failures:
20
- - rvm: rbx-3
21
20
  - rvm: ruby-head
22
21
  - rvm: jruby-head
23
- include:
24
- - rvm: jruby-head
25
- before_install: gem install bundler --no-ri --no-rdoc
22
+ - rvm: truffleruby
data/CHANGELOG.md CHANGED
@@ -4,6 +4,35 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [2.1.0] - [2021-11-30]
8
+
9
+ ### Fixed
10
+ - Difference between last positional and keyword arguments in Ruby 3.0+ (mrexox)
11
+
12
+ ## [2.0.1] - [2019-11-14]
13
+
14
+ ### Fixed
15
+ - Allow translation :scope to be customized in the #merge operation (sclinede)
16
+ Before the fix, the customized value was always replaced by the default value.
17
+
18
+ ## [2.0.0] - [2019-07-04]
19
+
20
+ ### Changed
21
+
22
+ - [BREAKING] separate `Tram::Policy::Errors` from a policy (nepalez, sclinede)
23
+
24
+ Instead of the policy, the collection refers to the explicit scope used for error messages' translation.
25
+ This change breaks the signature of `Tram::Policy::Error` and `Tram::Policy::Errors`.
26
+
27
+ ## [1.0.1] - [2019-05-06]
28
+
29
+ ### Added
30
+ - Support of `dry-initializer` v3.0+ (nepalez)
31
+
32
+ ### Fixed
33
+ - Fix be_invalid RSpec matcher if non-policy model is passed (Envek)
34
+ - Disable translation check for non-strings in rspec matcher (Envek)
35
+
7
36
  ## [1.0.0] - [2018-02-17]
8
37
 
9
38
  ### Changed
@@ -191,3 +220,8 @@ This is a first public release (@nepalez, @charlie-wasp, @JewelSam, @sergey-chec
191
220
  [0.3.0]: https://github.com/tram-rb/tram-policy/compare/v0.2.5...v0.3.0
192
221
  [0.3.1]: https://github.com/tram-rb/tram-policy/compare/v0.3.0...v0.3.1
193
222
  [0.4.0]: https://github.com/tram-rb/tram-policy/compare/v0.3.1...v0.4.0
223
+ [1.0.0]: https://github.com/tram-rb/tram-policy/compare/v0.4.0...v1.0.0
224
+ [1.0.1]: https://github.com/tram-rb/tram-policy/compare/v1.0.0...v1.0.1
225
+ [2.0.0]: https://github.com/tram-rb/tram-policy/compare/v1.0.1...v2.0.0
226
+ [2.0.1]: https://github.com/tram-rb/tram-policy/compare/v2.0.0...v2.0.1
227
+ [2.1.0]: https://github.com/tram-rb/tram-policy/compare/v2.0.1...v2.1.0
data/README.md CHANGED
@@ -7,7 +7,6 @@ Policy Object Pattern
7
7
 
8
8
  [![Gem Version][gem-badger]][gem]
9
9
  [![Build Status][travis-badger]][travis]
10
- [![Dependency Status][gemnasium-badger]][gemnasium]
11
10
  [![Inline docs][inch-badger]][inch]
12
11
 
13
12
  ## Intro
@@ -128,7 +127,7 @@ You can change the root scope if you will (this could be useful in libraries):
128
127
 
129
128
  ```ruby
130
129
  class MyGemPolicy < Tram::Policy
131
- scope "mygem", "policies" # inherited by subclasses
130
+ root_scope "mygem", "policies" # inherited by subclasses
132
131
  end
133
132
 
134
133
  class Article::ReadinessPolicy < MyGemPolicy
@@ -338,8 +337,6 @@ The gem is available as open source under the terms of the [MIT License](http://
338
337
  [codeclimate]: https://codeclimate.com/github/tram-rb/tram-policy
339
338
  [gem-badger]: https://img.shields.io/gem/v/tram-policy.svg?style=flat
340
339
  [gem]: https://rubygems.org/gems/tram-policy
341
- [gemnasium-badger]: https://img.shields.io/gemnasium/tram-rb/tram-policy.svg?style=flat
342
- [gemnasium]: https://gemnasium.com/tram-rb/tram-policy
343
340
  [inch-badger]: http://inch-ci.org/github/tram-rb/tram-policy.svg
344
341
  [inch]: https://inch-ci.org/github/tram-rb/tram-policy
345
342
  [travis-badger]: https://img.shields.io/travis/tram-rb/tram-policy/master.svg?style=flat
@@ -18,8 +18,8 @@ class Tram::Policy
18
18
  # @param [Object] *args
19
19
  # @return [Tram::Policy]
20
20
  #
21
- def [](*args)
22
- new(*args)
21
+ def [](*args, **kwargs)
22
+ new(*args, **kwargs)
23
23
  end
24
24
 
25
25
  # Sets the root scope of the policy and its subclasses
@@ -12,10 +12,10 @@ class Tram::Policy
12
12
  # If another error is send to the constructor, the error returned unchanged
13
13
  #
14
14
  # @param [Tram::Policy::Error, #to_s] value
15
- # @param [Hash<Symbol, Object>] opts
15
+ # @param [Hash<Symbol, Object>] tags
16
16
  # @return [Tram::Policy::Error]
17
17
  #
18
- def self.new(value, **opts)
18
+ def self.new(value, **tags)
19
19
  value.instance_of?(self) ? value : super
20
20
  end
21
21
 
@@ -27,7 +27,7 @@ class Tram::Policy
27
27
  # @return [Hash<Symbol, Object>] error tags
28
28
  attr_reader :tags
29
29
 
30
- # The list of arguments for [I18n.t]
30
+ # List of arguments for [I18n.t]
31
31
  #
32
32
  # @return [Array]
33
33
  #
@@ -36,7 +36,7 @@ class Tram::Policy
36
36
  end
37
37
  alias to_a item
38
38
 
39
- # The text of error message translated to the current locale
39
+ # Text of error message translated to the current locale
40
40
  #
41
41
  # @return [String]
42
42
  #
@@ -60,8 +60,8 @@ class Tram::Policy
60
60
  # @param [Proc] block
61
61
  # @return [Object]
62
62
  #
63
- def fetch(tag, default = Dry::Initializer::UNDEFINED, &block)
64
- if default == Dry::Initializer::UNDEFINED
63
+ def fetch(tag, default = UNDEFINED, &block)
64
+ if default == UNDEFINED
65
65
  tags.fetch(tag.to_sym, &block)
66
66
  else
67
67
  tags.fetch(tag.to_sym, default, &block)
@@ -92,17 +92,21 @@ class Tram::Policy
92
92
 
93
93
  private
94
94
 
95
+ UNDEFINED = Dry::Initializer::UNDEFINED
96
+ DEFAULT_SCOPE = %w[tram-policy errors].freeze
97
+
95
98
  def initialize(key, **tags)
96
99
  @key = key
97
100
  @tags = tags
101
+ @tags[:scope] = @tags.fetch(:scope) { DEFAULT_SCOPE } if key.is_a?(Symbol)
98
102
  end
99
103
 
100
104
  def respond_to_missing?(*)
101
105
  true
102
106
  end
103
107
 
104
- def method_missing(name, *args, &block)
105
- args.any? || block ? super : tags[name]
108
+ def method_missing(name, *args, **kwargs, &block)
109
+ args.any? || kwargs.any? || block ? super : tags[name]
106
110
  end
107
111
  end
108
112
  end
@@ -1,4 +1,5 @@
1
1
  class Tram::Policy
2
+ #
2
3
  # Enumerable collection of unique unordered validation errors
3
4
  #
4
5
  # Notice: A collection is context-dependent;
@@ -8,11 +9,9 @@ class Tram::Policy
8
9
  class Errors
9
10
  include Enumerable
10
11
 
11
- # @!attribute [r] policy
12
- #
13
- # @return [Tram::Policy] the poplicy errors provided by
14
- #
15
- attr_reader :policy
12
+ # @!attribute [r] scope
13
+ # @return [Array<String>] the scope for error messages' translation
14
+ attr_reader :scope
16
15
 
17
16
  # @!method add(message, tags)
18
17
  # Adds error message to the collection
@@ -22,9 +21,12 @@ class Tram::Policy
22
21
  # @return [self] the collection
23
22
  #
24
23
  def add(message, **tags)
25
- tags = tags.merge(scope: policy.scope) unless tags.key?(:scope)
26
24
  raise ArgumentError.new("Error message should be defined") unless message
27
- tap { @set << Tram::Policy::Error.new(message, **tags) }
25
+
26
+ tap do
27
+ tags = { scope: scope }.merge(tags) if message.is_a?(Symbol)
28
+ @set << Tram::Policy::Error.new(message, **tags)
29
+ end
28
30
  end
29
31
 
30
32
  # Iterates by collected errors
@@ -47,7 +49,7 @@ class Tram::Policy
47
49
  list = each_with_object(Set.new) do |error, obj|
48
50
  obj << error if error.contain?(key, tags)
49
51
  end
50
- self.class.new(policy, list)
52
+ self.class.new(scope: scope, errors: list)
51
53
  end
52
54
 
53
55
  # @!method empty?
@@ -101,9 +103,9 @@ class Tram::Policy
101
103
 
102
104
  private
103
105
 
104
- def initialize(policy, errors = [])
105
- @policy = policy
106
- @set = Set.new(errors)
106
+ def initialize(**options)
107
+ @scope = options[:scope] || Error::DEFAULT_SCOPE
108
+ @set = Set.new options[:errors].to_a
107
109
  end
108
110
  end
109
111
  end
@@ -17,8 +17,11 @@ RSpec::Matchers.define :be_invalid_at do |**tags|
17
17
 
18
18
  def missed_translations
19
19
  @missed_translations ||= \
20
- errors.flat_map { |rec| rec.values_at(*locales) }
21
- .select { |message| message.start_with? "translation missing" }
20
+ errors
21
+ .flat_map { |rec| rec.values_at(*locales) }
22
+ .select do |message|
23
+ message.is_a?(String) && message.start_with?("translation missing")
24
+ end
22
25
  end
23
26
 
24
27
  def report_errors
@@ -57,10 +60,12 @@ end
57
60
 
58
61
  RSpec::Matchers.define :be_invalid do
59
62
  match do |policy|
63
+ return expect(policy.valid?).to(be_falsey) unless policy.is_a?(Tram::Policy)
60
64
  expect(policy).to be_invalid_at
61
65
  end
62
66
 
63
67
  match_when_negated do |policy|
68
+ return expect(policy.valid?).to(be_truthy) unless policy.is_a?(Tram::Policy)
64
69
  expect(policy).not_to be_invalid_at
65
70
  end
66
71
  end
data/lib/tram/policy.rb CHANGED
@@ -40,7 +40,7 @@ module Tram
40
40
  # @return [Tram::Policy::Errors]
41
41
  #
42
42
  def errors
43
- @errors ||= Errors.new(self)
43
+ @errors ||= Errors.new(scope: scope)
44
44
  end
45
45
 
46
46
  # The array of error items for lazy translation
@@ -101,7 +101,7 @@ module Tram
101
101
 
102
102
  private
103
103
 
104
- def initialize(*)
104
+ def initialize(*, **)
105
105
  super
106
106
 
107
107
  self.class.validators.each do |validator|
@@ -1,11 +1,12 @@
1
1
  RSpec.describe Tram::Policy::Error do
2
2
  subject(:error) { described_class.new :bad, options }
3
3
 
4
- let(:options) { { level: "warning", scope: %w[tram-policy] } }
4
+ let(:scope) { %w[tram-policy] }
5
+ let(:options) { { level: "warning", scope: scope } }
5
6
 
6
7
  describe "#item" do
7
8
  subject { error.item }
8
- it { is_expected.to eq [:bad, level: "warning", scope: %w[tram-policy]] }
9
+ it { is_expected.to eq [:bad, level: "warning", scope: scope] }
9
10
  end
10
11
 
11
12
  describe "#message" do
@@ -1,6 +1,6 @@
1
1
  RSpec.describe Tram::Policy::Errors do
2
- let(:policy) { double :policy, scope: %w[tram-policy] }
3
- let(:errors) { described_class.new(policy) }
2
+ let(:scope) { %w[tram-policy] }
3
+ let(:errors) { described_class.new(scope: scope) }
4
4
 
5
5
  describe ".new" do
6
6
  subject { errors }
@@ -8,7 +8,7 @@ RSpec.describe Tram::Policy::Errors do
8
8
  it { is_expected.to be_kind_of Enumerable }
9
9
  it { is_expected.to respond_to :empty? }
10
10
  it { is_expected.to be_empty }
11
- its(:policy) { is_expected.to eql policy }
11
+ its(:scope) { is_expected.to eql scope }
12
12
  end
13
13
 
14
14
  describe "#add" do
@@ -21,7 +21,7 @@ RSpec.describe Tram::Policy::Errors do
21
21
 
22
22
  expect(error).to be_kind_of Tram::Policy::Error
23
23
  expect(error)
24
- .to eq [:omg, level: "info", field: "name", scope: %w[tram-policy]]
24
+ .to eq [:omg, level: "info", field: "name", scope: scope]
25
25
  end
26
26
  end
27
27
 
@@ -45,11 +45,11 @@ RSpec.describe Tram::Policy::Errors do
45
45
  end
46
46
 
47
47
  describe "#merge" do
48
- let(:other) { described_class.new(policy) }
48
+ let(:other) { described_class.new(scope: scope) }
49
49
 
50
50
  before do
51
- errors.add "D'OH!", level: "disaster"
52
- other.add "OUCH!", level: "error"
51
+ errors.add :"D'OH!", level: "disaster"
52
+ other.add "OUCH!", level: "error"
53
53
  end
54
54
 
55
55
  context "without a block:" do
@@ -58,8 +58,8 @@ RSpec.describe Tram::Policy::Errors do
58
58
  it "merges other collection as is" do
59
59
  expect(subject).to be_a Tram::Policy::Errors
60
60
  expect(subject.items).to match_array [
61
- ["D'OH!", level: "disaster", scope: %w[tram-policy]],
62
- ["OUCH!", level: "error", scope: %w[tram-policy]]
61
+ [:"D'OH!", level: "disaster", scope: scope],
62
+ ["OUCH!", level: "error"]
63
63
  ]
64
64
  end
65
65
  end
@@ -70,8 +70,8 @@ RSpec.describe Tram::Policy::Errors do
70
70
  it "merges filtered collection as is" do
71
71
  expect(subject).to be_a Tram::Policy::Errors
72
72
  expect(subject.items).to match_array [
73
- ["D'OH!", level: "disaster", scope: %w[tram-policy]],
74
- ["OUCH!", level: "error", scope: %w[tram-policy], source: "Homer"]
73
+ [:"D'OH!", level: "disaster", scope: scope],
74
+ ["OUCH!", level: "error", source: "Homer"]
75
75
  ]
76
76
  end
77
77
  end
@@ -82,8 +82,8 @@ RSpec.describe Tram::Policy::Errors do
82
82
  it "merges other collection with given options" do
83
83
  expect(subject).to be_a Tram::Policy::Errors
84
84
  expect(subject.items).to match_array [
85
- ["D'OH!", level: "disaster", scope: %w[tram-policy]],
86
- ["OUCH!", level: "error", scope: %w[tram-policy], source: "Homer"]
85
+ [:"D'OH!", level: "disaster", scope: scope],
86
+ ["OUCH!", level: "error", source: "Homer"]
87
87
  ]
88
88
  end
89
89
  end
@@ -94,8 +94,8 @@ RSpec.describe Tram::Policy::Errors do
94
94
  it "merges filtered collection with given options" do
95
95
  expect(subject).to be_a Tram::Policy::Errors
96
96
  expect(subject.items).to match_array [
97
- ["D'OH!", level: "disaster", scope: %w[tram-policy]],
98
- ["OUCH!", level: "error", scope: %w[tram-policy], id: 5, age: 4]
97
+ [:"D'OH!", level: "disaster", scope: scope],
98
+ ["OUCH!", level: "error", id: 5, age: 4]
99
99
  ]
100
100
  end
101
101
  end
@@ -125,8 +125,8 @@ RSpec.describe Tram::Policy::Errors do
125
125
 
126
126
  it "returns selected errors only" do
127
127
  expect(subject).to match_array [
128
- [:foo, field: "name", level: "error", scope: %w[tram-policy]],
129
- [:foo, field: "email", level: "error", scope: %w[tram-policy]]
128
+ [:foo, field: "name", level: "error", scope: scope],
129
+ [:foo, field: "email", level: "error", scope: scope]
130
130
  ]
131
131
  end
132
132
  end
@@ -46,4 +46,19 @@ RSpec.describe "RSpec support:" do
46
46
  .to raise_error RSpec::Expectations::ExpectationNotMetError
47
47
  end
48
48
  end
49
+
50
+ describe "to be_invalid" do
51
+ subject { double("model") }
52
+
53
+ it "fails with valid non-policy object" do
54
+ allow(subject).to receive(:valid?).and_return(true)
55
+ expect { expect(subject).to be_invalid }
56
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
57
+ end
58
+
59
+ it "passes with invalid non-policy object" do
60
+ allow(subject).to receive(:valid?).and_return(false)
61
+ expect { expect(subject).to be_invalid }.not_to raise_error
62
+ end
63
+ end
49
64
  end
@@ -63,8 +63,8 @@ RSpec.describe Tram::Policy do
63
63
  describe "#errors" do
64
64
  subject { policy.errors }
65
65
 
66
- its(:class) { is_expected.to eq Tram::Policy::Errors }
67
- its(:policy) { is_expected.to eql policy }
66
+ its(:class) { is_expected.to eq Tram::Policy::Errors }
67
+ its(:scope) { is_expected.to eql policy.scope }
68
68
  end
69
69
 
70
70
  describe "#valid?" do
data/tram-policy.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = "tram-policy"
3
- gem.version = "1.0.0"
3
+ gem.version = "2.1.0"
4
4
  gem.author = ["Viktor Sokolov (gzigzigzeo)", "Andrew Kozin (nepalez)"]
5
5
  gem.email = "andrew.kozin@gmail.com"
6
- gem.homepage = "https://github.com/tram/tram-policy"
6
+ gem.homepage = "https://github.com/tram-rb/tram-policy"
7
7
  gem.summary = "Policy Object Pattern"
8
8
  gem.license = "MIT"
9
9
 
@@ -14,7 +14,7 @@ Gem::Specification.new do |gem|
14
14
 
15
15
  gem.required_ruby_version = ">= 2.3"
16
16
 
17
- gem.add_runtime_dependency "dry-initializer", "~> 2.0"
17
+ gem.add_runtime_dependency "dry-initializer", "> 2", "< 4"
18
18
  gem.add_runtime_dependency "i18n", "~> 1.0"
19
19
 
20
20
  gem.add_development_dependency "rake", "> 10"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tram-policy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Viktor Sokolov (gzigzigzeo)
@@ -9,22 +9,28 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-02-17 00:00:00.000000000 Z
12
+ date: 2021-11-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dry-initializer
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">"
19
+ - !ruby/object:Gem::Version
20
+ version: '2'
21
+ - - "<"
19
22
  - !ruby/object:Gem::Version
20
- version: '2.0'
23
+ version: '4'
21
24
  type: :runtime
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
24
27
  requirements:
25
- - - "~>"
28
+ - - ">"
29
+ - !ruby/object:Gem::Version
30
+ version: '2'
31
+ - - "<"
26
32
  - !ruby/object:Gem::Version
27
- version: '2.0'
33
+ version: '4'
28
34
  - !ruby/object:Gem::Dependency
29
35
  name: i18n
30
36
  requirement: !ruby/object:Gem::Requirement
@@ -154,7 +160,7 @@ files:
154
160
  - spec/tram/policy/validation_error_spec.rb
155
161
  - spec/tram/policy_spec.rb
156
162
  - tram-policy.gemspec
157
- homepage: https://github.com/tram/tram-policy
163
+ homepage: https://github.com/tram-rb/tram-policy
158
164
  licenses:
159
165
  - MIT
160
166
  metadata: {}
@@ -173,8 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
179
  - !ruby/object:Gem::Version
174
180
  version: '0'
175
181
  requirements: []
176
- rubyforge_project:
177
- rubygems_version: 2.6.14
182
+ rubygems_version: 3.1.6
178
183
  signing_key:
179
184
  specification_version: 4
180
185
  summary: Policy Object Pattern