pragma 1.2.6 → 2.0.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 +4 -4
- data/.rubocop.yml +11 -8
- data/Gemfile +5 -0
- data/README.md +65 -10
- data/lib/pragma.rb +12 -1
- data/lib/pragma/decorator/error.rb +11 -0
- data/lib/pragma/operation/create.rb +14 -23
- data/lib/pragma/operation/destroy.rb +17 -15
- data/lib/pragma/operation/index.rb +19 -101
- data/lib/pragma/operation/macro/classes.rb +96 -0
- data/lib/pragma/operation/macro/contract/build.rb +27 -0
- data/lib/pragma/operation/macro/contract/persist.rb +27 -0
- data/lib/pragma/operation/macro/contract/validate.rb +27 -0
- data/lib/pragma/operation/macro/decorator.rb +61 -0
- data/lib/pragma/operation/macro/model.rb +27 -0
- data/lib/pragma/operation/macro/pagination.rb +92 -0
- data/lib/pragma/operation/macro/policy.rb +40 -0
- data/lib/pragma/operation/show.rb +8 -15
- data/lib/pragma/operation/update.rb +12 -23
- data/lib/pragma/version.rb +2 -1
- data/pragma.gemspec +7 -5
- metadata +34 -14
- data/doc/01-sensible-defaults.md +0 -50
- data/doc/02-crud-operations.md +0 -109
- data/lib/pragma/operation/defaults.rb +0 -83
data/lib/pragma/version.rb
CHANGED
data/pragma.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'pragma/version'
|
@@ -20,10 +21,11 @@ Gem::Specification.new do |spec|
|
|
20
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
22
|
spec.require_paths = ['lib']
|
22
23
|
|
23
|
-
spec.add_dependency '
|
24
|
-
spec.add_dependency 'pragma-
|
25
|
-
spec.add_dependency 'pragma-
|
26
|
-
spec.add_dependency 'pragma-
|
24
|
+
spec.add_dependency 'trailblazer', '~> 2.0'
|
25
|
+
spec.add_dependency 'pragma-operation', '~> 2.0'
|
26
|
+
spec.add_dependency 'pragma-policy', '~> 2.0'
|
27
|
+
spec.add_dependency 'pragma-contract', '~> 2.0'
|
28
|
+
spec.add_dependency 'pragma-decorator', '~> 2.0'
|
27
29
|
spec.add_dependency 'will_paginate', '~> 3.1'
|
28
30
|
|
29
31
|
spec.add_development_dependency 'bundler'
|
metadata
CHANGED
@@ -1,71 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pragma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Desantis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: trailblazer
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: pragma-operation
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - "~>"
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
33
|
+
version: '2.0'
|
20
34
|
type: :runtime
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
40
|
+
version: '2.0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: pragma-policy
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0
|
47
|
+
version: '2.0'
|
34
48
|
type: :runtime
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0
|
54
|
+
version: '2.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: pragma-contract
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0
|
61
|
+
version: '2.0'
|
48
62
|
type: :runtime
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0
|
68
|
+
version: '2.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: pragma-decorator
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '2.0'
|
62
76
|
type: :runtime
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '2.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: will_paginate
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -182,13 +196,19 @@ files:
|
|
182
196
|
- Rakefile
|
183
197
|
- bin/console
|
184
198
|
- bin/setup
|
185
|
-
- doc/01-sensible-defaults.md
|
186
|
-
- doc/02-crud-operations.md
|
187
199
|
- lib/pragma.rb
|
200
|
+
- lib/pragma/decorator/error.rb
|
188
201
|
- lib/pragma/operation/create.rb
|
189
|
-
- lib/pragma/operation/defaults.rb
|
190
202
|
- lib/pragma/operation/destroy.rb
|
191
203
|
- lib/pragma/operation/index.rb
|
204
|
+
- lib/pragma/operation/macro/classes.rb
|
205
|
+
- lib/pragma/operation/macro/contract/build.rb
|
206
|
+
- lib/pragma/operation/macro/contract/persist.rb
|
207
|
+
- lib/pragma/operation/macro/contract/validate.rb
|
208
|
+
- lib/pragma/operation/macro/decorator.rb
|
209
|
+
- lib/pragma/operation/macro/model.rb
|
210
|
+
- lib/pragma/operation/macro/pagination.rb
|
211
|
+
- lib/pragma/operation/macro/policy.rb
|
192
212
|
- lib/pragma/operation/show.rb
|
193
213
|
- lib/pragma/operation/update.rb
|
194
214
|
- lib/pragma/version.rb
|
@@ -213,7 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
213
233
|
version: '0'
|
214
234
|
requirements: []
|
215
235
|
rubyforge_project:
|
216
|
-
rubygems_version: 2.6.
|
236
|
+
rubygems_version: 2.6.13
|
217
237
|
signing_key:
|
218
238
|
specification_version: 4
|
219
239
|
summary: A pragmatic architecture for building JSON APIs with Ruby.
|
data/doc/01-sensible-defaults.md
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
# Sensible defaults
|
2
|
-
|
3
|
-
This gem works best if you follow the recommended structure (partially borrowed from
|
4
|
-
[Trailblazer](https://github.com/trailblazer/trailblazer)) for organizing resources:
|
5
|
-
|
6
|
-
```
|
7
|
-
└── api
|
8
|
-
└── v1
|
9
|
-
└── post
|
10
|
-
├── contract
|
11
|
-
│ ├── create.rb
|
12
|
-
│ └── update.rb
|
13
|
-
├── operation
|
14
|
-
│ ├── create.rb
|
15
|
-
│ ├── destroy.rb
|
16
|
-
│ ├── index.rb
|
17
|
-
│ └── update.rb
|
18
|
-
└── policy.rb
|
19
|
-
└── decorator.rb
|
20
|
-
```
|
21
|
-
|
22
|
-
Your modules and classes would, of course, follow the same structure: `API::V1::Post::Policy`,
|
23
|
-
`API::V1::Post::Operation::Create` and so on and so forth.
|
24
|
-
|
25
|
-
If you adhere to this structure, the gem will be able to locate all of your classes without explicit
|
26
|
-
configuration (i.e. no `#policy` or `#contract` calls etc.). This will save you a lot of time and is
|
27
|
-
highly recommended, especially when used in conjunction with the provided CRUD operations.
|
28
|
-
|
29
|
-
To leverage automatic discovery, include `Pragma::Operation::Defaults` in your operation:
|
30
|
-
|
31
|
-
```ruby
|
32
|
-
module API
|
33
|
-
module V1
|
34
|
-
module Post
|
35
|
-
module Operation
|
36
|
-
class Create < Pragma::Operation::Base
|
37
|
-
include Pragma::Operation::Defaults
|
38
|
-
|
39
|
-
def call
|
40
|
-
# You can use `decorate`, `validate` and `authorize` without having to explicitly
|
41
|
-
# specify the decorator, validator and policy classes.
|
42
|
-
#
|
43
|
-
# ...
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
```
|
data/doc/02-crud-operations.md
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
# CRUD operations
|
2
|
-
|
3
|
-
Pragma ships with a default set of CRUD operations which should work for most standard API
|
4
|
-
resources. You can use them as they are, modify them or simply roll your own.
|
5
|
-
|
6
|
-
## The Index operation
|
7
|
-
|
8
|
-
Pragma provides a default implementation of the Index operation. Here's how it works:
|
9
|
-
|
10
|
-
1. it finds all records of the model;
|
11
|
-
2. it wraps the query in the policy to only return viewable records;
|
12
|
-
3. it responds with 200 OK and a paginated list of decorated records.
|
13
|
-
|
14
|
-
To create an Index operation, inherit from `Pragma::Operation::Index`:
|
15
|
-
|
16
|
-
```ruby
|
17
|
-
module API
|
18
|
-
module V1
|
19
|
-
module Post
|
20
|
-
module Operation
|
21
|
-
class Index < Pragma::Operation::Index
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
```
|
28
|
-
|
29
|
-
To override the defaults of this operation, have a look at the [source code](https://github.com/pragmarb/pragma/blob/master/lib/pragma/operation/index.rb).
|
30
|
-
|
31
|
-
## The Create operation
|
32
|
-
|
33
|
-
Pragma provides a default implementation of the Create operation. Here's how it works:
|
34
|
-
|
35
|
-
1. it builds a new instance of the model;
|
36
|
-
2. it wraps the model in the Create contract;
|
37
|
-
3. it validates and authorizes the contract;
|
38
|
-
4. it saves the record;
|
39
|
-
5. it responds with 201 Created and the decorated record.
|
40
|
-
|
41
|
-
To create a Create operation (pun intended), inherit from `Pragma::Operation::Create`:
|
42
|
-
|
43
|
-
```ruby
|
44
|
-
module API
|
45
|
-
module V1
|
46
|
-
module Post
|
47
|
-
module Operation
|
48
|
-
class Create < Pragma::Operation::Create
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
```
|
55
|
-
|
56
|
-
To override the defaults of this operation, have a look at the [source code](https://github.com/pragmarb/pragma/blob/master/lib/pragma/operation/create.rb).
|
57
|
-
|
58
|
-
## The Update operation
|
59
|
-
|
60
|
-
Pragma provides a default implementation of the Update operation. Here's how it works:
|
61
|
-
|
62
|
-
1. it finds an instance of the model by ID;
|
63
|
-
2. it wraps the model in the Update contract;
|
64
|
-
3. it validates and authorizes the contract;
|
65
|
-
4. it saves the record;
|
66
|
-
5. it responds with 200 OK and the decorated record.
|
67
|
-
|
68
|
-
To create an Update operation, inherit from `Pragma::Operation::Update`:
|
69
|
-
|
70
|
-
```ruby
|
71
|
-
module API
|
72
|
-
module V1
|
73
|
-
module Post
|
74
|
-
module Operation
|
75
|
-
class Update < Pragma::Operation::Update
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
```
|
82
|
-
|
83
|
-
To override the defaults of this operation, have a look at the [source code](https://github.com/pragmarb/pragma/blob/master/lib/pragma/operation/update.rb).
|
84
|
-
|
85
|
-
## The Destroy operation
|
86
|
-
|
87
|
-
Pragma provides a default implementation of the Destroy operation. Here's how it works:
|
88
|
-
|
89
|
-
1. it finds an instance of the model by ID;
|
90
|
-
2. it authorizes the record;
|
91
|
-
3. it destroys the record;
|
92
|
-
4. it responds with 204 No Content.
|
93
|
-
|
94
|
-
To create a Destroy operation, inherit from `Pragma::Operation::Destroy`:
|
95
|
-
|
96
|
-
```ruby
|
97
|
-
module API
|
98
|
-
module V1
|
99
|
-
module Post
|
100
|
-
module Operation
|
101
|
-
class Destroy < Pragma::Operation::Destroy
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
```
|
108
|
-
|
109
|
-
To override the defaults of this operation, have a look at the [source code](https://github.com/pragmarb/pragma/blob/master/lib/pragma/operation/destroy.rb).
|
@@ -1,83 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Pragma
|
3
|
-
module Operation
|
4
|
-
# Provides support for inferring decorator, policy and contract names from the class name.
|
5
|
-
#
|
6
|
-
# @author Alessandro Desantis
|
7
|
-
module Defaults
|
8
|
-
def self.included(klass)
|
9
|
-
klass.extend ClassMethods
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods # :nodoc:
|
13
|
-
# Returns the decorator class for the current resource (if the inferred class exists).
|
14
|
-
#
|
15
|
-
# If the operation name is +API::V1::Post::Operation::Show+, returns
|
16
|
-
# +API::V1::Post::Decorator+.
|
17
|
-
#
|
18
|
-
# @return [Class]
|
19
|
-
def decorator_klass
|
20
|
-
super || (
|
21
|
-
Object.const_get(computed_decorator_klass) if class_exists?(computed_decorator_klass)
|
22
|
-
)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Returns the policy class for the current resource (if the inferred class exists).
|
26
|
-
#
|
27
|
-
# If the operation name is +API::V1::Post::Operation::Show+, returns
|
28
|
-
# +API::V1::Post::Policy+.
|
29
|
-
#
|
30
|
-
# @return [Class]
|
31
|
-
def policy_klass
|
32
|
-
super || (
|
33
|
-
Object.const_get(computed_policy_klass) if class_exists?(computed_policy_klass)
|
34
|
-
)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Returns the contract class for the current resource (if the inferred class exists).
|
38
|
-
#
|
39
|
-
# If the operation name is +API::V1::Post::Operation::Create+, returns
|
40
|
-
# +API::V1::Post::Contract::Create+.
|
41
|
-
#
|
42
|
-
# @return [Class]
|
43
|
-
def contract_klass
|
44
|
-
super || (
|
45
|
-
Object.const_get(computed_contract_klass) if class_exists?(computed_contract_klass)
|
46
|
-
)
|
47
|
-
end
|
48
|
-
|
49
|
-
# Returns the model class for the current resource (if the inferred class exists).
|
50
|
-
#
|
51
|
-
# If the operation name is +API::V1::Post::Operation::Create+, returns +::Post+.
|
52
|
-
def model_klass
|
53
|
-
Object.const_get("::#{name.split('::')[0..-3].last}")
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def computed_decorator_klass
|
59
|
-
(name.split('::')[0..-3] << 'Decorator').join('::')
|
60
|
-
end
|
61
|
-
|
62
|
-
def computed_policy_klass
|
63
|
-
(name.split('::')[0..-3] << 'Policy').join('::')
|
64
|
-
end
|
65
|
-
|
66
|
-
def computed_contract_klass
|
67
|
-
name_parts = name.split('::')
|
68
|
-
(name_parts[0..-3] << 'Contract' << name_parts.last).join('::')
|
69
|
-
end
|
70
|
-
|
71
|
-
def class_exists?(klass)
|
72
|
-
begin
|
73
|
-
Object.const_get(klass)
|
74
|
-
rescue NameError => e
|
75
|
-
raise e unless e.message.include?("uninitialized constant #{klass}")
|
76
|
-
end
|
77
|
-
|
78
|
-
Object.const_defined?(klass)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|