pragma-contract 2.0.1 → 2.1.1

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: 65bb088e2e5f2bea1013369379af3335d4c02b381775d376701c0453b8e8f17c
4
- data.tar.gz: e2bca105d4a8cc7c3980c8f927bea2468b33a5d342ace9574f5e41afb0a8fc04
3
+ metadata.gz: ee1d19808a18f852a7889126b040644ff9998dffb001fa385979752d11c1963b
4
+ data.tar.gz: 494b6b03190618620e2795ef9f61e076f61f1891d20bc1b375b8b06829c84a21
5
5
  SHA512:
6
- metadata.gz: c9a7cf260d36af1a576d4fa6f16c913b0a643dc4ec67a735a5760213efde02ccd94223b35a43ff601b72755d393a8045402e0ad03281c339c78aa4b93c3fcf36
7
- data.tar.gz: 07afc3dcc218d6f3208b18f28456327ea7a9850452c41cae0c96f9022a4c4cfe68a6b0808d436cb37651bc60462f17a7601131ae2e80527b7d8ef8c57428645f
6
+ metadata.gz: de13ebd9f314c416d083a049cb5a3d853bcdc9703d8b27b5945c79dc13eb558cd7c067dc65f3e8ed51c360b36f905be423a22d54a4edff76eae9aed5c57a5a49
7
+ data.tar.gz: ba6b2a7bced2b111976b1a6e8a4d5ba766df4721ce974ab47625018d1773eb19f6d1ff31a78a2d8c582e969c527419ccb0508fce4f0ab4fb67b414dade196604
@@ -5,6 +5,7 @@ AllCops:
5
5
  Include:
6
6
  - '**/Gemfile'
7
7
  - '**/Rakefile'
8
+ - '**/*.rb'
8
9
  Exclude:
9
10
  - 'bin/*'
10
11
  - 'db/**/*'
@@ -77,3 +78,6 @@ Style/Documentation:
77
78
  Naming/FileName:
78
79
  Exclude:
79
80
  - '*.gemspec'
81
+
82
+ Metrics/AbcSize:
83
+ Enabled: false
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.1.1]
11
+
12
+ ### Fixed
13
+
14
+ - Fixed `property` expecting two arguments
15
+
16
+ ## [2.1.0]
17
+
18
+ ### Added
19
+
20
+ - Implemented the ability to find records when coercing contracts
21
+
10
22
  ## [2.0.1]
11
23
 
12
24
  ### Fixed
@@ -23,6 +35,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
23
35
 
24
36
  First Pragma 2 release.
25
37
 
26
- [Unreleased]: https://github.com/pragmarb/pragma-contract/compare/v2.0.1...HEAD
38
+ [Unreleased]: https://github.com/pragmarb/pragma-contract/compare/v2.1.1...HEAD
39
+ [2.1.1]: https://github.com/pragmarb/pragma-contract/compare/v2.1.0...v2.1.1
40
+ [2.1.0]: https://github.com/pragmarb/pragma-contract/compare/v2.0.1...v2.1.0
27
41
  [2.0.1]: https://github.com/pragmarb/pragma-contract/compare/v2.0.0...v2.0.1
28
42
  [2.0.0]: https://github.com/pragmarb/pragma-contract/compare/v0.1.0...v2.0.0
data/README.md CHANGED
@@ -92,6 +92,60 @@ module API
92
92
  end
93
93
  ```
94
94
 
95
+ ### Model finders
96
+
97
+ This is a common pattern in API contracts:
98
+
99
+ ```ruby
100
+ module API
101
+ module V1
102
+ module Invoice
103
+ module Contract
104
+ class Base < Pragma::Contract::Base
105
+ property :customer
106
+
107
+ def customer=(val)
108
+ super ::Customer.find_by(id: val)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ ```
116
+
117
+ Pragma::Contract provides a shorthand syntax:
118
+
119
+ ```ruby
120
+ module API
121
+ module V1
122
+ module Invoice
123
+ module Contract
124
+ class Base < Pragma::Contract::Base
125
+ property :customer, type: Customer
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ ```
132
+
133
+ You can also specify a custom column to find by!
134
+
135
+ ```ruby
136
+ module API
137
+ module V1
138
+ module Invoice
139
+ module Contract
140
+ class Base < Pragma::Contract::Base
141
+ property :customer, type: Customer, by: :email
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ ```
148
+
95
149
  ## Contributing
96
150
 
97
151
  Bug reports and pull requests are welcome on GitHub at https://github.com/pragmarb/pragma-contract.
@@ -1,18 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'adaptor'
3
4
  require 'dry-validation'
4
5
  require 'dry-types'
5
6
  require 'reform'
6
7
 
7
8
  require 'pragma/contract/version'
9
+
8
10
  require 'pragma/contract/coercion'
11
+
12
+ require 'pragma/contract/model_finder/base'
13
+ require 'pragma/contract/model_finder/active_record'
14
+ require 'pragma/contract/model_finder'
15
+
9
16
  require 'pragma/contract/base'
17
+
10
18
  require 'pragma/contract/types'
11
19
 
12
20
  module Pragma
13
21
  # Form objects on steroids for your HTTP API.
14
- #
15
- # @author Alessandro Desantis
16
22
  module Contract
17
23
  end
18
24
  end
@@ -14,6 +14,7 @@ module Pragma
14
14
  feature Reform::Form::Coercion
15
15
  feature Pragma::Contract::Coercion
16
16
  feature Reform::Form::Dry
17
+ feature Pragma::Contract::ModelFinder
17
18
 
18
19
  property :current_user, virtual: true
19
20
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pragma
4
+ module Contract
5
+ module ModelFinder
6
+ include Adaptor::Loader
7
+ register ActiveRecord
8
+
9
+ FINDER_OPTIONS = [:by].freeze
10
+
11
+ def self.included(klass)
12
+ klass.extend ClassMethods
13
+ end
14
+
15
+ module ClassMethods
16
+ def property(name, options = {})
17
+ return super if !options[:type] || options[:type].is_a?(Dry::Types::Type)
18
+
19
+ property(name, Hash[options.reject { |k, _| k == :type }])
20
+
21
+ define_method("#{name}=") do |value|
22
+ finder = Pragma::Contract::ModelFinder.load_adaptor!(
23
+ options[:type],
24
+ Hash[options.select { |k, _| FINDER_OPTIONS.include?(k.to_sym) }]
25
+ )
26
+
27
+ super finder.find(value)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pragma
4
+ module Contract
5
+ module ModelFinder
6
+ class ActiveRecord < Base
7
+ class << self
8
+ def supports?(klass)
9
+ defined?(::ActiveRecord::Base) && klass < ::ActiveRecord::Base
10
+ end
11
+ end
12
+
13
+ def find(value)
14
+ klass.find_by(options[:by] => value)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pragma
4
+ module Contract
5
+ module ModelFinder
6
+ class Base
7
+ include Adaptor
8
+
9
+ class << self
10
+ def supports?(_klass)
11
+ fail NotImplementedError
12
+ end
13
+ end
14
+
15
+ attr_reader :klass, :options
16
+
17
+ def initialize(klass, options)
18
+ @klass = klass
19
+ @options = { by: :id }.merge(options)
20
+ end
21
+
22
+ def find(_value)
23
+ fail NotImplementedError
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Pragma
4
4
  module Contract
5
- VERSION = '2.0.1'
5
+ VERSION = '2.1.1'
6
6
  end
7
7
  end
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ['lib']
23
23
 
24
+ spec.add_dependency 'adaptor', '~> 0.2'
24
25
  spec.add_dependency 'dry-types', '~> 0.12.0'
25
26
  spec.add_dependency 'dry-validation', '~> 0.11.1'
26
27
  spec.add_dependency 'reform', '~> 2.2'
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pragma-contract
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Desantis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-09 00:00:00.000000000 Z
11
+ date: 2018-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: adaptor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: dry-types
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -157,6 +171,9 @@ files:
157
171
  - lib/pragma/contract.rb
158
172
  - lib/pragma/contract/base.rb
159
173
  - lib/pragma/contract/coercion.rb
174
+ - lib/pragma/contract/model_finder.rb
175
+ - lib/pragma/contract/model_finder/active_record.rb
176
+ - lib/pragma/contract/model_finder/base.rb
160
177
  - lib/pragma/contract/types.rb
161
178
  - lib/pragma/contract/version.rb
162
179
  - pragma-contract.gemspec