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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. metadata +146 -65
  3. data/CODE_OF_CONDUCT.md +0 -74
  4. data/MIT-LICENSE +0 -20
  5. data/README.md +0 -28
  6. data/Rakefile +0 -29
  7. data/lib/generators/sn_foil/all/all_generator.rb +0 -50
  8. data/lib/generators/sn_foil/context/context_generator.rb +0 -41
  9. data/lib/generators/sn_foil/context/templates/context.erb +0 -9
  10. data/lib/generators/sn_foil/controller/controller_generator.rb +0 -52
  11. data/lib/generators/sn_foil/controller/templates/api_controller.erb +0 -14
  12. data/lib/generators/sn_foil/controller/templates/controller.erb +0 -14
  13. data/lib/generators/sn_foil/jsonapi_deserializer/jsonapi_deserializer_generator.rb +0 -41
  14. data/lib/generators/sn_foil/jsonapi_deserializer/templates/jsonapi_deserializer.erb +0 -12
  15. data/lib/generators/sn_foil/jsonapi_serializer/jsonapi_serializer_generator.rb +0 -41
  16. data/lib/generators/sn_foil/jsonapi_serializer/templates/jsonapi_serializer.erb +0 -20
  17. data/lib/generators/sn_foil/policy/policy_generator.rb +0 -41
  18. data/lib/generators/sn_foil/policy/templates/policy.erb +0 -22
  19. data/lib/generators/sn_foil/searcher/searcher_generator.rb +0 -41
  20. data/lib/generators/sn_foil/searcher/templates/searcher.erb +0 -7
  21. data/lib/sn_foil/configuration/lazy_jsonapi_serializer.rb +0 -87
  22. data/lib/sn_foil/controller/api.rb +0 -90
  23. data/lib/sn_foil/controller/base.rb +0 -19
  24. data/lib/sn_foil/controller/concerns/change_controller_concern.rb +0 -21
  25. data/lib/sn_foil/controller/concerns/create_controller_concern.rb +0 -38
  26. data/lib/sn_foil/controller/concerns/destroy_controller_concern.rb +0 -40
  27. data/lib/sn_foil/controller/concerns/index_controller_concern.rb +0 -67
  28. data/lib/sn_foil/controller/concerns/setup_controller_concern.rb +0 -85
  29. data/lib/sn_foil/controller/concerns/show_controller_concern.rb +0 -36
  30. data/lib/sn_foil/controller/concerns/update_controller_concern.rb +0 -38
  31. data/lib/sn_foil/jsonapi_deserializer.rb +0 -159
  32. data/lib/sn_foil/jsonapi_serializer.rb +0 -16
  33. data/lib/sn_foil/rails/engine.rb +0 -23
  34. data/lib/sn_foil/rails/version.rb +0 -7
  35. data/lib/sn_foil/rails.rb +0 -25
  36. data/lib/sn_foil/searcher.rb +0 -122
  37. 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
@@ -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
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SnFoil
4
- module Rails
5
- VERSION = '0.8.3'
6
- end
7
- 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
@@ -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
data/lib/snfoil-rails.rb DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'sn_foil/rails'
4
- module SnFoil
5
- end