jat 0.0.3 → 0.0.5

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jat/attribute.rb +36 -4
  3. data/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads.rb +7 -3
  4. data/lib/jat/plugins/_activerecord_preloads/lib/preloader.rb +7 -13
  5. data/lib/jat/plugins/_lower_camel_case/_lower_camel_case.rb +32 -0
  6. data/lib/jat/plugins/_preloads/_preloads.rb +8 -2
  7. data/lib/jat/plugins/cache/cache.rb +9 -5
  8. data/lib/jat/plugins/json_api/json_api.rb +145 -105
  9. data/lib/jat/plugins/json_api/lib/fields_param_parser.rb +40 -0
  10. data/lib/jat/plugins/json_api/lib/include_param_parser.rb +84 -0
  11. data/lib/jat/plugins/json_api/lib/map.rb +92 -27
  12. data/lib/jat/plugins/json_api/lib/params/fields/validate.rb +8 -5
  13. data/lib/jat/plugins/json_api/lib/response.rb +84 -196
  14. data/lib/jat/plugins/json_api/lib/response_piece.rb +166 -0
  15. data/lib/jat/plugins/json_api_activerecord/json_api_activerecord.rb +31 -0
  16. data/lib/jat/plugins/{_json_api_activerecord → json_api_activerecord}/lib/preloads.rb +16 -24
  17. data/lib/jat/plugins/json_api_lower_camel_case/json_api_lower_camel_case.rb +30 -0
  18. data/lib/jat/plugins/json_api_maps_cache/json_api_maps_cache.rb +54 -0
  19. data/lib/jat/plugins/json_api_validate_params/json_api_validate_params.rb +57 -0
  20. data/lib/jat/plugins/json_api_validate_params/lib/params_error.rb +6 -0
  21. data/lib/jat/plugins/json_api_validate_params/lib/validate_fields_param.rb +59 -0
  22. data/lib/jat/plugins/json_api_validate_params/lib/validate_include_param.rb +33 -0
  23. data/lib/jat/plugins/simple_api/lib/fields_param_parser.rb +97 -0
  24. data/lib/jat/plugins/simple_api/lib/map.rb +80 -10
  25. data/lib/jat/plugins/simple_api/lib/response.rb +78 -89
  26. data/lib/jat/plugins/simple_api/lib/response_piece.rb +84 -0
  27. data/lib/jat/plugins/simple_api/simple_api.rb +83 -24
  28. data/lib/jat/plugins/simple_api_activerecord/lib/preloads.rb +55 -0
  29. data/lib/jat/plugins/simple_api_activerecord/simple_api_activerecord.rb +31 -0
  30. data/lib/jat/plugins/simple_api_lower_camel_case/simple_api_lower_camel_case.rb +30 -0
  31. data/lib/jat/plugins/simple_api_maps_cache/simple_api_maps_cache.rb +48 -0
  32. data/lib/jat/plugins/simple_api_validate_params/lib/fields_error.rb +6 -0
  33. data/lib/jat/plugins/simple_api_validate_params/lib/validate_fields_param.rb +45 -0
  34. data/lib/jat/plugins/simple_api_validate_params/simple_api_validate_params.rb +45 -0
  35. data/lib/jat/plugins/to_str/to_str.rb +10 -4
  36. data/lib/jat/plugins.rb +3 -16
  37. data/lib/jat.rb +28 -30
  38. data/test/lib/jat/attribute_test.rb +15 -5
  39. data/test/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads_test.rb +34 -15
  40. data/test/lib/jat/plugins/_activerecord_preloads/lib/preloader_test.rb +10 -24
  41. data/test/lib/jat/plugins/_camel_lower/_camel_lower_test.rb +26 -0
  42. data/test/lib/jat/plugins/_preloads/lib/format_user_preloads_test.rb +1 -1
  43. data/test/lib/jat/plugins/_preloads/lib/preloads_with_path_test.rb +1 -1
  44. data/test/lib/jat/plugins/cache/cache_test.rb +11 -11
  45. data/test/lib/jat/plugins/json_api/json_api_test.rb +63 -47
  46. data/test/lib/jat/plugins/json_api/lib/{params/fields_test.rb → fields_param_parser_test.rb} +7 -6
  47. data/test/lib/jat/plugins/json_api/lib/{params/include_test.rb → include_param_parser_test.rb} +4 -4
  48. data/test/lib/jat/plugins/json_api/lib/map_test.rb +150 -79
  49. data/test/lib/jat/plugins/json_api/lib/response_test.rb +32 -32
  50. data/test/lib/jat/plugins/{_json_api_activerecord/_json_api_activerecord_test.rb → json_api_activerecord/json_api_activerecord_test.rb} +14 -5
  51. data/test/lib/jat/plugins/{_json_api_activerecord → json_api_activerecord}/lib/preloads_test.rb +11 -10
  52. data/test/lib/jat/plugins/json_api_camel_lower/json_api_camel_lower_test.rb +79 -0
  53. data/test/lib/jat/plugins/json_api_maps_cache/json_api_maps_cache_test.rb +107 -0
  54. data/test/lib/jat/plugins/json_api_validate_params/json_api_validate_params_test.rb +84 -0
  55. data/test/lib/jat/plugins/simple_api/lib/{params/parse_test.rb → fields_param_parser_test.rb} +10 -4
  56. data/test/lib/jat/plugins/simple_api/lib/map_test.rb +111 -34
  57. data/test/lib/jat/plugins/simple_api/lib/response_test.rb +80 -74
  58. data/test/lib/jat/plugins/simple_api/simple_api_test.rb +91 -25
  59. data/test/lib/jat/plugins/simple_api_activerecord/lib/preloads_test.rb +135 -0
  60. data/test/lib/jat/plugins/simple_api_activerecord/simple_api_activerecord_test.rb +38 -0
  61. data/test/lib/jat/plugins/simple_api_camel_lower/simple_api_camel_lower_test.rb +48 -0
  62. data/test/lib/jat/plugins/simple_api_maps_cache/simple_api_maps_cache_test.rb +95 -0
  63. data/test/lib/jat/plugins/simple_api_validate_params/simple_api_validate_params_test.rb +89 -0
  64. data/test/lib/jat/plugins/to_str/to_str_test.rb +3 -3
  65. data/test/lib/jat_test.rb +47 -24
  66. data/test/lib/plugin_test.rb +3 -3
  67. data/test/test_helper.rb +0 -3
  68. data/test/test_plugin.rb +9 -12
  69. metadata +60 -71
  70. data/CHANGELOG.md +0 -7
  71. data/README.md +0 -21
  72. data/jat.gemspec +0 -37
  73. data/lib/jat/plugins/_json_api_activerecord/_json_api_activerecord.rb +0 -22
  74. data/lib/jat/plugins/camel_lower/camel_lower.rb +0 -18
  75. data/lib/jat/plugins/json_api/lib/construct_traversal_map.rb +0 -91
  76. data/lib/jat/plugins/json_api/lib/presenters/document_links_presenter.rb +0 -48
  77. data/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter.rb +0 -48
  78. data/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter.rb +0 -48
  79. data/lib/jat/plugins/json_api/lib/presenters/links_presenter.rb +0 -48
  80. data/lib/jat/plugins/json_api/lib/presenters/meta_presenter.rb +0 -48
  81. data/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter.rb +0 -53
  82. data/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter.rb +0 -53
  83. data/lib/jat/plugins/json_api/lib/traversal_map.rb +0 -34
  84. data/lib/jat/plugins/simple_api/lib/construct_traversal_map.rb +0 -45
  85. data/lib/jat/plugins/simple_api/lib/params/parse.rb +0 -68
  86. data/lib/jat/presenter.rb +0 -51
  87. data/test/lib/jat/plugins/camel_lower/camel_lower_test.rb +0 -78
  88. data/test/lib/jat/plugins/json_api/lib/construct_traversal_map_test.rb +0 -119
  89. data/test/lib/jat/plugins/json_api/lib/params/fields/parse_test.rb +0 -24
  90. data/test/lib/jat/plugins/json_api/lib/params/fields/validate_test.rb +0 -47
  91. data/test/lib/jat/plugins/json_api/lib/params/include/parse_test.rb +0 -46
  92. data/test/lib/jat/plugins/json_api/lib/params/include/validate_test.rb +0 -51
  93. data/test/lib/jat/plugins/json_api/lib/presenters/document_links_presenter_test.rb +0 -69
  94. data/test/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter_test.rb +0 -69
  95. data/test/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter_test.rb +0 -69
  96. data/test/lib/jat/plugins/json_api/lib/presenters/links_presenter_test.rb +0 -69
  97. data/test/lib/jat/plugins/json_api/lib/presenters/meta_presenter_test.rb +0 -69
  98. data/test/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter_test.rb +0 -75
  99. data/test/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter_test.rb +0 -75
  100. data/test/lib/jat/plugins/json_api/lib/traversal_map_test.rb +0 -58
  101. data/test/lib/jat/plugins/simple_api/lib/construct_traversal_map_test.rb +0 -100
  102. data/test/lib/jat/presenter_test.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3fdf9f1733a9d7ddcdeced1bcf6b6cbb1f53b9ffa11b8cb1592874dcc55c3bf2
4
- data.tar.gz: d8982abf27a244a845ec0147a51e23946a8f6cac66c36d350aef6567253326f8
3
+ metadata.gz: 405a0677976675d336278af6aa940fe83ac4bdd4f9d69263fb4728f5cb1c8b3e
4
+ data.tar.gz: 9f7e0ef9238788984a50b677b68876d7301eae6e020df469ec7eba933566dbf0
5
5
  SHA512:
6
- metadata.gz: f8a9be4d5e0d59922b37763de59a8833b5d3c71ac634f2c3555b6b9ab36e8a4149be04f8b33a68406616cfaeda85f49ed349fe8cc4d47bc44e0a873f0128829a
7
- data.tar.gz: 9dcf9433b3d5f40e538db79e082095b54977f8ba8fd885ada3442441c98f374635956d0cd5201c654282954dd24d59e589a181338d2774855b97bd9677fa40d4
6
+ metadata.gz: dd533f933d3504b8b549ac13f231ee70bfa7a8c00baafe88ab09a8973a6d278d8a727ddbd0e4e783abed34b0e8f22c3ccb314ced10699427de80877865a9ff0d
7
+ data.tar.gz: 323559cf6470e9c569f919356f2c0c0033b46e51ccb0b9c1b79b9e0d5d397d68b1322a2401788560f1ed5a474cbf19a81720f38ed78291e1c75326ec6f9a7a07
data/lib/jat/attribute.rb CHANGED
@@ -59,11 +59,43 @@ class Jat
59
59
  end
60
60
 
61
61
  def block
62
- @block ||=
63
- params.fetch(:block) || begin
64
- key_method_name = key
65
- -> { object.public_send(key_method_name) }
62
+ return @block if instance_variable_defined?(:@block)
63
+
64
+ current_block = params.fetch(:block).tap { |bl| check_block_valid(bl) if bl }
65
+ current_block ||= keyword_block
66
+
67
+ @block = anonymized_block(current_block)
68
+ end
69
+
70
+ def value(object, context)
71
+ block.call(object, context)
72
+ end
73
+
74
+ private
75
+
76
+ def keyword_block
77
+ key_method_name = key
78
+ proc { |object| object.public_send(key_method_name) }
79
+ end
80
+
81
+ def anonymized_block(block)
82
+ Class.new do
83
+ private
84
+
85
+ define_method(:_doe) do |object, context|
86
+ block.call(object, context)
66
87
  end
88
+ end.new.method(:_doe)
89
+ end
90
+
91
+ def check_block_valid(block)
92
+ raise Error, "Block must be a Proc (not lambda)" if block.lambda?
93
+
94
+ params = block.parameters
95
+ raise Error, "Block can have 0-2 parameters" if params.count > 2
96
+
97
+ valid_params_types = params.all? { |param| param[0] == :opt }
98
+ raise Error, "Block parameters must be optional and no keyword parameters" unless valid_params_types
67
99
  end
68
100
  end
69
101
 
@@ -5,10 +5,14 @@ require_relative "./lib/preloader"
5
5
  class Jat
6
6
  module Plugins
7
7
  module ActiverecordPreloads
8
+ def self.load(jat_class, **_opts)
9
+ jat_class.include(InstanceMethods)
10
+ end
11
+
8
12
  module InstanceMethods
9
- def initialize(*)
13
+ def to_h(object)
14
+ object = add_preloads(object)
10
15
  super
11
- @object = add_preloads(@object)
12
16
  end
13
17
 
14
18
  private
@@ -16,7 +20,7 @@ class Jat
16
20
  def add_preloads(obj)
17
21
  return obj if obj.nil? || (obj.is_a?(Array) && obj.empty?)
18
22
 
19
- preloads = self.class.jat_preloads(self)
23
+ preloads = preloads()
20
24
  return obj if preloads.empty?
21
25
 
22
26
  Preloader.preload(obj, preloads)
@@ -27,11 +27,7 @@ class Jat
27
27
  end
28
28
 
29
29
  def preload(object, preloads)
30
- # Reset associations that will be preloaded to fix possible bugs with
31
- # ActiveRecord::Associations::Preloader
32
- preloads.each_key { |key| object.association(key).reset }
33
30
  ActiveRecord::Associations::Preloader.new.preload(object, preloads)
34
-
35
31
  object
36
32
  end
37
33
  end
@@ -46,7 +42,13 @@ class Jat
46
42
  end
47
43
 
48
44
  def preload(objects, preloads)
49
- objects.preload(preloads)
45
+ if objects.loaded?
46
+ array_objects = objects.to_a
47
+ ActiverecordArray.preload(array_objects, preloads)
48
+ objects
49
+ else
50
+ objects.preload(preloads).load
51
+ end
50
52
  end
51
53
  end
52
54
 
@@ -62,20 +64,12 @@ class Jat
62
64
  end
63
65
 
64
66
  def preload(objects, preloads)
65
- # Reset associations that will be preloaded to fix possible bugs with
66
- # ActiveRecord::Associations::Preloader
67
- preloads.each_key { |key| reset_association(objects, key) }
68
67
  ActiveRecord::Associations::Preloader.new.preload(objects, preloads)
69
-
70
68
  objects
71
69
  end
72
70
 
73
71
  private
74
72
 
75
- def reset_association(objects, key)
76
- objects.each { |object| object.association(key).reset }
77
- end
78
-
79
73
  def same_kind?(objects)
80
74
  first_object_class = objects.first.class
81
75
  objects.all? { |object| object.instance_of?(first_object_class) }
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Jat
4
+ module Plugins
5
+ module LowerCamelCase
6
+ def self.load(jat_class, **_opts)
7
+ jat_class::Attribute.include(AttributeInstanceMethods)
8
+ end
9
+
10
+ module AttributeInstanceMethods
11
+ def name
12
+ LowerCamelCaseTransformation.call(original_name)
13
+ end
14
+ end
15
+ end
16
+
17
+ register_plugin(:_lower_camel_case, LowerCamelCase)
18
+ end
19
+
20
+ class LowerCamelCaseTransformation
21
+ SEPARATOR = "_"
22
+
23
+ def self.call(string)
24
+ first_word, *others = string.to_s.split(SEPARATOR)
25
+
26
+ first_word[0] = first_word[0].downcase
27
+ last_words = others.each(&:capitalize!).join
28
+
29
+ :"#{first_word}#{last_words}"
30
+ end
31
+ end
32
+ end
@@ -7,6 +7,10 @@ require_relative "./lib/preloads_with_path"
7
7
  class Jat
8
8
  module Plugins
9
9
  module Preloads
10
+ def self.load(jat_class, **_opts)
11
+ jat_class::Attribute.include(AttributeMethods)
12
+ end
13
+
10
14
  module AttributeMethods
11
15
  NULL_PRELOADS = [nil, [].freeze].freeze
12
16
 
@@ -28,7 +32,7 @@ class Jat
28
32
  # we don't know which entity is main (:user or :profile in this example) but
29
33
  # we need to know main value to add nested preloads to it.
30
34
  # User can specify main preloaded entity by adding "!" suffix
31
- # ({ user!: [:profile] } for example), othervice the latest key will be considered main.
35
+ # ({ user!: [:profile] } for example), otherwise the latest key will be considered main.
32
36
  def get_preloads_with_path
33
37
  preloads_provided = opts.key?(:preload)
34
38
  preloads =
@@ -43,7 +47,9 @@ class Jat
43
47
  return NULL_PRELOADS if preloads_provided && !preloads
44
48
 
45
49
  preloads = FormatUserPreloads.to_hash(preloads)
46
- PreloadsWithPath.call(preloads)
50
+ preloads, path = PreloadsWithPath.call(preloads)
51
+
52
+ [EnumDeepFreeze.call(preloads), path.freeze]
47
53
  end
48
54
  end
49
55
  end
@@ -7,25 +7,29 @@ class Jat
7
7
  jat_class.plugin :to_str, **opts
8
8
  end
9
9
 
10
+ def self.load(jat_class, **_opts)
11
+ jat_class.include(InstanceMethods)
12
+ end
13
+
10
14
  module InstanceMethods
11
15
  FORMAT_TO_STR = :to_str
12
16
  FORMAT_TO_H = :to_h
13
17
 
14
- def to_h
18
+ def to_h(object)
15
19
  return super if context[:_format] == FORMAT_TO_STR
16
20
 
17
21
  context[:_format] = FORMAT_TO_H
18
- cached { super }
22
+ cached(object) { super }
19
23
  end
20
24
 
21
- def to_str
25
+ def to_str(object)
22
26
  context[:_format] = FORMAT_TO_STR
23
- cached { super }
27
+ cached(object) { super }
24
28
  end
25
29
 
26
30
  private
27
31
 
28
- def cached(&block)
32
+ def cached(object, &block)
29
33
  cache = context[:cache]
30
34
  return yield unless cache
31
35
 
@@ -1,125 +1,159 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "./lib/fields_param_parser"
4
+ require_relative "./lib/include_param_parser"
5
+ require_relative "./lib/map"
3
6
  require_relative "./lib/response"
4
- require_relative "./lib/traversal_map"
5
- require_relative "./lib/presenters/document_links_presenter"
6
- require_relative "./lib/presenters/document_meta_presenter"
7
- require_relative "./lib/presenters/jsonapi_presenter"
8
- require_relative "./lib/presenters/links_presenter"
9
- require_relative "./lib/presenters/meta_presenter"
10
- require_relative "./lib/presenters/relationship_links_presenter"
11
- require_relative "./lib/presenters/relationship_meta_presenter"
7
+ require_relative "./lib/response_piece"
12
8
 
13
9
  # Serializes to JSON-API format
14
10
  class Jat
15
11
  module Plugins
16
12
  module JsonApi
17
- def self.after_load(jat_class, **opts)
18
- jat_class.plugin(:_json_api_activerecord, **opts) if opts[:activerecord]
13
+ def self.before_load(jat_class, **_opts)
14
+ response_plugin = jat_class.config[:response_plugin_loaded]
15
+ return unless response_plugin
19
16
 
20
- jat_class.const_set(:JsonapiPresenter, Class.new(Jat::Presenters::JsonapiPresenter))
21
- jat_class::JsonapiPresenter.jat_class = jat_class
17
+ raise Error, "Response plugin `#{response_plugin}` was already loaded before"
18
+ end
22
19
 
23
- jat_class.const_set(:LinksPresenter, Class.new(Jat::Presenters::LinksPresenter))
24
- jat_class::LinksPresenter.jat_class = jat_class
20
+ def self.load(jat_class, **_opts)
21
+ jat_class.include(InstanceMethods)
22
+ jat_class.extend(ClassMethods)
23
+ end
25
24
 
26
- jat_class.const_set(:DocumentLinksPresenter, Class.new(Jat::Presenters::DocumentLinksPresenter))
27
- jat_class::DocumentLinksPresenter.jat_class = jat_class
25
+ def self.after_load(jat_class, **opts)
26
+ fields_parser_class = Class.new(FieldsParamParser)
27
+ fields_parser_class.jat_class = jat_class
28
+ jat_class.const_set(:FieldsParamParser, fields_parser_class)
28
29
 
29
- jat_class.const_set(:RelationshipLinksPresenter, Class.new(Jat::Presenters::RelationshipLinksPresenter))
30
- jat_class::RelationshipLinksPresenter.jat_class = jat_class
30
+ includes_parser_class = Class.new(IncludeParamParser)
31
+ includes_parser_class.jat_class = jat_class
32
+ jat_class.const_set(:IncludeParamParser, includes_parser_class)
31
33
 
32
- jat_class.const_set(:MetaPresenter, Class.new(Jat::Presenters::MetaPresenter))
33
- jat_class::MetaPresenter.jat_class = jat_class
34
+ map_class = Class.new(Map)
35
+ map_class.jat_class = jat_class
36
+ jat_class.const_set(:Map, map_class)
34
37
 
35
- jat_class.const_set(:DocumentMetaPresenter, Class.new(Jat::Presenters::DocumentMetaPresenter))
36
- jat_class::DocumentMetaPresenter.jat_class = jat_class
38
+ response_class = Class.new(Response)
39
+ response_class.jat_class = jat_class
40
+ jat_class.const_set(:Response, response_class)
37
41
 
38
- jat_class.const_set(:RelationshipMetaPresenter, Class.new(Jat::Presenters::RelationshipMetaPresenter))
39
- jat_class::RelationshipMetaPresenter.jat_class = jat_class
42
+ response_piece_class = Class.new(ResponsePiece)
43
+ response_piece_class.jat_class = jat_class
44
+ jat_class.const_set(:ResponsePiece, response_piece_class)
45
+
46
+ jat_class.config[:response_plugin_loaded] = :json_api
47
+ jat_class.plugin(:json_api_activerecord, **opts) if opts[:activerecord]
48
+ jat_class.id
40
49
  end
41
50
 
42
51
  module InstanceMethods
43
- def to_h
44
- Response.new(self).response
52
+ def to_h(object)
53
+ self.class::Response.call(object, context)
45
54
  end
46
55
 
47
- def traversal_map
48
- @traversal_map ||= TraversalMap.new(self)
56
+ def map
57
+ @map ||= self.class.map(context)
49
58
  end
50
59
  end
51
60
 
52
61
  module ClassMethods
53
62
  def inherited(subclass)
63
+ super
64
+
65
+ fields_parser_class = Class.new(self::FieldsParamParser)
66
+ fields_parser_class.jat_class = subclass
67
+ subclass.const_set(:FieldsParamParser, fields_parser_class)
68
+
69
+ includes_parser_class = Class.new(self::IncludeParamParser)
70
+ includes_parser_class.jat_class = subclass
71
+ subclass.const_set(:IncludeParamParser, includes_parser_class)
72
+
73
+ map_class = Class.new(self::Map)
74
+ map_class.jat_class = subclass
75
+ subclass.const_set(:Map, map_class)
76
+
77
+ response_class = Class.new(self::Response)
78
+ response_class.jat_class = subclass
79
+ subclass.const_set(:Response, response_class)
80
+
81
+ response_piece_class = Class.new(self::ResponsePiece)
82
+ response_piece_class.jat_class = subclass
83
+ subclass.const_set(:ResponsePiece, response_piece_class)
84
+
54
85
  subclass.type(@type) if defined?(@type)
86
+ subclass.id(&get_id.params[:block])
55
87
 
56
- # Initialize JsonApi data Presenters
57
- jsonapi_data_presenter_class = Class.new(self::Presenters::JsonapiPresenter)
58
- jsonapi_data_presenter_class.jat_class = subclass
59
- subclass.const_set(:JsonapiPresenter, jsonapi_data_presenter_class)
60
- jsonapi_data.each { |key, block| subclass.jsonapi(key, &block) }
61
-
62
- # Initialize Links Presenters
63
- links_presenter_class = Class.new(self::Presenters::LinksPresenter)
64
- links_presenter_class.jat_class = subclass
65
- subclass.const_set(:LinksPresenter, links_presenter_class)
66
- object_links.each { |key, block| subclass.object_link(key, &block) }
67
-
68
- # Initialize DocumentLinks Presenters
69
- document_links_presenter_class = Class.new(self::Presenters::DocumentLinksPresenter)
70
- document_links_presenter_class.jat_class = subclass
71
- subclass.const_set(:DocumentLinksPresenter, document_links_presenter_class)
72
- document_links.each { |key, block| subclass.document_link(key, &block) }
73
-
74
- # Initialize RelationshipLinks Presenters
75
- relationship_links_presenter_class = Class.new(self::Presenters::RelationshipLinksPresenter)
76
- relationship_links_presenter_class.jat_class = subclass
77
- subclass.const_set(:RelationshipLinksPresenter, relationship_links_presenter_class)
78
- relationship_links.each { |key, block| subclass.relationship_link(key, &block) }
79
-
80
- # Initialize Meta Presenters
81
- meta_presenter_class = Class.new(self::Presenters::MetaPresenter)
82
- meta_presenter_class.jat_class = subclass
83
- subclass.const_set(:MetaPresenter, meta_presenter_class)
84
- added_object_meta.each { |key, block| subclass.object_meta(key, &block) }
85
-
86
- # Initialize DocumentMeta Presenters
87
- document_meta_presenter_class = Class.new(self::Presenters::DocumentMetaPresenter)
88
- document_meta_presenter_class.jat_class = subclass
89
- subclass.const_set(:DocumentMetaPresenter, document_meta_presenter_class)
90
- added_document_meta.each { |key, block| subclass.document_meta(key, &block) }
91
-
92
- # Initialize RelationshipMeta Presenters
93
- relationship_meta_presenter_class = Class.new(self::Presenters::RelationshipMetaPresenter)
94
- relationship_meta_presenter_class.jat_class = subclass
95
- subclass.const_set(:RelationshipMetaPresenter, relationship_meta_presenter_class)
96
- added_relationship_meta.each { |key, block| subclass.relationship_meta(key, &block) }
88
+ # Assign same jsonapi_data
89
+ jsonapi_data.each_value do |attribute|
90
+ params = attribute.params
91
+ subclass.jsonapi(params[:name], **params[:opts], &params[:block])
92
+ end
97
93
 
98
- super
94
+ # Assign same object_links
95
+ object_links.each_value do |attribute|
96
+ params = attribute.params
97
+ subclass.object_link(params[:name], **params[:opts], &params[:block])
98
+ end
99
+
100
+ # Assign same document_links
101
+ document_links.each_value do |attribute|
102
+ params = attribute.params
103
+ subclass.document_link(params[:name], **params[:opts], &params[:block])
104
+ end
105
+
106
+ # Assign same relationship_links
107
+ relationship_links.each_value do |attribute|
108
+ params = attribute.params
109
+ subclass.relationship_link(params[:name], **params[:opts], &params[:block])
110
+ end
111
+
112
+ # Assign same added_object_meta
113
+ added_object_meta.each_value do |attribute|
114
+ params = attribute.params
115
+ subclass.object_meta(params[:name], **params[:opts], &params[:block])
116
+ end
117
+
118
+ # Assign same added_document_meta
119
+ added_document_meta.each_value do |attribute|
120
+ params = attribute.params
121
+ subclass.document_meta(params[:name], **params[:opts], &params[:block])
122
+ end
123
+
124
+ # Assign same added_relationship_meta
125
+ added_relationship_meta.each_value do |attribute|
126
+ params = attribute.params
127
+ subclass.relationship_meta(params[:name], **params[:opts], &params[:block])
128
+ end
99
129
  end
100
130
 
101
- def type(new_type = nil)
102
- return (defined?(@type) && @type) || raise(Error, "#{self} has no defined type") unless new_type
131
+ def get_type
132
+ (defined?(@type) && @type) || raise(Error, "#{self} has no defined type")
133
+ end
134
+
135
+ def type(new_type)
136
+ @type = new_type.to_sym
137
+ end
103
138
 
104
- new_type = new_type.to_sym
105
- @type = new_type
139
+ def get_id
140
+ @id
106
141
  end
107
142
 
108
- def relationship(name, serializer:, **opts, &block)
109
- attribute(name, serializer: serializer, **opts, &block)
143
+ def id(**opts, &block)
144
+ @id = self::Attribute.new(name: :id, opts: opts, block: block)
110
145
  end
111
146
 
112
147
  # JSON API block values
113
148
  #
114
149
  # https://jsonapi.org/format/#document-jsonapi-object
115
- def jsonapi_data(value = nil)
150
+ def jsonapi_data(_value = nil)
116
151
  @jsonapi_data ||= {}
117
152
  end
118
153
 
119
- def jsonapi(key, &block)
120
- jsonapi_data[key.to_sym] = block
121
- self::JsonapiPresenter.add_method(key, block)
122
- block
154
+ def jsonapi(name, **opts, &block)
155
+ new_attr = self::Attribute.new(name: name, opts: opts, block: block)
156
+ jsonapi_data[new_attr.name] = new_attr
123
157
  end
124
158
 
125
159
  # Links related to the resource
@@ -129,10 +163,9 @@ class Jat
129
163
  @object_links ||= {}
130
164
  end
131
165
 
132
- def object_link(key, &block)
133
- object_links[key.to_sym] = block
134
- self::LinksPresenter.add_method(key, block)
135
- block
166
+ def object_link(name, **opts, &block)
167
+ new_attr = self::Attribute.new(name: name, opts: opts, block: block)
168
+ object_links[new_attr.name] = new_attr
136
169
  end
137
170
 
138
171
  # Top-level document links
@@ -142,10 +175,9 @@ class Jat
142
175
  @document_links ||= {}
143
176
  end
144
177
 
145
- def document_link(key, &block)
146
- document_links[key.to_sym] = block
147
- self::DocumentLinksPresenter.add_method(key, block)
148
- block
178
+ def document_link(name, **opts, &block)
179
+ new_attr = self::Attribute.new(name: name, opts: opts, block: block)
180
+ document_links[new_attr.name] = new_attr
149
181
  end
150
182
 
151
183
  # Relationship links
@@ -155,10 +187,9 @@ class Jat
155
187
  @relationship_links ||= {}
156
188
  end
157
189
 
158
- def relationship_link(key, &block)
159
- relationship_links[key.to_sym] = block
160
- self::RelationshipLinksPresenter.add_method(key, block)
161
- block
190
+ def relationship_link(name, **opts, &block)
191
+ new_attr = self::Attribute.new(name: name, opts: opts, block: block)
192
+ relationship_links[new_attr.name] = new_attr
162
193
  end
163
194
 
164
195
  # Object meta
@@ -168,10 +199,9 @@ class Jat
168
199
  @added_object_meta ||= {}
169
200
  end
170
201
 
171
- def object_meta(key, &block)
172
- added_object_meta[key.to_sym] = block
173
- self::MetaPresenter.add_method(key, block)
174
- block
202
+ def object_meta(name, **opts, &block)
203
+ new_attr = self::Attribute.new(name: name, opts: opts, block: block)
204
+ added_object_meta[new_attr.name] = new_attr
175
205
  end
176
206
 
177
207
  # Top-level document meta
@@ -181,10 +211,9 @@ class Jat
181
211
  @added_document_meta ||= {}
182
212
  end
183
213
 
184
- def document_meta(key, &block)
185
- added_document_meta[key.to_sym] = block
186
- self::DocumentMetaPresenter.add_method(key, block)
187
- block
214
+ def document_meta(name, **opts, &block)
215
+ new_attr = self::Attribute.new(name: name, opts: opts, block: block)
216
+ added_document_meta[new_attr.name] = new_attr
188
217
  end
189
218
 
190
219
  # Relationship meta
@@ -194,10 +223,21 @@ class Jat
194
223
  @added_relationship_meta ||= {}
195
224
  end
196
225
 
197
- def relationship_meta(key, &block)
198
- added_relationship_meta[key.to_sym] = block
199
- self::RelationshipMetaPresenter.add_method(key, block)
200
- block
226
+ def relationship_meta(name, **opts, &block)
227
+ new_attr = self::Attribute.new(name: name, opts: opts, block: block)
228
+ added_relationship_meta[new_attr.name] = new_attr
229
+ end
230
+
231
+ def map(context)
232
+ self::Map.call(context)
233
+ end
234
+
235
+ def map_full
236
+ @map_full ||= self::Map.call(exposed: :all)
237
+ end
238
+
239
+ def map_exposed
240
+ @map_exposed ||= self::Map.call(exposed: :default)
201
241
  end
202
242
  end
203
243
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Jat
4
+ module Plugins
5
+ module JsonApi
6
+ class FieldsParamParser
7
+ module ClassMethods
8
+ COMMA = ","
9
+
10
+ # Returns the Jat class that this FieldsParamParser class is namespaced under.
11
+ attr_accessor :jat_class
12
+
13
+ # Since FieldsParamParser is anonymously subclassed when Jat is subclassed,
14
+ # and then assigned to a constant of the Jat subclass, make inspect
15
+ # reflect the likely name for the class.
16
+ def inspect
17
+ "#{jat_class.inspect}::FieldsParamParser"
18
+ end
19
+
20
+ def parse(fields)
21
+ return FROZEN_EMPTY_HASH unless fields
22
+
23
+ parse_to_nested_hash(fields)
24
+ end
25
+
26
+ private
27
+
28
+ def parse_to_nested_hash(fields)
29
+ fields.each_with_object({}) do |(type, attrs_string), obj|
30
+ attrs = attrs_string.split(COMMA).map!(&:to_sym)
31
+ obj[type.to_sym] = attrs
32
+ end
33
+ end
34
+ end
35
+
36
+ extend ClassMethods
37
+ end
38
+ end
39
+ end
40
+ end