tram-policy 0.0.1 → 0.0.2
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/CHANGELOG.md +20 -0
- data/README.md +76 -19
- data/bin/tram-policy +1 -1
- data/lib/tram/policy.rb +10 -5
- data/lib/tram/policy/generator.rb +30 -11
- data/lib/tram/policy/generator/policy.erb +11 -4
- data/lib/tram/policy/generator/policy_spec.erb +17 -8
- data/lib/tram/policy/{matchers.rb → rspec.rb} +25 -6
- data/lib/tram/policy/validator.rb +17 -0
- data/spec/spec_helper.rb +3 -6
- data/spec/tram/policy/{matchers_spec.rb → rspec_spec.rb} +9 -1
- data/spec/tram/policy_spec.rb +23 -1
- data/tram-policy.gemspec +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d61d4df530a82fdee0fffa4c5129421348d60c18
|
4
|
+
data.tar.gz: e129c65a0019df533cad7e2b90981c332572a6be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e11195f58b75868feaacb300a57377dbb5ba1d5955709c6ee589d8729bc7304a685cfe2db9c48f6e0f1a7ffb47c0746def0c9331c262199853662cdf8b6624e
|
7
|
+
data.tar.gz: f3d07ca8653f883a72052abc0c3430845ad4c1d88177a8f266ca02f0c73a4b0e31e367cd658955ea6a129d0668b1d22695bd249926780080a9b7d3bba1caba95
|
data/CHANGELOG.md
CHANGED
@@ -6,8 +6,28 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.0.2] - [2017-04-25]
|
10
|
+
The gem is battle-tested for production (in a real commertial project).
|
11
|
+
|
12
|
+
### Removed
|
13
|
+
- `.validate` with several keys for several validators at once (@nepalez)
|
14
|
+
|
15
|
+
Use a multiline version instead of `validate :foo, :bar`:
|
16
|
+
|
17
|
+
```
|
18
|
+
validate :foo
|
19
|
+
validate :bar
|
20
|
+
```
|
21
|
+
|
22
|
+
### Added
|
23
|
+
- `.validate` supports option `stop_on_failure` (@nepalez)
|
24
|
+
|
25
|
+
### Fixed
|
26
|
+
- Minor bugs in generators (@nepalez)
|
27
|
+
|
9
28
|
## [0.0.1] - [2017-04-18]
|
10
29
|
This is a first public release (@nepalez, @charlie-wasp, @JewelSam, @sergey-chechaev)
|
11
30
|
|
12
31
|
[Unreleased]: https://github.com/tram-rb/tram-policy
|
13
32
|
[0.0.1]: https://github.com/tram-rb/tram-policy/releases/tag/v0.0.1
|
33
|
+
[0.0.2]: https://github.com/tram-rb/tram-policy/compare/v0.0.1...v0.0.2
|
data/README.md
CHANGED
@@ -172,6 +172,36 @@ rescue Tram::Policy::ValidationError => error
|
|
172
172
|
end
|
173
173
|
```
|
174
174
|
|
175
|
+
## Additional options
|
176
|
+
|
177
|
+
Class method `.validate` supports several options:
|
178
|
+
|
179
|
+
### `stop_on_faiure`
|
180
|
+
|
181
|
+
If a selected validation will fail (adds an error to the collection), the following validations won't be executed.
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
require "tram-policy"
|
185
|
+
|
186
|
+
class Article::ReadinessPolicy < Tram::Policy
|
187
|
+
# required param for article to validate
|
188
|
+
param :article
|
189
|
+
|
190
|
+
validate :title_presence, stop_on_failure: true
|
191
|
+
validate :title_valid # not executed if title is absent
|
192
|
+
|
193
|
+
# ...
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
### `if`
|
198
|
+
|
199
|
+
[WIP] Not implemented (coming soon in v0.1.0)
|
200
|
+
|
201
|
+
### `unless`
|
202
|
+
|
203
|
+
[WIP] Not implemented (coming soon in v0.1.0)
|
204
|
+
|
175
205
|
## RSpec matchers
|
176
206
|
|
177
207
|
RSpec matchers defined in a file `tram-policy/matcher` (not loaded in runtime).
|
@@ -197,7 +227,7 @@ end
|
|
197
227
|
|
198
228
|
```ruby
|
199
229
|
# spec/spec_helper.rb
|
200
|
-
require "tram
|
230
|
+
require "tram/policy/rspec"
|
201
231
|
```
|
202
232
|
|
203
233
|
```ruby
|
@@ -217,14 +247,14 @@ RSpec.describe User::ReadinessPolicy do
|
|
217
247
|
end
|
218
248
|
```
|
219
249
|
|
220
|
-
**Notice** that you have to wrap policy into block `{ policy }`. This is because matcher checks not only presence of an error, but also ensures its message is translated to all available locales (`I18n.available_locales`). The block containing a policy will be executed separately for every such language.
|
250
|
+
**Notice** that you have to wrap policy into block `{ policy }`. This is because the matcher checks not only presence of an error, but also ensures its message is translated to all available locales (`I18n.available_locales`). The block containing a policy will be executed separately for every such language.
|
221
251
|
|
222
252
|
## Generators
|
223
253
|
|
224
254
|
The gem provides simple tool for scaffolding new policy along with RSpec test template.
|
225
255
|
|
226
256
|
```shell
|
227
|
-
$ tram-policy user/readiness_policy -p user -o admin -v name_present email_present
|
257
|
+
$ tram-policy user/readiness_policy -p user -o admin -v name_present:blank_name email_present:blank_email
|
228
258
|
```
|
229
259
|
|
230
260
|
This will generate a policy class with specification compatible to both [RSpec][rspec] and [FactoryGirl][factory-girl]:
|
@@ -232,7 +262,13 @@ This will generate a policy class with specification compatible to both [RSpec][
|
|
232
262
|
|
233
263
|
```ruby
|
234
264
|
# app/policies/user/readiness_policy.rb
|
265
|
+
|
266
|
+
# TODO: describe the policy, its subject and context
|
235
267
|
class User::ReadinessPolicy < Tram::Policy
|
268
|
+
# TODO: add default values (default: -> { ... }),
|
269
|
+
# coercers (type: proc(&:to_s)),
|
270
|
+
# and optional arguments (optional: true)
|
271
|
+
# when necessary
|
236
272
|
param :user
|
237
273
|
option :admin
|
238
274
|
|
@@ -242,13 +278,17 @@ class User::ReadinessPolicy < Tram::Policy
|
|
242
278
|
private
|
243
279
|
|
244
280
|
def name_present
|
245
|
-
|
246
|
-
|
281
|
+
# TODO: define a condition
|
282
|
+
return if true
|
283
|
+
# TODO: add necessary tags
|
284
|
+
errors.add :blank_name
|
247
285
|
end
|
248
286
|
|
249
287
|
def email_present
|
250
|
-
|
251
|
-
|
288
|
+
# TODO: define a condition
|
289
|
+
return if true
|
290
|
+
# TODO: add necessary tags
|
291
|
+
errors.add :blank_email
|
252
292
|
end
|
253
293
|
end
|
254
294
|
```
|
@@ -258,32 +298,46 @@ end
|
|
258
298
|
---
|
259
299
|
en:
|
260
300
|
user/readiness_policy:
|
261
|
-
|
262
|
-
|
301
|
+
blank_name: translation missing
|
302
|
+
blank_email: translation missing
|
263
303
|
```
|
264
304
|
|
265
305
|
```ruby
|
266
306
|
# spec/policies/user/readiness_policy_spec.rb
|
267
|
-
|
268
|
-
|
307
|
+
require "spec_helper"
|
308
|
+
# TODO: move it to spec_helper
|
309
|
+
require "tram/policy/rspec"
|
269
310
|
|
270
|
-
|
311
|
+
RSpec.describe User::ReadinessPolicy, ".[]" do
|
312
|
+
# TODO: either remove this line, or set another source for locales to check
|
313
|
+
let(:available_locales) { I18n.available_locales }
|
314
|
+
let(:user) { FactoryGirl.build :user }
|
271
315
|
|
272
|
-
it
|
316
|
+
it "is valid with proper arguments" do
|
317
|
+
expect { described_class[user] }.to be_valid
|
318
|
+
end
|
273
319
|
|
320
|
+
# TODO: check the description
|
274
321
|
it "is invalid when not name_present" do
|
275
|
-
|
276
|
-
|
322
|
+
# TODO: modify some arguments
|
323
|
+
user = nil
|
324
|
+
# TODO: add necessary tags to focus the condition
|
325
|
+
expect { described_class[user] }.to be_invalid_at
|
277
326
|
end
|
278
327
|
|
328
|
+
# TODO: check the description
|
279
329
|
it "is invalid when not email_present" do
|
280
|
-
|
281
|
-
|
330
|
+
# TODO: modify some arguments
|
331
|
+
user = nil
|
332
|
+
# TODO: add necessary tags to focus the condition
|
333
|
+
expect { described_class[user] }.to be_invalid_at
|
282
334
|
end
|
283
335
|
end
|
284
336
|
```
|
285
337
|
|
286
|
-
|
338
|
+
Then you should go through all TODO-s and add necessary details.
|
339
|
+
|
340
|
+
Later you can copy-paste examples to provide more edge case for testing your policies.
|
287
341
|
|
288
342
|
Notice that RSpec matcher `be_invalid_at` checks at once:
|
289
343
|
|
@@ -291,7 +345,10 @@ Notice that RSpec matcher `be_invalid_at` checks at once:
|
|
291
345
|
- that the error has given tags
|
292
346
|
- that the error is translated to every available locale
|
293
347
|
|
294
|
-
|
348
|
+
Its negation (`not_to be_invalid_at`) checks that no errors added with given tags.
|
349
|
+
When called without tags, it checks that the policy is valid as a whole.
|
350
|
+
|
351
|
+
Both matchers provide a full description for the essence of the failure.
|
295
352
|
|
296
353
|
## To Recap
|
297
354
|
|
data/bin/tram-policy
CHANGED
data/lib/tram/policy.rb
CHANGED
@@ -8,6 +8,7 @@ module Tram
|
|
8
8
|
require_relative "policy/inflector"
|
9
9
|
require_relative "policy/error"
|
10
10
|
require_relative "policy/errors"
|
11
|
+
require_relative "policy/validator"
|
11
12
|
|
12
13
|
extend Dry::Initializer
|
13
14
|
|
@@ -17,8 +18,8 @@ module Tram
|
|
17
18
|
# @param [#to_sym, Array<#to_sym>] names
|
18
19
|
# @return [self]
|
19
20
|
#
|
20
|
-
def validate(
|
21
|
-
|
21
|
+
def validate(name, **opts)
|
22
|
+
validators[name.to_sym] = opts
|
22
23
|
self
|
23
24
|
end
|
24
25
|
|
@@ -34,12 +35,12 @@ module Tram
|
|
34
35
|
private
|
35
36
|
|
36
37
|
def validators
|
37
|
-
@validators ||=
|
38
|
+
@validators ||= {}
|
38
39
|
end
|
39
40
|
|
40
41
|
def inherited(klass)
|
41
42
|
super
|
42
|
-
klass.validate
|
43
|
+
validators.each { |name, opts| klass.validate name, opts }
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
@@ -107,7 +108,11 @@ module Tram
|
|
107
108
|
def initialize(*)
|
108
109
|
super
|
109
110
|
@__scope__ = Inflector.underscore(self.class.name)
|
110
|
-
self.class.send(:validators).each
|
111
|
+
self.class.send(:validators).each do |name, opts|
|
112
|
+
size = errors.count
|
113
|
+
send(name)
|
114
|
+
break if (errors.count > size) && opts[:stop_on_failure]
|
115
|
+
end
|
111
116
|
end
|
112
117
|
end
|
113
118
|
end
|
@@ -25,11 +25,25 @@ module Tram
|
|
25
25
|
default: [],
|
26
26
|
aliases: "-v",
|
27
27
|
banner: "validator[ validator]"
|
28
|
+
class_option :locales, desc: "list of available_locales",
|
29
|
+
type: :array,
|
30
|
+
default: [],
|
31
|
+
aliases: "-l",
|
32
|
+
banner: "en[ ru]"
|
28
33
|
|
29
34
|
def self.source_root
|
30
35
|
File.dirname(__FILE__)
|
31
36
|
end
|
32
37
|
|
38
|
+
def set_available_locales
|
39
|
+
@available_locales = \
|
40
|
+
if Array(options[:locales]).any?
|
41
|
+
options[:locales]
|
42
|
+
else
|
43
|
+
ask("Enter available locales for translation:").scan(/\w{2}/)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
33
47
|
def generate_class
|
34
48
|
template "generator/policy.erb", "app/policies/#{file}.rb"
|
35
49
|
end
|
@@ -39,7 +53,8 @@ module Tram
|
|
39
53
|
@locale = locale
|
40
54
|
add_locale
|
41
55
|
localize_policy
|
42
|
-
parsed_validators.
|
56
|
+
parsed_validators.sort_by { |v| v[:key] }
|
57
|
+
.each { |validator| localize_validator(validator) }
|
43
58
|
end
|
44
59
|
end
|
45
60
|
|
@@ -48,6 +63,10 @@ module Tram
|
|
48
63
|
end
|
49
64
|
|
50
65
|
no_tasks do
|
66
|
+
def available_locales
|
67
|
+
@available_locales ||= []
|
68
|
+
end
|
69
|
+
|
51
70
|
def klass
|
52
71
|
@klass ||= Inflector.camelize name
|
53
72
|
end
|
@@ -65,17 +84,17 @@ module Tram
|
|
65
84
|
end
|
66
85
|
|
67
86
|
def parsed_validators
|
68
|
-
@parsed_validators ||= options[:validators].map
|
87
|
+
@parsed_validators ||= options[:validators].map do |str|
|
88
|
+
name, key = str.downcase.split(":")
|
89
|
+
{ name: name, key: key || name }
|
90
|
+
end
|
69
91
|
end
|
70
92
|
|
71
93
|
def policy_signature
|
72
|
-
@policy_signature ||=
|
94
|
+
@policy_signature ||= (
|
73
95
|
parsed_params + \
|
74
96
|
parsed_options.map { |option| "#{option}: #{option}" }
|
75
|
-
|
76
|
-
|
77
|
-
def available_locales
|
78
|
-
ask("What locales should be used for translation?").scan(/\w{2}/)
|
97
|
+
).join(", ")
|
79
98
|
end
|
80
99
|
|
81
100
|
def locale_file
|
@@ -90,8 +109,8 @@ module Tram
|
|
90
109
|
@locale_group ||= " #{file}:\n"
|
91
110
|
end
|
92
111
|
|
93
|
-
def locale_line(
|
94
|
-
" #{
|
112
|
+
def locale_line(key)
|
113
|
+
" #{key}: translation missing\n"
|
95
114
|
end
|
96
115
|
|
97
116
|
def add_locale
|
@@ -102,8 +121,8 @@ module Tram
|
|
102
121
|
append_to_file(locale_file, locale_group)
|
103
122
|
end
|
104
123
|
|
105
|
-
def localize_validator(
|
106
|
-
insert_into_file locale_file, locale_line(
|
124
|
+
def localize_validator(key:, **)
|
125
|
+
insert_into_file locale_file, locale_line(key), after: locale_group
|
107
126
|
end
|
108
127
|
end
|
109
128
|
end
|
@@ -1,4 +1,9 @@
|
|
1
|
+
# TODO: describe the policy, its subject and context
|
1
2
|
class <%= klass %> < Tram::Policy
|
3
|
+
# TODO: add default values (default: -> { ... }),
|
4
|
+
# coercers (type: proc(&:to_s)),
|
5
|
+
# and optional arguments (optional: true)
|
6
|
+
# when necessary
|
2
7
|
<% parsed_params.each do |param| -%>
|
3
8
|
param :<%= param %>
|
4
9
|
<% end -%>
|
@@ -7,14 +12,16 @@ class <%= klass %> < Tram::Policy
|
|
7
12
|
<% end -%>
|
8
13
|
|
9
14
|
<% parsed_validators.each do |validator| -%>
|
10
|
-
validate :<%= validator %>
|
15
|
+
validate :<%= validator[:name] %>
|
11
16
|
<% end -%>
|
12
17
|
|
13
18
|
private
|
14
19
|
<% parsed_validators.each do |validator| %>
|
15
|
-
def <%= validator %>
|
16
|
-
|
17
|
-
|
20
|
+
def <%= validator[:name] %>
|
21
|
+
# TODO: define a condition
|
22
|
+
return if true
|
23
|
+
# TODO: add necessary tags
|
24
|
+
errors.add :<%= validator[:key] %>
|
18
25
|
end
|
19
26
|
<% end -%>
|
20
27
|
end
|
@@ -1,17 +1,26 @@
|
|
1
1
|
require "spec_helper"
|
2
|
+
# TODO: move it to spec_helper
|
3
|
+
require "tram/policy/rspec"
|
2
4
|
|
3
|
-
RSpec.describe <%= klass %>, "
|
4
|
-
|
5
|
-
|
5
|
+
RSpec.describe <%= klass %>, ".[]" do
|
6
|
+
# TODO: either remove this line, or set another source for available locales
|
7
|
+
let(:available_locales) { I18n.available_locales }
|
6
8
|
<% (parsed_params + parsed_options).each do |name| -%>
|
7
9
|
let(:<%= name %>) { FactoryGirl.build :<%= name %> }
|
8
10
|
<% end -%>
|
9
11
|
|
10
|
-
it
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
it "is valid with proper arguments" do
|
13
|
+
expect { described_class[<%= policy_signature %>] }.not_to be_invalid_at
|
14
|
+
end
|
15
|
+
<% parsed_validators.each do |v| %>
|
16
|
+
# TODO: fix default description
|
17
|
+
it "is invalid when <%= "not " if v[:key] == v[:name] %><%= v[:key] %>" do
|
18
|
+
# TODO: modify some arguments
|
19
|
+
<% (parsed_params + parsed_options).each do |name| -%>
|
20
|
+
<%= name %> = nil
|
21
|
+
<% end -%>
|
22
|
+
# TODO: add necessary tags to focus the condition
|
23
|
+
expect { described_class[<%= policy_signature %>] }.to be_invalid_at
|
15
24
|
end
|
16
25
|
<% end -%>
|
17
26
|
end
|
@@ -36,9 +36,13 @@ RSpec::Matchers.define :be_invalid_at do |**tags|
|
|
36
36
|
|
37
37
|
# Runs block in every available locale
|
38
38
|
def in_available_locales
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
locales = if respond_to?(:available_locales)
|
40
|
+
available_locales
|
41
|
+
else
|
42
|
+
I18n.available_locales
|
43
|
+
end
|
44
|
+
|
45
|
+
locales.flat_map { |locale| I18n.with_locale(locale) { yield } }
|
42
46
|
end
|
43
47
|
|
44
48
|
# Collects results for the current locale
|
@@ -67,7 +71,7 @@ RSpec::Matchers.define :be_invalid_at do |**tags|
|
|
67
71
|
# Checks if all collected errors are translated
|
68
72
|
def translated?
|
69
73
|
texts = errors.values.flatten.map(&:message)
|
70
|
-
texts.select { |text| text.start_with?("translation missing
|
74
|
+
texts.select { |text| text.start_with?("translation missing") }.empty?
|
71
75
|
end
|
72
76
|
|
73
77
|
def report_errors
|
@@ -89,7 +93,8 @@ RSpec::Matchers.define :be_invalid_at do |**tags|
|
|
89
93
|
end
|
90
94
|
|
91
95
|
failure_message do |_|
|
92
|
-
text = "
|
96
|
+
text = "The policy: #{policy}\n"
|
97
|
+
text << "should have had errors with tags: #{tags}, "
|
93
98
|
text << "whose messages are translated in all available locales.\n"
|
94
99
|
text << report_errors
|
95
100
|
text
|
@@ -105,8 +110,22 @@ RSpec::Matchers.define :be_invalid_at do |**tags|
|
|
105
110
|
end
|
106
111
|
|
107
112
|
failure_message_when_negated do |_|
|
108
|
-
text = "#{policy}
|
113
|
+
text = "#{policy}\nshould not have had any error with tags: #{tags}.\n"
|
109
114
|
text << report_errors
|
110
115
|
text
|
111
116
|
end
|
112
117
|
end
|
118
|
+
|
119
|
+
RSpec.shared_examples :invalid_policy do |condition = nil, **tags|
|
120
|
+
constraint = "with tags: #{tags}" if tags.any?
|
121
|
+
it ["is invalid", condition, constraint].compact.join(" ") do
|
122
|
+
expect { subject }.to be_invalid_at(tags)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
RSpec.shared_examples :valid_policy do |condition = nil, **tags|
|
127
|
+
constraint = "with tags: #{tags}" if tags.any?
|
128
|
+
it ["is valid", condition, constraint].compact.join(" ") do
|
129
|
+
expect { subject }.not_to be_invalid_at(tags)
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Tram::Policy
|
2
|
+
# Describes a validator
|
3
|
+
class Validator
|
4
|
+
attr_reader :name, :stop_on_failure
|
5
|
+
|
6
|
+
def ==(other)
|
7
|
+
other.is_a?(self.class) && other.name == name
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def initialize(name, stop_on_failure: false)
|
13
|
+
@name = name.to_sym
|
14
|
+
@stop_on_failure = stop_on_failure
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,7 +5,7 @@ rescue
|
|
5
5
|
end
|
6
6
|
require "bundler/setup"
|
7
7
|
require "tram/policy"
|
8
|
-
require "tram/policy/
|
8
|
+
require "tram/policy/rspec"
|
9
9
|
require "rspec/its"
|
10
10
|
|
11
11
|
RSpec.configure do |config|
|
@@ -19,9 +19,6 @@ RSpec.configure do |config|
|
|
19
19
|
config.run_all_when_everything_filtered = true
|
20
20
|
|
21
21
|
# Prepare the Test namespace for constants defined in specs
|
22
|
-
config.
|
23
|
-
|
24
|
-
example.run
|
25
|
-
Object.send :remove_const, :Test
|
26
|
-
end
|
22
|
+
config.before(:each) { Test = Class.new(Module) }
|
23
|
+
config.after(:each) { Object.send :remove_const, :Test }
|
27
24
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
RSpec.describe "RSpec
|
1
|
+
RSpec.describe "RSpec support:" do
|
2
2
|
subject { Test::UserPolicy[name: nil] }
|
3
3
|
|
4
4
|
before do
|
@@ -67,4 +67,12 @@ RSpec.describe "RSpec matchers:" do
|
|
67
67
|
end.to raise_error RSpec::Expectations::ExpectationNotMetError
|
68
68
|
end
|
69
69
|
end
|
70
|
+
|
71
|
+
describe "shared examples" do
|
72
|
+
it_behaves_like :invalid_policy
|
73
|
+
it_behaves_like :invalid_policy, field: "name" do
|
74
|
+
before { I18n.available_locales = %i[en ru] }
|
75
|
+
end
|
76
|
+
it_behaves_like :valid_policy, field: "email"
|
77
|
+
end
|
70
78
|
end
|
data/spec/tram/policy_spec.rb
CHANGED
@@ -5,7 +5,9 @@ RSpec.describe Tram::Policy do
|
|
5
5
|
class Test::UserPolicy < Tram::Policy
|
6
6
|
param :user
|
7
7
|
|
8
|
-
validate :name
|
8
|
+
validate :name
|
9
|
+
validate "email"
|
10
|
+
validate "name"
|
9
11
|
|
10
12
|
private
|
11
13
|
|
@@ -53,6 +55,26 @@ RSpec.describe Tram::Policy do
|
|
53
55
|
|
54
56
|
Test::AdminPolicy.new(user)
|
55
57
|
end
|
58
|
+
|
59
|
+
context "when :stop_on_failure is set" do
|
60
|
+
before { Test::UserPolicy.validate :name, stop_on_failure: true }
|
61
|
+
|
62
|
+
it "stops validation after failure" do
|
63
|
+
expect(user).to receive(:name).once
|
64
|
+
expect(user).not_to receive(:email)
|
65
|
+
|
66
|
+
Test::UserPolicy.new(user)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "continues validation after success" do
|
70
|
+
user = double :user, name: "Andy", email: nil, login: nil
|
71
|
+
|
72
|
+
expect(user).to receive(:name).once.ordered
|
73
|
+
expect(user).to receive(:email).once.ordered
|
74
|
+
|
75
|
+
Test::UserPolicy.new(user)
|
76
|
+
end
|
77
|
+
end
|
56
78
|
end
|
57
79
|
|
58
80
|
describe "#inspect" do
|
data/tram-policy.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = "tram-policy"
|
3
|
-
gem.version = "0.0.
|
3
|
+
gem.version = "0.0.2"
|
4
4
|
gem.author = ["Viktor Sokolov (gzigzigzeo)", "Andrew Kozin (nepalez)"]
|
5
5
|
gem.email = ["andrew.kozin@gmail.com"]
|
6
6
|
gem.homepage = "https://github.com/tram/tram-policy"
|
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: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Viktor Sokolov (gzigzigzeo)
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-04-
|
12
|
+
date: 2017-04-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: dry-initializer
|
@@ -138,13 +138,14 @@ files:
|
|
138
138
|
- lib/tram/policy/generator/policy.erb
|
139
139
|
- lib/tram/policy/generator/policy_spec.erb
|
140
140
|
- lib/tram/policy/inflector.rb
|
141
|
-
- lib/tram/policy/
|
141
|
+
- lib/tram/policy/rspec.rb
|
142
142
|
- lib/tram/policy/validation_error.rb
|
143
|
+
- lib/tram/policy/validator.rb
|
143
144
|
- spec/spec_helper.rb
|
144
145
|
- spec/tram/policy/error_spec.rb
|
145
146
|
- spec/tram/policy/errors_spec.rb
|
146
147
|
- spec/tram/policy/inflector_spec.rb
|
147
|
-
- spec/tram/policy/
|
148
|
+
- spec/tram/policy/rspec_spec.rb
|
148
149
|
- spec/tram/policy/validation_error_spec.rb
|
149
150
|
- spec/tram/policy_spec.rb
|
150
151
|
- tram-policy.gemspec
|
@@ -177,6 +178,6 @@ test_files:
|
|
177
178
|
- spec/tram/policy/error_spec.rb
|
178
179
|
- spec/tram/policy/errors_spec.rb
|
179
180
|
- spec/tram/policy/inflector_spec.rb
|
180
|
-
- spec/tram/policy/
|
181
|
+
- spec/tram/policy/rspec_spec.rb
|
181
182
|
- spec/tram/policy/validation_error_spec.rb
|
182
183
|
- spec/tram/policy_spec.rb
|