jat 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/jat.rb +186 -0
  3. metadata +45 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0c17f2cb00d5dc319df32abc1b0fd41d00adb30f0f8357faf6d74b7d440ef1d9
4
+ data.tar.gz: 0d638bef47aa94698fa25a5c2dc0f6559e528ef8b5bf525bec07310307dbcda3
5
+ SHA512:
6
+ metadata.gz: 369741fcd71f789f49fe0e555db75982fd7758959c59833b1b3d4dd8c55d424cd159f825a9ee6a7d17d5da3c821d44c7052b3ec49910bcf5ab569114916ed6b4
7
+ data.tar.gz: 25a6235d5ec37e44917f64e0d40a98032bb391120832c0357741b56f98571d5941323b548c501bb4a1c761caf62f6cc0a65a09cb8b05f1376d20ba093799688c
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jat/attributes'
4
+ require 'jat/config'
5
+ require 'jat/error'
6
+ require 'jat/map'
7
+ require 'jat/map/construct'
8
+ require 'jat/opts'
9
+ require 'jat/preloads'
10
+ require 'jat/preload_handler'
11
+ require 'jat/response'
12
+ require 'jat/utils/preloads_to_hash'
13
+
14
+ # Main namespace
15
+ class Jat
16
+ module ClassMethods
17
+ def inherited(subclass)
18
+ subclass.extend DSLClassMethods
19
+ subclass.include DSLInstanceMethods
20
+ copy_to(subclass)
21
+
22
+ super
23
+ end
24
+
25
+ def config
26
+ @config ||= Config.new(self)
27
+ end
28
+
29
+ def config=(config)
30
+ @config = config
31
+ end
32
+
33
+ def attributes
34
+ @attributes ||= Attributes.new
35
+ end
36
+
37
+ # Used to validate provided params (fields, include)
38
+ def full_map
39
+ @full_map ||= Map::Construct.new(self, :all).to_h
40
+ end
41
+
42
+ def exposed_map
43
+ @exposed_map ||= Map::Construct.new(self, :exposed).to_h
44
+ end
45
+
46
+ def clear
47
+ @full_map = nil
48
+ @exposed_map = nil
49
+ end
50
+
51
+ def refresh
52
+ attributes.refresh
53
+ clear
54
+ end
55
+
56
+ def copy_to(subclass)
57
+ subclass.type(@type) if defined?(@type)
58
+ config.copy_to(subclass)
59
+ attributes.copy_to(subclass)
60
+ end
61
+ end
62
+
63
+ module DSLClassMethods
64
+ def call
65
+ self
66
+ end
67
+
68
+ def to_h(object, context = {})
69
+ new.to_h(object, context)
70
+ end
71
+
72
+ def to_str(object, context = {})
73
+ new.to_str(object, context)
74
+ end
75
+
76
+ def type(new_type = nil)
77
+ return @type || raise(Error, "#{self} has no defined type") unless new_type
78
+
79
+ new_type = new_type.to_sym
80
+ define_method(:type) { new_type }
81
+ @type = new_type
82
+ end
83
+
84
+ def id(key: nil, &block)
85
+ raise Error, "Key and block can't be provided together" if key && block
86
+ raise Error, 'Key or block must be provided' if !key && !block
87
+
88
+ block ||= proc { |obj| obj.public_send(key) }
89
+ define_method(:id, &block)
90
+ end
91
+
92
+ def attribute(name, **opts, &block)
93
+ add_attribute(name: name, opts: opts, block: block)
94
+ end
95
+
96
+ def relationship(name, serializer:, **opts, &block)
97
+ opts[:serializer] = serializer
98
+ add_attribute(name: name, opts: opts, block: block)
99
+ end
100
+
101
+ private
102
+
103
+ def add_attribute(params)
104
+ opts = Opts.new(self, params)
105
+
106
+ Attribute.new(opts).tap do |attribute|
107
+ attributes << attribute
108
+ add_method(attribute)
109
+ clear
110
+ end
111
+ end
112
+
113
+ def add_method(attribute)
114
+ block = attribute.block
115
+ return unless block
116
+
117
+ name = attribute.original_name
118
+ # Warning-free method redefinition
119
+ remove_method(name) if method_defined?(name)
120
+ define_method(name, &block)
121
+ end
122
+ end
123
+
124
+ # :reek:ModuleInitialize
125
+ module DSLInstanceMethods
126
+ attr_reader :_context
127
+
128
+ def initialize(context = {}, full_map = nil)
129
+ @_context = context.dup
130
+ @_full_map = full_map
131
+ end
132
+
133
+ def to_h(object, context = {})
134
+ _reinitialize(context)
135
+
136
+ Response.new(self, object).to_h
137
+ end
138
+
139
+ def to_str(object, context = {})
140
+ _reinitialize(context)
141
+ Response.new(self, object).to_str
142
+ end
143
+
144
+ def id(object)
145
+ object.id
146
+ end
147
+
148
+ def _preloads
149
+ Preloads.new(_full_map).for(self.class)
150
+ end
151
+
152
+ def _copy_to(nested_serializer)
153
+ nested_serializer.().new(_context, _full_map)
154
+ end
155
+
156
+ def _full_map
157
+ @_full_map ||= begin
158
+ params = _context[:params]
159
+ fields = params && (params[:fields] || params['fields'])
160
+ includes = params && (params[:include] || params['include'])
161
+ Map.(self.class, fields, includes)
162
+ end
163
+ end
164
+
165
+ def _map
166
+ @_map ||= _full_map.fetch(type)
167
+ end
168
+
169
+ private
170
+
171
+ def _reinitialize(context)
172
+ new_params = context[:params]
173
+ old_params = _context[:params]
174
+
175
+ # maps depend on params, so we should clear them when params changed
176
+ if new_params != old_params
177
+ @_full_map = nil
178
+ @_map = nil
179
+ end
180
+
181
+ @_context = _context.merge!(context)
182
+ end
183
+ end
184
+
185
+ extend ClassMethods
186
+ end
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - aglushkov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-07 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: 'Serialization tool to build JSON API response
14
+
15
+ '
16
+ email: aglushkov@shakuro.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/jat.rb
22
+ homepage: https://github.com/aglushkov/jat
23
+ licenses:
24
+ - MIT
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubygems_version: 3.0.3
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: JSON API Serializer
45
+ test_files: []