snfoil-rails 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CODE_OF_CONDUCT.md +74 -0
- data/Rakefile +1 -1
- data/lib/generators/sn_foil/sn_foil_generator.rb +47 -0
- data/lib/sn_foil/controller/api.rb +77 -0
- data/lib/sn_foil/controller/base.rb +19 -0
- data/lib/sn_foil/controller/concerns/change_controller_concern.rb +21 -0
- data/lib/sn_foil/controller/concerns/create_controller_concern.rb +38 -0
- data/lib/sn_foil/controller/concerns/destroy_controller_concern.rb +40 -0
- data/lib/sn_foil/controller/concerns/index_controller_concern.rb +66 -0
- data/lib/sn_foil/controller/concerns/setup_controller_concern.rb +84 -0
- data/lib/sn_foil/controller/concerns/show_controller_concern.rb +36 -0
- data/lib/sn_foil/controller/concerns/update_controller_concern.rb +38 -0
- data/lib/sn_foil/jsonapi_deserializer.rb +151 -0
- data/lib/sn_foil/jsonapi_serializer.rb +16 -0
- data/lib/sn_foil/rails.rb +18 -7
- data/lib/sn_foil/rails/engine.rb +24 -0
- data/lib/sn_foil/rails/version.rb +1 -1
- data/lib/sn_foil/searcher.rb +123 -0
- metadata +47 -13
- data/lib/sn_foil/rails/controller/api.rb +0 -22
- data/lib/sn_foil/rails/controller/concerns/change_controller_concern.rb +0 -28
- data/lib/sn_foil/rails/controller/concerns/create_controller_concern.rb +0 -40
- data/lib/sn_foil/rails/controller/concerns/destroy_controller_concern.rb +0 -42
- data/lib/sn_foil/rails/controller/concerns/index_controller_concern.rb +0 -72
- data/lib/sn_foil/rails/controller/concerns/setup_controller_concern.rb +0 -110
- data/lib/sn_foil/rails/controller/concerns/show_controller_concern.rb +0 -38
- data/lib/sn_foil/rails/controller/concerns/update_controller_concern.rb +0 -40
- data/lib/sn_foil/rails/railtie.rb +0 -10
- data/lib/sn_foil/rails/searcher.rb +0 -127
- data/lib/tasks/sn_foil/rails_tasks.rake +0 -5
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'action_controller/api'
|
4
|
-
require_relative 'concerns/create_controller_concern'
|
5
|
-
require_relative 'concerns/destroy_controller_concern'
|
6
|
-
require_relative 'concerns/index_controller_concern'
|
7
|
-
require_relative 'concerns/show_controller_concern'
|
8
|
-
require_relative 'concerns/update_controller_concern'
|
9
|
-
|
10
|
-
module SnFoil
|
11
|
-
module Rails
|
12
|
-
module Controller
|
13
|
-
class API < ::ActionController::API
|
14
|
-
include Concerns::CreateControllerConcern
|
15
|
-
include Concerns::DestroyControllerConcern
|
16
|
-
include Concerns::IndexControllerConcern
|
17
|
-
include Concerns::ShowControllerConcern
|
18
|
-
include Concerns::UpdateControllerConcern
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require_relative 'setup_controller_concern'
|
5
|
-
|
6
|
-
module SnFoil
|
7
|
-
module Rails
|
8
|
-
module Controller
|
9
|
-
module Concerns
|
10
|
-
module ChangeControllerConcern
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
|
13
|
-
included do
|
14
|
-
include SetupControllerConcern
|
15
|
-
end
|
16
|
-
|
17
|
-
def render_change(model, **_options)
|
18
|
-
if model.errors.empty?
|
19
|
-
render model
|
20
|
-
else
|
21
|
-
render model.errors, status: :unprocessable_entity
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require_relative 'setup_controller_concern'
|
5
|
-
require_relative 'change_controller_concern'
|
6
|
-
|
7
|
-
module SnFoil
|
8
|
-
module Rails
|
9
|
-
module Controller
|
10
|
-
module Concerns
|
11
|
-
module CreateControllerConcern
|
12
|
-
extend ActiveSupport::Concern
|
13
|
-
|
14
|
-
included do
|
15
|
-
include SetupControllerConcern
|
16
|
-
include ChangeControllerConcern
|
17
|
-
end
|
18
|
-
|
19
|
-
def create(**options)
|
20
|
-
options = setup_create(**options)
|
21
|
-
model = process_create(**options)
|
22
|
-
render_create(model, **options)
|
23
|
-
end
|
24
|
-
|
25
|
-
def setup_create(**options)
|
26
|
-
setup_options(**options.merge(deserialize: true))
|
27
|
-
end
|
28
|
-
|
29
|
-
def process_create(**options)
|
30
|
-
current_context(**options).create(**options)
|
31
|
-
end
|
32
|
-
|
33
|
-
def render_create(model, **options)
|
34
|
-
render_change(model, **options)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require_relative 'setup_controller_concern'
|
5
|
-
|
6
|
-
module SnFoil
|
7
|
-
module Rails
|
8
|
-
module Controller
|
9
|
-
module Concerns
|
10
|
-
module DestroyControllerConcern
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
|
13
|
-
included do
|
14
|
-
include SetupControllerConcern
|
15
|
-
end
|
16
|
-
|
17
|
-
def destroy(**options)
|
18
|
-
options = setup_update(**options)
|
19
|
-
model = process_destroy(**options)
|
20
|
-
render_destroy(model, **options)
|
21
|
-
end
|
22
|
-
|
23
|
-
def setup_destroy(**options)
|
24
|
-
setup_options(**options)
|
25
|
-
end
|
26
|
-
|
27
|
-
def process_destroy(**options)
|
28
|
-
current_context(**options).destroy(**options)
|
29
|
-
end
|
30
|
-
|
31
|
-
def render_destroy(model, **_options)
|
32
|
-
if model.errors.empty?
|
33
|
-
render nil
|
34
|
-
else
|
35
|
-
render model.errors, status: :unprocessable_entity
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require_relative 'setup_controller_concern'
|
5
|
-
|
6
|
-
module SnFoil
|
7
|
-
module Rails
|
8
|
-
module Controller
|
9
|
-
module Concerns
|
10
|
-
module IndexControllerConcern
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
|
13
|
-
included do
|
14
|
-
include SetupControllerConcern
|
15
|
-
end
|
16
|
-
|
17
|
-
def index(**options)
|
18
|
-
options = setup_index(**options)
|
19
|
-
results = process_index(**options)
|
20
|
-
render_index(results, **options)
|
21
|
-
end
|
22
|
-
|
23
|
-
def setup_index(**options)
|
24
|
-
setup_options(**options)
|
25
|
-
end
|
26
|
-
|
27
|
-
def process_index(**options)
|
28
|
-
searcher = options.fetch(:searcher) do
|
29
|
-
current_context(**options).index(options)
|
30
|
-
end
|
31
|
-
searcher.results
|
32
|
-
end
|
33
|
-
|
34
|
-
def render_index(results, **options)
|
35
|
-
paginate(results, **options)
|
36
|
-
end
|
37
|
-
|
38
|
-
def paginate(results, **options)
|
39
|
-
return results unless results.respond_to?(:page)
|
40
|
-
|
41
|
-
results.page(page(**options))
|
42
|
-
.per(per_page(**options))
|
43
|
-
end
|
44
|
-
|
45
|
-
def page(**options)
|
46
|
-
options[:params].fetch(:page, 1).to_i
|
47
|
-
end
|
48
|
-
|
49
|
-
def per_page(**options)
|
50
|
-
per_page_param = options[:params].fetch(:per_page, 10).to_i
|
51
|
-
return 10_000 if per_page_param.zero?
|
52
|
-
|
53
|
-
per_page_param
|
54
|
-
end
|
55
|
-
|
56
|
-
def meta(results, **options)
|
57
|
-
total_pages = results&.total_pages
|
58
|
-
total_count = results&.total_count
|
59
|
-
paginated = total_pages && total_count
|
60
|
-
|
61
|
-
{
|
62
|
-
page: paginated ? page(**options) : nil,
|
63
|
-
pages: total_pages || 1,
|
64
|
-
total: total_count || 1,
|
65
|
-
per: paginated ? per_page(**options) : nil
|
66
|
-
}
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
|
-
module SnFoil
|
6
|
-
module Rails
|
7
|
-
module Controller
|
8
|
-
module Concerns
|
9
|
-
module SetupControllerConcern
|
10
|
-
extend ActiveSupport::Concern
|
11
|
-
|
12
|
-
class_methods do
|
13
|
-
attr_reader :i_deserializer, :i_serializer, :i_context
|
14
|
-
|
15
|
-
def context(klass = nil)
|
16
|
-
@i_context = klass
|
17
|
-
end
|
18
|
-
|
19
|
-
def serializer(klass = nil)
|
20
|
-
@i_serializer = klass
|
21
|
-
end
|
22
|
-
|
23
|
-
def deserializer(klass = nil)
|
24
|
-
@i_deserializer = klass
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def context(**options)
|
29
|
-
options[:context] || self.class.i_context
|
30
|
-
end
|
31
|
-
|
32
|
-
def serializer(**options)
|
33
|
-
options[:serializer] || self.class.i_serializer
|
34
|
-
end
|
35
|
-
|
36
|
-
def deserializer(**options)
|
37
|
-
options[:deserializer] || self.class.i_deserializer
|
38
|
-
end
|
39
|
-
|
40
|
-
def setup_options(**options)
|
41
|
-
options = inject_params(**options)
|
42
|
-
options = inject_id(**options)
|
43
|
-
options = inject_includes(**options)
|
44
|
-
options = inject_controller_action(**options)
|
45
|
-
inject_deserialized_params(**options)
|
46
|
-
end
|
47
|
-
|
48
|
-
def current_context(**options)
|
49
|
-
@current_context ||= context(**options).new(context_user)
|
50
|
-
end
|
51
|
-
|
52
|
-
protected
|
53
|
-
|
54
|
-
def pundit_not_authorized
|
55
|
-
head :forbidden
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
# Grab the rails params and inject them into the options
|
61
|
-
def inject_params(**options)
|
62
|
-
return options unless params
|
63
|
-
|
64
|
-
options[:params] = params.to_unsafe_h.deep_symbolize_keys
|
65
|
-
options[:controller_params] = options[:params]
|
66
|
-
options
|
67
|
-
end
|
68
|
-
|
69
|
-
def inject_id(**options)
|
70
|
-
return options if options[:id]
|
71
|
-
|
72
|
-
options[:id] = id if defined? id
|
73
|
-
options[:id] ||= options[:params][:id]
|
74
|
-
options
|
75
|
-
end
|
76
|
-
|
77
|
-
def inject_includes(**options)
|
78
|
-
return options if options[:include]
|
79
|
-
return options unless options.dig(:params, :include)
|
80
|
-
|
81
|
-
options[:include] = options.dig(:params, :include)
|
82
|
-
.split(',')
|
83
|
-
.map { |item| item.underscore.to_sym }
|
84
|
-
options
|
85
|
-
end
|
86
|
-
|
87
|
-
def inject_controller_action(**options)
|
88
|
-
return options if options[:controller_action]
|
89
|
-
return options unless options.dig(:params, :action)
|
90
|
-
|
91
|
-
options[:controller_action] = options[:params][:action]
|
92
|
-
options
|
93
|
-
end
|
94
|
-
|
95
|
-
def inject_deserialized_params(**options)
|
96
|
-
return options unless options[:params].present? && options[:deserialize] == true
|
97
|
-
return options unless deserializer(**options)
|
98
|
-
|
99
|
-
options[:params] = deserializer(**options).new(options[:params], **options).to_h
|
100
|
-
options
|
101
|
-
end
|
102
|
-
|
103
|
-
def context_user
|
104
|
-
return current_user if defined? current_user
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require_relative 'setup_controller_concern'
|
5
|
-
|
6
|
-
module SnFoil
|
7
|
-
module Rails
|
8
|
-
module Controller
|
9
|
-
module Concerns
|
10
|
-
module ShowControllerConcern
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
|
13
|
-
included do
|
14
|
-
include SetupControllerConcern
|
15
|
-
end
|
16
|
-
|
17
|
-
def show(**options)
|
18
|
-
options = setup_show(**options)
|
19
|
-
model = process_show(**options)
|
20
|
-
render_show(model, **options)
|
21
|
-
end
|
22
|
-
|
23
|
-
def setup_show(**options)
|
24
|
-
setup_options(**options)
|
25
|
-
end
|
26
|
-
|
27
|
-
def process_show(**options)
|
28
|
-
current_context(**options).show(**options)
|
29
|
-
end
|
30
|
-
|
31
|
-
def render_show(model, **_options)
|
32
|
-
render model
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require_relative 'setup_controller_concern'
|
5
|
-
require_relative 'change_controller_concern'
|
6
|
-
|
7
|
-
module SnFoil
|
8
|
-
module Rails
|
9
|
-
module Controller
|
10
|
-
module Concerns
|
11
|
-
module UpdateControllerConcern
|
12
|
-
extend ActiveSupport::Concern
|
13
|
-
|
14
|
-
included do
|
15
|
-
include SetupControllerConcern
|
16
|
-
include ChangeControllerConcern
|
17
|
-
end
|
18
|
-
|
19
|
-
def update(**options)
|
20
|
-
options = setup_update(**options)
|
21
|
-
model = process_update(**options)
|
22
|
-
render_update(model, **options)
|
23
|
-
end
|
24
|
-
|
25
|
-
def setup_update(**options)
|
26
|
-
setup_options(**options.merge(deserialize: true))
|
27
|
-
end
|
28
|
-
|
29
|
-
def process_update(**options)
|
30
|
-
current_context(**options).update(**options)
|
31
|
-
end
|
32
|
-
|
33
|
-
def render_update(model, **options)
|
34
|
-
render_change(model, **options)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,127 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require 'sn_foil/searcher'
|
5
|
-
|
6
|
-
module SnFoil
|
7
|
-
module Rails
|
8
|
-
module Searcher
|
9
|
-
extend ActiveSupport::Concern
|
10
|
-
|
11
|
-
included do
|
12
|
-
include SnFoil::Searcher
|
13
|
-
|
14
|
-
module_eval do
|
15
|
-
alias_method :base_search, :search
|
16
|
-
|
17
|
-
# patch the additional search capabilities into the method
|
18
|
-
def search(params = {})
|
19
|
-
filtered_scope = base_search(params)
|
20
|
-
additional_search(filtered_scope, params)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
ASC ||= 'ASC'
|
25
|
-
DESC ||= 'DESC'
|
26
|
-
end
|
27
|
-
|
28
|
-
class_methods do
|
29
|
-
attr_reader :i_include_params, :i_order_method, :i_order_block, :i_order_by_attr, :i_order_by_direction, :i_is_distinct
|
30
|
-
|
31
|
-
def order(method = nil, &block)
|
32
|
-
@i_order_method = method
|
33
|
-
@i_order_block = block
|
34
|
-
end
|
35
|
-
|
36
|
-
def order_by(attr, direction = nil)
|
37
|
-
@i_order_by_attr = attr
|
38
|
-
@i_order_by_direction = direction
|
39
|
-
end
|
40
|
-
|
41
|
-
def distinct(bool = true)
|
42
|
-
@i_is_distinct = bool
|
43
|
-
end
|
44
|
-
|
45
|
-
def includes(*array)
|
46
|
-
@i_include_params ||= [] # create new array if none exists
|
47
|
-
@i_include_params |= array # combine unique elements of both arrays
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def distinct?
|
52
|
-
self.class.i_is_distinct || false
|
53
|
-
end
|
54
|
-
|
55
|
-
def included_params
|
56
|
-
self.class.i_include_params
|
57
|
-
end
|
58
|
-
|
59
|
-
def order_by(params = {})
|
60
|
-
if params[:order_by].present?
|
61
|
-
params[:order_by] = params[:order_by].to_s.underscore
|
62
|
-
return params[:order_by].to_sym if model.attribute_names.include?(params[:order_by])
|
63
|
-
end
|
64
|
-
|
65
|
-
self.class.i_order_by_attr || :id
|
66
|
-
end
|
67
|
-
|
68
|
-
def order(params = {})
|
69
|
-
if params[:order].present?
|
70
|
-
params[:order] = params[:order].to_s.upcase
|
71
|
-
return params[:order] if params[:order].eql?(ASC) || params[:order].eql?(DESC)
|
72
|
-
end
|
73
|
-
|
74
|
-
self.class.i_order_by_direction || ASC
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
def additional_search(filtered_scope, params = {})
|
80
|
-
filtered_scope = apply_order(filtered_scope, params)
|
81
|
-
filtered_scope = apply_includes(filtered_scope)
|
82
|
-
apply_distinct(filtered_scope, params)
|
83
|
-
end
|
84
|
-
|
85
|
-
def apply_includes(filtered_scope)
|
86
|
-
return filtered_scope unless included_params
|
87
|
-
|
88
|
-
filtered_scope.includes(*included_params)
|
89
|
-
end
|
90
|
-
|
91
|
-
def apply_order(filtered_scope, params)
|
92
|
-
return apply_default_order(filtered_scope, params) if params[:order_by].blank? && params[:order].blank?
|
93
|
-
|
94
|
-
filtered_scope.order(order_by(params) => order(params))
|
95
|
-
end
|
96
|
-
|
97
|
-
def apply_default_order(filtered_scope, params)
|
98
|
-
return order_method(filtered_scope, params) if order_method?
|
99
|
-
return order_block(filtered_scope, params) if order_block?
|
100
|
-
|
101
|
-
filtered_scope.order(order_by => order)
|
102
|
-
end
|
103
|
-
|
104
|
-
def order_method(filtered_scope, params)
|
105
|
-
send(self.class.i_order_method, filtered_scope, params)
|
106
|
-
end
|
107
|
-
|
108
|
-
def order_method?
|
109
|
-
self.class.i_order_method.present?
|
110
|
-
end
|
111
|
-
|
112
|
-
def order_block(filtered_scope, params)
|
113
|
-
self.class.i_order_block.call(filtered_scope, params)
|
114
|
-
end
|
115
|
-
|
116
|
-
def order_block?
|
117
|
-
self.class.i_order_block.present?
|
118
|
-
end
|
119
|
-
|
120
|
-
def apply_distinct(filtered_scope, params)
|
121
|
-
return filtered_scope unless distinct? || params[:distinct] == true
|
122
|
-
|
123
|
-
filtered_scope.distinct
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|