pragma 2.1.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|