snfoil-rails 0.8.3 → 1.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
- metadata +146 -65
- data/CODE_OF_CONDUCT.md +0 -74
- data/MIT-LICENSE +0 -20
- data/README.md +0 -28
- data/Rakefile +0 -29
- data/lib/generators/sn_foil/all/all_generator.rb +0 -50
- data/lib/generators/sn_foil/context/context_generator.rb +0 -41
- data/lib/generators/sn_foil/context/templates/context.erb +0 -9
- data/lib/generators/sn_foil/controller/controller_generator.rb +0 -52
- data/lib/generators/sn_foil/controller/templates/api_controller.erb +0 -14
- data/lib/generators/sn_foil/controller/templates/controller.erb +0 -14
- data/lib/generators/sn_foil/jsonapi_deserializer/jsonapi_deserializer_generator.rb +0 -41
- data/lib/generators/sn_foil/jsonapi_deserializer/templates/jsonapi_deserializer.erb +0 -12
- data/lib/generators/sn_foil/jsonapi_serializer/jsonapi_serializer_generator.rb +0 -41
- data/lib/generators/sn_foil/jsonapi_serializer/templates/jsonapi_serializer.erb +0 -20
- data/lib/generators/sn_foil/policy/policy_generator.rb +0 -41
- data/lib/generators/sn_foil/policy/templates/policy.erb +0 -22
- data/lib/generators/sn_foil/searcher/searcher_generator.rb +0 -41
- data/lib/generators/sn_foil/searcher/templates/searcher.erb +0 -7
- data/lib/sn_foil/configuration/lazy_jsonapi_serializer.rb +0 -87
- data/lib/sn_foil/controller/api.rb +0 -90
- data/lib/sn_foil/controller/base.rb +0 -19
- data/lib/sn_foil/controller/concerns/change_controller_concern.rb +0 -21
- data/lib/sn_foil/controller/concerns/create_controller_concern.rb +0 -38
- data/lib/sn_foil/controller/concerns/destroy_controller_concern.rb +0 -40
- data/lib/sn_foil/controller/concerns/index_controller_concern.rb +0 -67
- data/lib/sn_foil/controller/concerns/setup_controller_concern.rb +0 -85
- data/lib/sn_foil/controller/concerns/show_controller_concern.rb +0 -36
- data/lib/sn_foil/controller/concerns/update_controller_concern.rb +0 -38
- data/lib/sn_foil/jsonapi_deserializer.rb +0 -159
- data/lib/sn_foil/jsonapi_serializer.rb +0 -16
- data/lib/sn_foil/rails/engine.rb +0 -23
- data/lib/sn_foil/rails/version.rb +0 -7
- data/lib/sn_foil/rails.rb +0 -25
- data/lib/sn_foil/searcher.rb +0 -122
- data/lib/snfoil-rails.rb +0 -5
@@ -1,85 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
|
-
module SnFoil
|
6
|
-
module Controller
|
7
|
-
module Concerns
|
8
|
-
module SetupControllerConcern
|
9
|
-
extend ActiveSupport::Concern
|
10
|
-
|
11
|
-
class_methods do
|
12
|
-
attr_reader :i_context
|
13
|
-
|
14
|
-
def context(klass = nil)
|
15
|
-
@i_context = klass
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def context(**options)
|
20
|
-
options[:context] || self.class.i_context
|
21
|
-
end
|
22
|
-
|
23
|
-
def setup_options(**options)
|
24
|
-
options = inject_params(**options)
|
25
|
-
options = inject_id(**options)
|
26
|
-
options = inject_includes(**options)
|
27
|
-
inject_controller_action(**options)
|
28
|
-
end
|
29
|
-
|
30
|
-
def current_context(**options)
|
31
|
-
@current_context ||= context(**options).new(context_entity)
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
|
36
|
-
def pundit_not_authorized
|
37
|
-
head :forbidden
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
# Grab the rails params and inject them into the options
|
43
|
-
def inject_params(**options)
|
44
|
-
return options if options[:params]
|
45
|
-
return options unless params
|
46
|
-
|
47
|
-
options[:params] = params.to_unsafe_h.deep_symbolize_keys
|
48
|
-
options[:controller_params] = options[:params]
|
49
|
-
options
|
50
|
-
end
|
51
|
-
|
52
|
-
def inject_id(**options)
|
53
|
-
return options if options[:id]
|
54
|
-
|
55
|
-
options[:id] = id if defined? id
|
56
|
-
options[:id] ||= options[:params][:id]
|
57
|
-
options
|
58
|
-
end
|
59
|
-
|
60
|
-
def inject_includes(**options)
|
61
|
-
return options if options[:include]
|
62
|
-
return options unless options.dig(:params, :include)
|
63
|
-
|
64
|
-
options[:include] = options.dig(:params, :include)
|
65
|
-
.split(',')
|
66
|
-
.map { |item| item.underscore.to_sym }
|
67
|
-
options
|
68
|
-
end
|
69
|
-
|
70
|
-
def inject_controller_action(**options)
|
71
|
-
return options if options[:controller_action]
|
72
|
-
return options unless options.dig(:params, :action)
|
73
|
-
|
74
|
-
options[:controller_action] = options[:params][:action]
|
75
|
-
options
|
76
|
-
end
|
77
|
-
|
78
|
-
def context_entity
|
79
|
-
return current_entity if defined? current_entity
|
80
|
-
return current_user if defined? current_user
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
@@ -1,36 +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 Controller
|
8
|
-
module Concerns
|
9
|
-
module ShowControllerConcern
|
10
|
-
extend ActiveSupport::Concern
|
11
|
-
|
12
|
-
included do
|
13
|
-
include SetupControllerConcern
|
14
|
-
end
|
15
|
-
|
16
|
-
def show(**options)
|
17
|
-
options = setup_show(**options)
|
18
|
-
model = process_show(**options)
|
19
|
-
render_show(model, **options)
|
20
|
-
end
|
21
|
-
|
22
|
-
def setup_show(**options)
|
23
|
-
setup_options(**options)
|
24
|
-
end
|
25
|
-
|
26
|
-
def process_show(**options)
|
27
|
-
current_context(**options).show(**options)
|
28
|
-
end
|
29
|
-
|
30
|
-
def render_show(model, **_options)
|
31
|
-
render model
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,38 +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 Controller
|
9
|
-
module Concerns
|
10
|
-
module UpdateControllerConcern
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
|
13
|
-
included do
|
14
|
-
include SetupControllerConcern
|
15
|
-
include ChangeControllerConcern
|
16
|
-
end
|
17
|
-
|
18
|
-
def update(**options)
|
19
|
-
options = setup_update(**options)
|
20
|
-
model = process_update(**options)
|
21
|
-
render_update(model, **options)
|
22
|
-
end
|
23
|
-
|
24
|
-
def setup_update(**options)
|
25
|
-
setup_options(**options)
|
26
|
-
end
|
27
|
-
|
28
|
-
def process_update(**options)
|
29
|
-
current_context(**options).update(**options)
|
30
|
-
end
|
31
|
-
|
32
|
-
def render_update(model, **options)
|
33
|
-
render_change(model, **options)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,159 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
|
-
module SnFoil
|
6
|
-
module JsonapiDeserializer # rubocop:disable Metrics/ModuleLength
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
class_methods do
|
10
|
-
attr_reader :i_attribute_fields, :i_attribute_transforms
|
11
|
-
|
12
|
-
def attributes(*fields)
|
13
|
-
@i_attribute_fields ||= []
|
14
|
-
@i_attribute_fields |= fields
|
15
|
-
end
|
16
|
-
|
17
|
-
def attribute(key, **options)
|
18
|
-
@i_attribute_transforms ||= {}
|
19
|
-
@i_attribute_transforms[key] = options.merge(transform_type: :attribute)
|
20
|
-
end
|
21
|
-
|
22
|
-
def has_one(key, deserializer:, **options) # rubocop:disable Naming/PredicateName
|
23
|
-
@i_attribute_transforms ||= {}
|
24
|
-
@i_attribute_transforms[key] = options.merge(deserializer: deserializer, transform_type: :has_one)
|
25
|
-
end
|
26
|
-
alias_method :belongs_to, :has_one
|
27
|
-
|
28
|
-
def has_many(key, deserializer:, **options) # rubocop:disable Naming/PredicateName
|
29
|
-
@i_attribute_transforms ||= {}
|
30
|
-
@i_attribute_transforms[key] = options.merge(deserializer: deserializer, transform_type: :has_many)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
attr_reader :object, :included, :options
|
35
|
-
|
36
|
-
def initialize(object, included: nil, **options)
|
37
|
-
@object = object
|
38
|
-
@included = included || object[:included]
|
39
|
-
@options = options
|
40
|
-
end
|
41
|
-
|
42
|
-
def attribute_fields
|
43
|
-
self.class.i_attribute_fields || []
|
44
|
-
end
|
45
|
-
|
46
|
-
def attribute_transforms
|
47
|
-
self.class.i_attribute_transforms || {}
|
48
|
-
end
|
49
|
-
|
50
|
-
def attributes
|
51
|
-
@attributes ||= attribute_fields | attribute_transforms.map { |k, v| v[:key] || k }
|
52
|
-
end
|
53
|
-
|
54
|
-
def parse
|
55
|
-
parse_data
|
56
|
-
end
|
57
|
-
alias to_h parse
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def parse_data
|
62
|
-
if object[:data].is_a? Array
|
63
|
-
object[:data].map { |d| build_attributes(d) }
|
64
|
-
else
|
65
|
-
build_attributes(object[:data])
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def build_attributes(data)
|
70
|
-
attributes = data_id({}, data)
|
71
|
-
attributes = parse_standard_attributes(attributes, data) if data[:attributes]
|
72
|
-
attribute_transforms.each do |key, opts|
|
73
|
-
attributes = apply_attribute_transform(attributes, data, key, **opts)
|
74
|
-
end
|
75
|
-
attributes
|
76
|
-
end
|
77
|
-
|
78
|
-
def data_id(attributes, data)
|
79
|
-
if data[:id]
|
80
|
-
attributes[:id] = data[:id]
|
81
|
-
elsif data[:'local:id']
|
82
|
-
attributes[:lid] = data[:'local:id']
|
83
|
-
end
|
84
|
-
attributes
|
85
|
-
end
|
86
|
-
|
87
|
-
def parse_standard_attributes(attributes, data)
|
88
|
-
attributes.merge!(data[:attributes].select { |k, _| attribute_fields.include? k })
|
89
|
-
end
|
90
|
-
|
91
|
-
def apply_attribute_transform(attributes, data, key, transform_type:, **opts)
|
92
|
-
case transform_type
|
93
|
-
when :attribute
|
94
|
-
parse_attribute_transform(attributes, data, key, **opts)
|
95
|
-
when :has_one
|
96
|
-
parse_has_one_relationship(attributes, data, key, **opts)
|
97
|
-
when :has_many
|
98
|
-
parse_has_many_relationship(attributes, data, key, **opts)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def parse_attribute_transform(attributes, data, key, **opts)
|
103
|
-
return attributes unless data.dig(:attributes, key)
|
104
|
-
|
105
|
-
attributes.merge({ opts.fetch(:key) { key } => data[:attributes][key] })
|
106
|
-
end
|
107
|
-
|
108
|
-
def parse_relationships(attributes, data)
|
109
|
-
self.class.has_one_relationships.each do |key, opts|
|
110
|
-
attributes = has_one_relationship(attributes, data, key, **opts)
|
111
|
-
end
|
112
|
-
self.class.has_many_relationships.each do |key, opts|
|
113
|
-
attributes = has_many_relationship(attributes, data, key, **opts)
|
114
|
-
end
|
115
|
-
attributes
|
116
|
-
end
|
117
|
-
|
118
|
-
def parse_has_one_relationship(attributes, data, key, deserializer:, **opts)
|
119
|
-
resource_data = data.dig(:relationships, key, :data)
|
120
|
-
return attributes unless resource_data
|
121
|
-
|
122
|
-
resource_data = data_id(resource_data, resource_data)
|
123
|
-
attribute_data = lookup_relationship(resource_data)
|
124
|
-
relationship_data = { data: attribute_data || resource_data }
|
125
|
-
attributes[opts.fetch(:key) { key }] = deserializer.new(relationship_data, **options, included: included).parse
|
126
|
-
attributes
|
127
|
-
end
|
128
|
-
|
129
|
-
def parse_has_many_relationship(attributes, data, key, deserializer:, **opts)
|
130
|
-
array_data = data.dig(:relationships, key, :data)
|
131
|
-
return attributes unless array_data
|
132
|
-
|
133
|
-
attributes[opts.fetch(:key) { key }] = array_data.map do |resource_data|
|
134
|
-
resource_data = data_id(resource_data, resource_data)
|
135
|
-
attribute_data = lookup_relationship(resource_data)
|
136
|
-
relationship_data = { data: attribute_data || resource_data }
|
137
|
-
deserializer.new(relationship_data, **options, included: included).parse
|
138
|
-
end
|
139
|
-
attributes
|
140
|
-
end
|
141
|
-
|
142
|
-
def lookup_relationship(type:, id: nil, lid: nil, **_opts)
|
143
|
-
check_for_id(id, lid)
|
144
|
-
|
145
|
-
included&.find do |x|
|
146
|
-
x[:type].eql?(type) &&
|
147
|
-
if id
|
148
|
-
x[:id].eql?(id)
|
149
|
-
elsif lid
|
150
|
-
x[:'local:id'].eql?(lid)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def check_for_id(id, lid)
|
156
|
-
raise ::ArgumentError, "missing keyword: id or lid for type: #{type}" unless id || lid
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require 'jsonapi/serializer'
|
5
|
-
|
6
|
-
module SnFoil
|
7
|
-
module JsonapiSerializer
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
included do
|
11
|
-
include JSONAPI::Serializer
|
12
|
-
|
13
|
-
set_key_transform :dash
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/lib/sn_foil/rails/engine.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SnFoil
|
4
|
-
module Rails
|
5
|
-
class Engine < ::Rails::Engine
|
6
|
-
require 'sn_foil'
|
7
|
-
require_relative '../searcher'
|
8
|
-
require_relative '../jsonapi_serializer'
|
9
|
-
require_relative '../jsonapi_deserializer'
|
10
|
-
require_relative '../controller/concerns/change_controller_concern'
|
11
|
-
require_relative '../controller/concerns/create_controller_concern'
|
12
|
-
require_relative '../controller/concerns/destroy_controller_concern'
|
13
|
-
require_relative '../controller/concerns/index_controller_concern'
|
14
|
-
require_relative '../controller/concerns/setup_controller_concern'
|
15
|
-
require_relative '../controller/concerns/show_controller_concern'
|
16
|
-
require_relative '../controller/concerns/update_controller_concern'
|
17
|
-
require_relative '../controller/api'
|
18
|
-
require_relative '../controller/base'
|
19
|
-
|
20
|
-
require_relative '../configuration/lazy_jsonapi_serializer'
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/sn_foil/rails.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SnFoil
|
4
|
-
module Rails
|
5
|
-
if defined?(Rails)
|
6
|
-
require 'sn_foil/rails/engine'
|
7
|
-
else
|
8
|
-
require 'sn_foil'
|
9
|
-
require_relative '../searcher'
|
10
|
-
require_relative '../jsonapi_serializer'
|
11
|
-
require_relative '../jsonapi_deserializer'
|
12
|
-
require_relative '../controller/concerns/change_controller_concern'
|
13
|
-
require_relative '../controller/concerns/create_controller_concern'
|
14
|
-
require_relative '../controller/concerns/destroy_controller_concern'
|
15
|
-
require_relative '../controller/concerns/index_controller_concern'
|
16
|
-
require_relative '../controller/concerns/setup_controller_concern'
|
17
|
-
require_relative '../controller/concerns/show_controller_concern'
|
18
|
-
require_relative '../controller/concerns/update_controller_concern'
|
19
|
-
require_relative '../controller/api'
|
20
|
-
require_relative '../controller/base'
|
21
|
-
|
22
|
-
require_relative '../configuration/lazy_jsonapi_serializer'
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/sn_foil/searcher.rb
DELETED
@@ -1,122 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/concern'
|
4
|
-
require 'sn_foil/searcher'
|
5
|
-
|
6
|
-
module SnFoil
|
7
|
-
module Searcher
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
ASC = 'ASC'
|
10
|
-
DESC = 'DESC'
|
11
|
-
|
12
|
-
included do
|
13
|
-
module_eval do
|
14
|
-
alias_method :base_search, :search
|
15
|
-
|
16
|
-
# patch the additional search capabilities into the method
|
17
|
-
def search(params = {})
|
18
|
-
filtered_scope = base_search(params)
|
19
|
-
additional_search(filtered_scope, params)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
class_methods do
|
25
|
-
attr_reader :i_include_params, :i_order_method, :i_order_block, :i_order_by_attr, :i_order_by_direction, :i_is_distinct
|
26
|
-
|
27
|
-
def order(method = nil, &block)
|
28
|
-
@i_order_method = method
|
29
|
-
@i_order_block = block
|
30
|
-
end
|
31
|
-
|
32
|
-
def order_by(attr, direction = nil)
|
33
|
-
@i_order_by_attr = attr
|
34
|
-
@i_order_by_direction = direction
|
35
|
-
end
|
36
|
-
|
37
|
-
def distinct(bool = true) # rubocop:disable Style/OptionalBooleanParameter reason: class configuration looks better this way
|
38
|
-
@i_is_distinct = bool
|
39
|
-
end
|
40
|
-
|
41
|
-
def includes(*array)
|
42
|
-
@i_include_params ||= [] # create new array if none exists
|
43
|
-
@i_include_params |= array # combine unique elements of both arrays
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def distinct?
|
48
|
-
self.class.i_is_distinct || false
|
49
|
-
end
|
50
|
-
|
51
|
-
def included_params
|
52
|
-
self.class.i_include_params
|
53
|
-
end
|
54
|
-
|
55
|
-
def order_by(params = {})
|
56
|
-
if params[:order_by].present?
|
57
|
-
params[:order_by] = params[:order_by].to_s.underscore
|
58
|
-
return params[:order_by].to_sym if model.attribute_names.include?(params[:order_by])
|
59
|
-
end
|
60
|
-
|
61
|
-
self.class.i_order_by_attr || :id
|
62
|
-
end
|
63
|
-
|
64
|
-
def order(params = {})
|
65
|
-
if params[:order].present?
|
66
|
-
params[:order] = params[:order].to_s.upcase
|
67
|
-
return params[:order] if params[:order].eql?(ASC) || params[:order].eql?(DESC)
|
68
|
-
end
|
69
|
-
|
70
|
-
self.class.i_order_by_direction || ASC
|
71
|
-
end
|
72
|
-
|
73
|
-
private
|
74
|
-
|
75
|
-
def additional_search(filtered_scope, params = {})
|
76
|
-
filtered_scope = apply_order(filtered_scope, params)
|
77
|
-
filtered_scope = apply_includes(filtered_scope)
|
78
|
-
apply_distinct(filtered_scope, params)
|
79
|
-
end
|
80
|
-
|
81
|
-
def apply_includes(filtered_scope)
|
82
|
-
return filtered_scope unless included_params
|
83
|
-
|
84
|
-
filtered_scope.includes(*included_params)
|
85
|
-
end
|
86
|
-
|
87
|
-
def apply_order(filtered_scope, params)
|
88
|
-
return apply_default_order(filtered_scope, params) if params[:order_by].blank? && params[:order].blank?
|
89
|
-
|
90
|
-
filtered_scope.order(order_by(params) => order(params))
|
91
|
-
end
|
92
|
-
|
93
|
-
def apply_default_order(filtered_scope, params)
|
94
|
-
return order_method(filtered_scope, params) if order_method?
|
95
|
-
return order_block(filtered_scope, params) if order_block?
|
96
|
-
|
97
|
-
filtered_scope.order(order_by => order)
|
98
|
-
end
|
99
|
-
|
100
|
-
def order_method(filtered_scope, params)
|
101
|
-
send(self.class.i_order_method, filtered_scope, params)
|
102
|
-
end
|
103
|
-
|
104
|
-
def order_method?
|
105
|
-
self.class.i_order_method.present?
|
106
|
-
end
|
107
|
-
|
108
|
-
def order_block(filtered_scope, params)
|
109
|
-
instance_exec filtered_scope, params, &self.class.i_order_block
|
110
|
-
end
|
111
|
-
|
112
|
-
def order_block?
|
113
|
-
self.class.i_order_block.present?
|
114
|
-
end
|
115
|
-
|
116
|
-
def apply_distinct(filtered_scope, params)
|
117
|
-
return filtered_scope unless distinct? || params[:distinct] == true
|
118
|
-
|
119
|
-
filtered_scope.distinct
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|