pragma 2.1.1 → 2.2.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 +5 -5
- data/.gitignore +1 -0
- data/CHANGELOG.md +23 -1
- data/README.md +22 -15
- data/lib/pragma.rb +21 -15
- data/lib/pragma/filter/base.rb +17 -0
- data/lib/pragma/filter/equals.rb +18 -0
- data/lib/pragma/filter/ilike.rb +18 -0
- data/lib/pragma/filter/like.rb +18 -0
- data/lib/pragma/filter/scope.rb +18 -0
- data/lib/pragma/filter/where.rb +18 -0
- data/lib/pragma/macro/classes.rb +98 -0
- data/lib/pragma/macro/contract/build.rb +25 -0
- data/lib/pragma/macro/contract/persist.rb +25 -0
- data/lib/pragma/macro/contract/validate.rb +25 -0
- data/lib/pragma/macro/decorator.rb +80 -0
- data/lib/pragma/macro/filtering.rb +45 -0
- data/lib/pragma/macro/model.rb +28 -0
- data/lib/pragma/macro/ordering.rb +81 -0
- data/lib/pragma/macro/pagination.rb +94 -0
- data/lib/pragma/macro/policy.rb +41 -0
- data/lib/pragma/operation/create.rb +1 -1
- data/lib/pragma/operation/destroy.rb +2 -2
- data/lib/pragma/operation/filter.rb +7 -0
- data/lib/pragma/operation/index.rb +3 -3
- data/lib/pragma/operation/macro.rb +7 -0
- data/lib/pragma/operation/show.rb +1 -1
- data/lib/pragma/operation/update.rb +1 -1
- data/lib/pragma/version.rb +1 -1
- metadata +21 -17
- data/lib/pragma/operation/filter/base.rb +0 -20
- data/lib/pragma/operation/filter/equals.rb +0 -13
- data/lib/pragma/operation/filter/ilike.rb +0 -13
- data/lib/pragma/operation/filter/like.rb +0 -13
- data/lib/pragma/operation/macro/classes.rb +0 -102
- data/lib/pragma/operation/macro/contract/build.rb +0 -27
- data/lib/pragma/operation/macro/contract/persist.rb +0 -27
- data/lib/pragma/operation/macro/contract/validate.rb +0 -27
- data/lib/pragma/operation/macro/decorator.rb +0 -82
- data/lib/pragma/operation/macro/filtering.rb +0 -47
- data/lib/pragma/operation/macro/model.rb +0 -30
- data/lib/pragma/operation/macro/ordering.rb +0 -84
- data/lib/pragma/operation/macro/pagination.rb +0 -96
- data/lib/pragma/operation/macro/policy.rb +0 -40
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'trailblazer/operation/model'
|
4
|
-
|
5
|
-
module Pragma
|
6
|
-
module Operation
|
7
|
-
module Macro
|
8
|
-
def self.Model(action = nil)
|
9
|
-
step = lambda do |input, options|
|
10
|
-
Trailblazer::Operation::Pipetree::Step.new(
|
11
|
-
Trailblazer::Operation::Model.for(options['model.class'], action),
|
12
|
-
'model.class' => options['model.class'],
|
13
|
-
'model.action' => action
|
14
|
-
).call(input, options).tap do |result|
|
15
|
-
unless result
|
16
|
-
options['result.response'] = Pragma::Operation::Response::NotFound.new.decorate_with(
|
17
|
-
Pragma::Decorator::Error
|
18
|
-
)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
[step, name: "model.#{action || 'build'}"]
|
24
|
-
end
|
25
|
-
|
26
|
-
module Model
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Pragma
|
4
|
-
module Operation
|
5
|
-
module Macro
|
6
|
-
def self.Ordering
|
7
|
-
step = ->(input, options) { Ordering.for(input, options) }
|
8
|
-
[step, name: 'ordering']
|
9
|
-
end
|
10
|
-
|
11
|
-
module Ordering
|
12
|
-
class << self
|
13
|
-
def for(_input, options)
|
14
|
-
set_defaults(options)
|
15
|
-
|
16
|
-
unless validate_params(options)
|
17
|
-
handle_invalid_contract(options)
|
18
|
-
return false
|
19
|
-
end
|
20
|
-
|
21
|
-
order_column = order_column(options)
|
22
|
-
|
23
|
-
if order_column
|
24
|
-
options['model'] = options['model'].order(order_column => order_direction(options))
|
25
|
-
end
|
26
|
-
|
27
|
-
true
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def set_defaults(options)
|
33
|
-
default_column = if options['model.class']&.method_defined?(:created_at)
|
34
|
-
:created_at
|
35
|
-
end
|
36
|
-
|
37
|
-
{
|
38
|
-
'ordering.columns' => [default_column].compact,
|
39
|
-
'ordering.default_column' => default_column,
|
40
|
-
'ordering.default_direction' => :desc,
|
41
|
-
'ordering.column_param' => :order_property,
|
42
|
-
'ordering.direction_param' => :order_direction
|
43
|
-
}.each_pair do |key, value|
|
44
|
-
options[key] = value unless options[key]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def validate_params(options)
|
49
|
-
options['contract.ordering'] = Dry::Validation.Schema do
|
50
|
-
optional(options['ordering.column_param']).filled do
|
51
|
-
str? & included_in?(options['ordering.columns'].map(&:to_s))
|
52
|
-
end
|
53
|
-
optional(options['ordering.direction_param']).filled do
|
54
|
-
str? & included_in?(%w[asc desc ASC DESC])
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
options['result.contract.ordering'] = options['contract.ordering'].call(
|
59
|
-
options['params']
|
60
|
-
)
|
61
|
-
|
62
|
-
options['result.contract.ordering'].errors.empty?
|
63
|
-
end
|
64
|
-
|
65
|
-
def handle_invalid_contract(options)
|
66
|
-
options['result.response'] = Response::UnprocessableEntity.new(
|
67
|
-
errors: options['result.contract.ordering'].errors
|
68
|
-
).decorate_with(Pragma::Decorator::Error)
|
69
|
-
end
|
70
|
-
|
71
|
-
def order_column(options)
|
72
|
-
params = options['params']
|
73
|
-
params[options['ordering.column_param']] || options['ordering.default_column']
|
74
|
-
end
|
75
|
-
|
76
|
-
def order_direction(options)
|
77
|
-
params = options['params']
|
78
|
-
params[options['ordering.direction_param']] || options['ordering.default_direction']
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Pragma
|
4
|
-
module Operation
|
5
|
-
module Macro
|
6
|
-
def self.Pagination
|
7
|
-
step = ->(input, options) { Pagination.for(input, options) }
|
8
|
-
[step, name: 'pagination']
|
9
|
-
end
|
10
|
-
|
11
|
-
module Pagination
|
12
|
-
class << self
|
13
|
-
def for(_input, options)
|
14
|
-
set_defaults(options)
|
15
|
-
normalize_params(options)
|
16
|
-
|
17
|
-
unless validate_params(options)
|
18
|
-
handle_invalid_contract(options)
|
19
|
-
return false
|
20
|
-
end
|
21
|
-
|
22
|
-
options['model'] = options['model'].paginate(
|
23
|
-
page: page(options, **options),
|
24
|
-
per_page: per_page(options, **options)
|
25
|
-
)
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def set_defaults(options)
|
31
|
-
{
|
32
|
-
'pagination.page_param' => :page,
|
33
|
-
'pagination.per_page_param' => :per_page,
|
34
|
-
'pagination.default_per_page' => 30,
|
35
|
-
'pagination.max_per_page' => 100
|
36
|
-
}.each_pair do |key, value|
|
37
|
-
options[key] = value unless options[key]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def normalize_params(options)
|
42
|
-
# This is required because Rails treats all incoming parameters as strings, since it
|
43
|
-
# can't distinguish. Maybe there's a better way to do it?
|
44
|
-
options['params'].tap do |p|
|
45
|
-
%w[pagination.page_param pagination.per_page_param].each do |key|
|
46
|
-
if p[options[key]] && p[options[key]].respond_to?(:to_i)
|
47
|
-
p[options[key]] = p[options[key]].to_i
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def validate_params(options)
|
54
|
-
options['contract.pagination'] = Dry::Validation.Schema do
|
55
|
-
optional(options['pagination.page_param']).filled { int? & gteq?(1) }
|
56
|
-
optional(options['pagination.per_page_param']).filled do
|
57
|
-
int? & (gteq?(1) & lteq?(options['pagination.max_per_page']))
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
options['result.contract.pagination'] = options['contract.pagination'].call(
|
62
|
-
options['params']
|
63
|
-
)
|
64
|
-
|
65
|
-
options['result.contract.pagination'].errors.empty?
|
66
|
-
end
|
67
|
-
|
68
|
-
def handle_invalid_contract(options)
|
69
|
-
options['result.response'] = Response::UnprocessableEntity.new(
|
70
|
-
errors: options['result.contract.pagination'].errors
|
71
|
-
).decorate_with(Pragma::Decorator::Error)
|
72
|
-
end
|
73
|
-
|
74
|
-
def page(options, params:, **)
|
75
|
-
return 1 if
|
76
|
-
!params[options['pagination.page_param']] ||
|
77
|
-
params[options['pagination.page_param']].blank?
|
78
|
-
|
79
|
-
params[options['pagination.page_param']].to_i
|
80
|
-
end
|
81
|
-
|
82
|
-
def per_page(options, params:, **)
|
83
|
-
return options['pagination.default_per_page'] if
|
84
|
-
!params[options['pagination.per_page_param']] ||
|
85
|
-
params[options['pagination.per_page_param']].blank?
|
86
|
-
|
87
|
-
[
|
88
|
-
params[options['pagination.per_page_param']].to_i,
|
89
|
-
options['pagination.max_per_page']
|
90
|
-
].min
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Pragma
|
4
|
-
module Operation
|
5
|
-
module Macro
|
6
|
-
def self.Policy(name: :default)
|
7
|
-
step = ->(input, options) { Policy.for(input, name, options) }
|
8
|
-
[step, name: "policy.#{name}"]
|
9
|
-
end
|
10
|
-
|
11
|
-
module Policy
|
12
|
-
class << self
|
13
|
-
def for(input, name, options)
|
14
|
-
policy = options["policy.#{name}.class"].new(options['current_user'], options['model'])
|
15
|
-
|
16
|
-
options["result.policy.#{name}"] = Trailblazer::Operation::Result.new(
|
17
|
-
policy.send("#{input.class.operation_name}?"),
|
18
|
-
'policy' => policy
|
19
|
-
)
|
20
|
-
|
21
|
-
unless options["result.policy.#{name}"].success?
|
22
|
-
handle_unauthorized!(options)
|
23
|
-
return false
|
24
|
-
end
|
25
|
-
|
26
|
-
true
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def handle_unauthorized!(options)
|
32
|
-
options['result.response'] = Pragma::Operation::Response::Forbidden.new.decorate_with(
|
33
|
-
Pragma::Decorator::Error
|
34
|
-
)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|