snfoil-rails 0.8.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|