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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64401d6617c7ebcde128f5e283695475effec0be39a3089ed1a04cc9dd769ec3
4
- data.tar.gz: 4f6192608d2110d1053d2cf1ab0b9afe1973cb65dc60bd556ac37d0d26defce7
3
+ metadata.gz: 3a060433f1f524041e43b2018c267f09296f33c9d62f9ca13fd2ca13d171f09d
4
+ data.tar.gz: e63df883e61a45ea42436cca24e53a750bfda2bea13a74351d55b005d251119a
5
5
  SHA512:
6
- metadata.gz: 76c705ee8b4c09b172b73433487376781683fb1b6619168ad1972557046f2e6f4d831e776ffd91746f4b9b17a2f36a7b6831768453208a61857076602f991b8d
7
- data.tar.gz: 0bf7be2a899cf05f60eeaea97703944ed563f4f7e5dd46565e77858455d65832ed21a11f50dd8b774ca56df8d3db3ae722e9554df47bd3d097349134c68c32a9
6
+ metadata.gz: b891269e835a23d6255fd3fd1fb6a5eceb7f65b933816e48832581fd306d52f6344dac5ff1dfb5da06e2be1e8901d6940d76889937d5174cc68628050bdfcc36
7
+ data.tar.gz: dcafe4902a3471e0eb0d40d14f74abc28775cddb67bbb6a6658c6f53cb9f9ab35029316f5ec29d1efd98e417a4af231160b7d63c94b2f937fc739b12b8849406
@@ -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.5
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.3:
42
+ - test_ruby-2.4:
43
43
  filters:
44
44
  tags:
45
45
  only: /.*/
46
- - test_ruby-2.4:
46
+ - test_ruby-2.5:
47
47
  filters:
48
48
  tags:
49
49
  only: /.*/
50
- - test_ruby-2.5:
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 might be used as Command in CQRS pattern or replace [Strong Params](http://api.rubyonrails.org/classes/ActionController/Parameters.html) in [Ruby on Rails](https://rubyonrails.org/) applications.
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
- ## Command Usage
26
+ ## Usage
30
27
 
31
- Define structure
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 :validate_params, if: { |c| c.params_schema_registered? }
34
+ before_action :verify_contract, if: { |c| c.contract_registered? }
68
35
 
69
- # Define schema just before action method
70
- def_schema do
71
- required(:id).filled
72
- required(:message).schema do
73
- required(:title).filled
74
- optional(:value).maybe(:decimal?)
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
- validated_params
49
+ claimed_params
81
50
  end
82
51
 
83
- # default handler for invalid params which you can override
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
- ## Configuration
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
- Gate::Rails.configure do
102
- configure do |config|
103
- config.messages_file = Rails.root.join("config", "locales" "en.yml")
104
-
105
- predicates(SharedPredicates)
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
- ### Separated setup
74
+ class ExampleController < ActionController::Base
75
+ include Gate::Rails
115
76
 
116
- Sometimes there is a requirement to have a very specific configuration or behaviour in a one schema validation. The easiest way is to do it in a special `configure` block.
77
+ before_action :verify_contract, if: { |c| c.contract_registered? }
117
78
 
118
- ```ruby
119
- class DoSomethingCommand
120
- include Gate::Command
79
+ contract(ExampleFooContract)
80
+ def foo
81
+ # you can access Dry::Validation result with:
82
+ claimed_params
83
+ end
121
84
 
122
- schema do
123
- configure do
124
- config.messages_file = Rails.root.join("config", "locales" "special_en.yml")
125
- predicates(SharedPredicates)
126
- end
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.
@@ -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 = "CQRS Command"
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.12"
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
@@ -1,11 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gate
4
- InvalidCommand = Class.new(StandardError)
5
4
  end
6
5
 
7
6
  require "dry-validation"
8
7
 
9
- require "gate/command"
10
8
  require "gate/rails"
11
9
  require "gate/version"
@@ -2,49 +2,55 @@
2
2
 
3
3
  module Gate
4
4
  module Rails
5
- attr_reader :validated_params
5
+ attr_reader :claimed_params
6
6
 
7
- SchemaNotDefined = Class.new(StandardError)
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 params_schemas
20
- @params_schemas ||= {}
14
+ def _contracts
15
+ @_contracts ||= {}
21
16
  end
22
17
 
23
- def fetch_params_schema(schema_name)
24
- params_schemas.fetch(schema_name) do
25
- raise SchemaNotDefined, "Missing `#{schema_name}` schema"
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 def_schema(&block)
30
- @_schema = Dry::Validation.Params(Gate::Rails::instance_variable_get(:@base_schema), &block)
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
- return unless instance_variable_defined?(:@_schema)
38
+ if instance_variable_defined?(:@_contract)
39
+ _contracts[method_name] = @_contract
40
+ remove_instance_variable(:@_contract)
41
+ end
35
42
 
36
- params_schemas[method_name] = @_schema
37
- remove_instance_variable(:@_schema)
43
+ super
38
44
  end
39
45
  end
40
46
 
41
- def validate_params
42
- result = params_schema.call(request.params)
47
+ def verify_contract
48
+ result = self.class.contract_for(_contract_name).call(request.params)
43
49
 
44
50
  if result.success?
45
- @validated_params = result.output
51
+ @claimed_params = result.to_h
46
52
  else
47
- handle_invalid_params(result.messages)
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 params_schema_registered?
56
- self.class.params_schemas.key?(params_schema_name)
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 params_schema_name
65
+ def _contract_name
64
66
  action_name.to_sym
65
67
  end
66
68
  end
@@ -1,3 +1,3 @@
1
1
  module Gate
2
- VERSION = "0.10.0"
2
+ VERSION = "1.0.0"
3
3
  end
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.10.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: 2018-09-10 00:00:00.000000000 Z
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.12'
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.12'
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
- rubyforge_project:
156
- rubygems_version: 2.7.7
167
+ rubygems_version: 3.0.3
157
168
  signing_key:
158
169
  specification_version: 4
159
- summary: CQRS Command
170
+ summary: Strong params replacement
160
171
  test_files: []
@@ -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
@@ -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