gate 0.10.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +9 -9
- data/README.md +38 -76
- data/gate.gemspec +3 -2
- data/lib/gate.rb +0 -2
- data/lib/gate/rails.rb +31 -29
- data/lib/gate/version.rb +1 -1
- metadata +20 -9
- data/.rubocop.yml +0 -19
- data/lib/gate/command.rb +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a060433f1f524041e43b2018c267f09296f33c9d62f9ca13fd2ca13d171f09d
|
4
|
+
data.tar.gz: e63df883e61a45ea42436cca24e53a750bfda2bea13a74351d55b005d251119a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b891269e835a23d6255fd3fd1fb6a5eceb7f65b933816e48832581fd306d52f6344dac5ff1dfb5da06e2be1e8901d6940d76889937d5174cc68628050bdfcc36
|
7
|
+
data.tar.gz: dcafe4902a3471e0eb0d40d14f74abc28775cddb67bbb6a6658c6f53cb9f9ab35029316f5ec29d1efd98e417a4af231160b7d63c94b2f937fc739b12b8849406
|
data/.circleci/config.yml
CHANGED
@@ -7,10 +7,6 @@ build_steps: &build_steps
|
|
7
7
|
|
8
8
|
version: 2
|
9
9
|
jobs:
|
10
|
-
test_ruby-2.3:
|
11
|
-
<<: *build_steps
|
12
|
-
docker:
|
13
|
-
- image: circleci/ruby:2.3
|
14
10
|
test_ruby-2.4:
|
15
11
|
<<: *build_steps
|
16
12
|
docker:
|
@@ -19,9 +15,13 @@ jobs:
|
|
19
15
|
<<: *build_steps
|
20
16
|
docker:
|
21
17
|
- image: circleci/ruby:2.5
|
18
|
+
test_ruby-2.6:
|
19
|
+
<<: *build_steps
|
20
|
+
docker:
|
21
|
+
- image: circleci/ruby:2.6
|
22
22
|
release:
|
23
23
|
docker:
|
24
|
-
- image: circleci/ruby:2.
|
24
|
+
- image: circleci/ruby:2.6
|
25
25
|
steps:
|
26
26
|
- checkout
|
27
27
|
- run:
|
@@ -39,23 +39,23 @@ workflows:
|
|
39
39
|
version: 2
|
40
40
|
test_and_release:
|
41
41
|
jobs:
|
42
|
-
- test_ruby-2.
|
42
|
+
- test_ruby-2.4:
|
43
43
|
filters:
|
44
44
|
tags:
|
45
45
|
only: /.*/
|
46
|
-
- test_ruby-2.
|
46
|
+
- test_ruby-2.5:
|
47
47
|
filters:
|
48
48
|
tags:
|
49
49
|
only: /.*/
|
50
|
-
- test_ruby-2.
|
50
|
+
- test_ruby-2.6:
|
51
51
|
filters:
|
52
52
|
tags:
|
53
53
|
only: /.*/
|
54
54
|
- release:
|
55
55
|
requires:
|
56
|
-
- test_ruby-2.3
|
57
56
|
- test_ruby-2.4
|
58
57
|
- test_ruby-2.5
|
58
|
+
- test_ruby-2.6
|
59
59
|
filters:
|
60
60
|
tags:
|
61
61
|
only: /^v.*/
|
data/README.md
CHANGED
@@ -2,13 +2,10 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/gate.svg)](http://badge.fury.io/rb/gate)
|
4
4
|
[![Circle CI](https://circleci.com/gh/monterail/gate.svg?style=shield)](https://circleci.com/gh/monterail/gate)
|
5
|
-
[![Dependency Status](https://gemnasium.com/monterail/gate.svg)](https://gemnasium.com/monterail/gate)
|
6
5
|
[![Code Climate](https://codeclimate.com/github/monterail/gate/badges/gpa.svg)](https://codeclimate.com/github/monterail/gate)
|
7
6
|
[![Test Coverage](https://codeclimate.com/github/monterail/gate/badges/coverage.svg)](https://codeclimate.com/github/monterail/gate/coverage)
|
8
7
|
|
9
|
-
Gate is a small wrapper on [dry-validation](http://dry-rb.org/gems/dry-validation/) that
|
10
|
-
|
11
|
-
`Gate::Command` will raise `InvalidCommand` error for invalid input and provide simple struct with access to coerced input.
|
8
|
+
**Gate** is a small wrapper on [dry-validation](http://dry-rb.org/gems/dry-validation/) that integrates it with [Ruby on Rails](https://rubyonrails.org/) and replaces [Strong Params](http://api.rubyonrails.org/classes/ActionController/Parameters.html).
|
12
9
|
|
13
10
|
## Installation
|
14
11
|
|
@@ -26,61 +23,33 @@ Or install it yourself as:
|
|
26
23
|
|
27
24
|
$ gem install gate
|
28
25
|
|
29
|
-
##
|
26
|
+
## Usage
|
30
27
|
|
31
|
-
Define
|
32
|
-
|
33
|
-
```ruby
|
34
|
-
class DoSomethingCommand
|
35
|
-
include Gate::Command
|
36
|
-
|
37
|
-
schema do
|
38
|
-
required(:id).filled
|
39
|
-
required(:message).schema do
|
40
|
-
required(:title).filled
|
41
|
-
optional(:value).maybe(:decimal?)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
```
|
46
|
-
|
47
|
-
Use it
|
48
|
-
|
49
|
-
```ruby
|
50
|
-
begin
|
51
|
-
cmd = DoSomethingCommand.with(params)
|
52
|
-
cmd.id
|
53
|
-
cmd.message
|
54
|
-
rescue DoSomethingCommand::InvalidCommand => e
|
55
|
-
e.errors # => hash { key => [errors] }
|
56
|
-
end
|
57
|
-
```
|
58
|
-
|
59
|
-
## Rails Usage
|
60
|
-
|
61
|
-
Define schemas per action
|
28
|
+
Define [contract](https://dry-rb.org/gems/dry-validation) per action with controller DSL...
|
62
29
|
|
63
30
|
```ruby
|
64
31
|
class ExampleController < ActionController::Base
|
65
32
|
include Gate::Rails
|
66
33
|
|
67
|
-
before_action :
|
34
|
+
before_action :verify_contract, if: { |c| c.contract_registered? }
|
68
35
|
|
69
|
-
# Define
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
required(:
|
74
|
-
|
36
|
+
# Define contract just before action method
|
37
|
+
contract(handler: :handle_invalid_params) do
|
38
|
+
params do
|
39
|
+
required(:id).filled
|
40
|
+
required(:message).hash do
|
41
|
+
required(:title).filled
|
42
|
+
optional(:value).maybe(:decimal?)
|
43
|
+
end
|
75
44
|
end
|
76
45
|
end
|
77
46
|
|
78
47
|
def foo
|
79
48
|
# you can access Dry::Validation result with:
|
80
|
-
|
49
|
+
claimed_params
|
81
50
|
end
|
82
51
|
|
83
|
-
#
|
52
|
+
# handler for invalid params
|
84
53
|
def handle_invalid_params(_errors)
|
85
54
|
# errors is Dry::Validation messages hash
|
86
55
|
|
@@ -89,50 +58,43 @@ class ExampleController < ActionController::Base
|
|
89
58
|
end
|
90
59
|
```
|
91
60
|
|
92
|
-
|
93
|
-
|
94
|
-
Gate gives a possibility to create global, inherited configuration and separated setup in each one schema definition.
|
95
|
-
|
96
|
-
### Inheriting base setup
|
97
|
-
|
98
|
-
In order to configure the library according to the whole application, create a file under `config/initializers/gate.rb`. There is a possibility of creating a base configuration, defining shared, custom predicates and a lot more useful things. The full list of supported configuration options is consistent with available options in [dry-validation](https://dry-rb.org/gems/dry-validation/) gem.
|
61
|
+
... or as a separate class:
|
99
62
|
|
100
63
|
```ruby
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
def foo?(value)
|
108
|
-
value == "FOO"
|
64
|
+
class ExampleFooContract < Dry::Validation::Contract
|
65
|
+
params do
|
66
|
+
required(:id).filled
|
67
|
+
required(:message).hash do
|
68
|
+
required(:title).filled
|
69
|
+
optional(:value).maybe(:decimal?)
|
109
70
|
end
|
110
71
|
end
|
111
72
|
end
|
112
|
-
```
|
113
73
|
|
114
|
-
|
74
|
+
class ExampleController < ActionController::Base
|
75
|
+
include Gate::Rails
|
115
76
|
|
116
|
-
|
77
|
+
before_action :verify_contract, if: { |c| c.contract_registered? }
|
117
78
|
|
118
|
-
|
119
|
-
|
120
|
-
|
79
|
+
contract(ExampleFooContract)
|
80
|
+
def foo
|
81
|
+
# you can access Dry::Validation result with:
|
82
|
+
claimed_params
|
83
|
+
end
|
121
84
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
required(:id).filled
|
128
|
-
required(:message).schema do
|
129
|
-
required(:title).filled
|
130
|
-
optional(:value).maybe(:decimal?)
|
131
|
-
end
|
85
|
+
# just use default handler
|
86
|
+
def handle_invalid_params(_errors)
|
87
|
+
# errors is Dry::Validation messages hash
|
88
|
+
|
89
|
+
head :bad_request
|
132
90
|
end
|
133
91
|
end
|
134
92
|
```
|
135
93
|
|
94
|
+
## Configuration
|
95
|
+
|
96
|
+
*TODO*
|
97
|
+
|
136
98
|
## Development
|
137
99
|
|
138
100
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/gate.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.authors = ["Jan Dudulski"]
|
11
11
|
spec.email = ["jan@dudulski.pl"]
|
12
12
|
|
13
|
-
spec.summary = "
|
13
|
+
spec.summary = "Strong params replacement"
|
14
14
|
spec.description = "Validate and coerce user input against defined structure."
|
15
15
|
spec.homepage = "https://github.com/monterail/gate"
|
16
16
|
spec.license = "MIT"
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
22
22
|
|
23
|
-
spec.add_runtime_dependency "dry-validation", "~> 0
|
23
|
+
spec.add_runtime_dependency "dry-validation", "~> 1.0"
|
24
24
|
|
25
25
|
spec.add_development_dependency "bundler", "~> 1.16"
|
26
26
|
spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0"
|
@@ -28,4 +28,5 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_development_dependency "pry", "~> 0.11"
|
29
29
|
spec.add_development_dependency "rails", "~> 5.2"
|
30
30
|
spec.add_development_dependency "rake", "~> 12.0"
|
31
|
+
spec.add_development_dependency "standardrb", ">= 1.0"
|
31
32
|
end
|
data/lib/gate.rb
CHANGED
data/lib/gate/rails.rb
CHANGED
@@ -2,49 +2,55 @@
|
|
2
2
|
|
3
3
|
module Gate
|
4
4
|
module Rails
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :claimed_params
|
6
6
|
|
7
|
-
|
8
|
-
@base_schema = nil
|
7
|
+
ContractNotDefined = Class.new(StandardError)
|
9
8
|
|
10
9
|
def self.included(base)
|
11
10
|
base.send(:extend, ClassMethods)
|
12
11
|
end
|
13
12
|
|
14
|
-
def self.configure(&block)
|
15
|
-
@base_schema = Class.new(Dry::Validation::Schema, &block)
|
16
|
-
end
|
17
|
-
|
18
13
|
module ClassMethods
|
19
|
-
def
|
20
|
-
@
|
14
|
+
def _contracts
|
15
|
+
@_contracts ||= {}
|
21
16
|
end
|
22
17
|
|
23
|
-
def
|
24
|
-
|
25
|
-
raise
|
26
|
-
end
|
18
|
+
def contract_for(contract_name)
|
19
|
+
_contracts.fetch(contract_name) do
|
20
|
+
raise ContractNotDefined, "Missing `#{contract_name}` contract"
|
21
|
+
end.fetch(:contract)
|
22
|
+
end
|
23
|
+
|
24
|
+
def handler_for(contract_name)
|
25
|
+
_contracts.fetch(contract_name) do
|
26
|
+
raise ContractNotDefined, "Missing `#{contract_name}` contract"
|
27
|
+
end.fetch(:handler)
|
27
28
|
end
|
28
29
|
|
29
|
-
def
|
30
|
-
@
|
30
|
+
def contract(klass = nil, handler: :handle_invalid_params, &block)
|
31
|
+
@_contract = {
|
32
|
+
contract: klass ? klass.new : Dry::Validation.Contract(&block),
|
33
|
+
handler: handler,
|
34
|
+
}
|
31
35
|
end
|
32
36
|
|
33
37
|
def method_added(method_name)
|
34
|
-
|
38
|
+
if instance_variable_defined?(:@_contract)
|
39
|
+
_contracts[method_name] = @_contract
|
40
|
+
remove_instance_variable(:@_contract)
|
41
|
+
end
|
35
42
|
|
36
|
-
|
37
|
-
remove_instance_variable(:@_schema)
|
43
|
+
super
|
38
44
|
end
|
39
45
|
end
|
40
46
|
|
41
|
-
def
|
42
|
-
result =
|
47
|
+
def verify_contract
|
48
|
+
result = self.class.contract_for(_contract_name).call(request.params)
|
43
49
|
|
44
50
|
if result.success?
|
45
|
-
@
|
51
|
+
@claimed_params = result.to_h
|
46
52
|
else
|
47
|
-
|
53
|
+
send(self.class.handler_for(_contract_name), result.errors.to_h)
|
48
54
|
end
|
49
55
|
end
|
50
56
|
|
@@ -52,15 +58,11 @@ module Gate
|
|
52
58
|
head :bad_request
|
53
59
|
end
|
54
60
|
|
55
|
-
def
|
56
|
-
self.class.
|
57
|
-
end
|
58
|
-
|
59
|
-
def params_schema
|
60
|
-
self.class.fetch_params_schema(params_schema_name)
|
61
|
+
def contract_registered?
|
62
|
+
self.class._contracts.key?(_contract_name)
|
61
63
|
end
|
62
64
|
|
63
|
-
def
|
65
|
+
def _contract_name
|
64
66
|
action_name.to_sym
|
65
67
|
end
|
66
68
|
end
|
data/lib/gate/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Dudulski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-validation
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0
|
19
|
+
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0
|
26
|
+
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '12.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: standardrb
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.0'
|
111
125
|
description: Validate and coerce user input against defined structure.
|
112
126
|
email:
|
113
127
|
- jan@dudulski.pl
|
@@ -119,7 +133,6 @@ files:
|
|
119
133
|
- ".circleci/gem_credentials"
|
120
134
|
- ".codeclimate.yml"
|
121
135
|
- ".gitignore"
|
122
|
-
- ".rubocop.yml"
|
123
136
|
- ".travis.yml"
|
124
137
|
- Gemfile
|
125
138
|
- LICENSE.txt
|
@@ -129,7 +142,6 @@ files:
|
|
129
142
|
- bin/setup
|
130
143
|
- gate.gemspec
|
131
144
|
- lib/gate.rb
|
132
|
-
- lib/gate/command.rb
|
133
145
|
- lib/gate/rails.rb
|
134
146
|
- lib/gate/version.rb
|
135
147
|
homepage: https://github.com/monterail/gate
|
@@ -152,9 +164,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
164
|
- !ruby/object:Gem::Version
|
153
165
|
version: '0'
|
154
166
|
requirements: []
|
155
|
-
|
156
|
-
rubygems_version: 2.7.7
|
167
|
+
rubygems_version: 3.0.3
|
157
168
|
signing_key:
|
158
169
|
specification_version: 4
|
159
|
-
summary:
|
170
|
+
summary: Strong params replacement
|
160
171
|
test_files: []
|
data/.rubocop.yml
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
Style/Documentation:
|
2
|
-
Description: Document classes and non-namespace modules.
|
3
|
-
Enabled: false
|
4
|
-
Style/StringLiterals:
|
5
|
-
Description: Checks if uses of quotes match the configured preference.
|
6
|
-
StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-string-literals
|
7
|
-
Enabled: true
|
8
|
-
EnforcedStyle: double_quotes
|
9
|
-
SupportedStyles:
|
10
|
-
- single_quotes
|
11
|
-
- double_quotes
|
12
|
-
Style/StringLiteralsInInterpolation:
|
13
|
-
Description: Checks if uses of quotes inside expressions in interpolated strings
|
14
|
-
match the configured preference.
|
15
|
-
Enabled: true
|
16
|
-
EnforcedStyle: single_quotes
|
17
|
-
SupportedStyles:
|
18
|
-
- single_quotes
|
19
|
-
- double_quotes
|
data/lib/gate/command.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "forwardable"
|
4
|
-
|
5
|
-
module Gate
|
6
|
-
module Command
|
7
|
-
extend Forwardable
|
8
|
-
|
9
|
-
def_delegator :result, :to_h
|
10
|
-
|
11
|
-
SchemaAlreadyRegistered = Class.new(StandardError)
|
12
|
-
SchemaNotDefined = Class.new(StandardError)
|
13
|
-
|
14
|
-
attr_reader :result
|
15
|
-
|
16
|
-
class InvalidCommand < StandardError
|
17
|
-
attr_reader :errors
|
18
|
-
|
19
|
-
def initialize(errors)
|
20
|
-
@errors = errors
|
21
|
-
super("Invalid command")
|
22
|
-
end
|
23
|
-
|
24
|
-
def full_message
|
25
|
-
errors.values.join(", ")
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.included(base)
|
30
|
-
base.send(:extend, ClassMethods)
|
31
|
-
end
|
32
|
-
|
33
|
-
def initialize(data)
|
34
|
-
@result = data
|
35
|
-
end
|
36
|
-
|
37
|
-
module ClassMethods
|
38
|
-
# rubocop:disable Metrics/MethodLength
|
39
|
-
def schema(&block)
|
40
|
-
if block_given?
|
41
|
-
raise SchemaAlreadyRegistered if instance_variable_defined?(:@schema)
|
42
|
-
@schema = Dry::Validation.Params(&block)
|
43
|
-
@schema.rules.keys.each do |name|
|
44
|
-
define_method(name) do
|
45
|
-
result[name]
|
46
|
-
end
|
47
|
-
end
|
48
|
-
else
|
49
|
-
raise SchemaNotDefined unless @schema
|
50
|
-
@schema
|
51
|
-
end
|
52
|
-
end
|
53
|
-
# rubocop:enable Metrics/MethodLength
|
54
|
-
|
55
|
-
def with(input)
|
56
|
-
result = schema.call(input)
|
57
|
-
raise InvalidCommand, result.messages(full: true) if result.failure?
|
58
|
-
new result.output
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|