jat 0.0.3 → 0.0.5

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