jsonapi-materializer 1.0.0.rc.pre.1 → 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.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JSONAPI
2
4
  module Materializer
3
5
  module Resource
@@ -9,29 +11,17 @@ module JSONAPI
9
11
  extend(ActiveSupport::Concern)
10
12
  include(ActiveModel::Model)
11
13
 
12
- MIXIN_HOOK = ->(*) do
14
+ MIXIN_HOOK = lambda do |*|
13
15
  @attributes = {}
14
16
  @relations = {}
15
17
 
16
- unless const_defined?("Collection")
18
+ unless const_defined?(:Collection)
17
19
  self::Collection = Class.new do
18
20
  include(JSONAPI::Materializer::Collection)
19
21
  end
20
22
  end
21
23
 
22
- unless const_defined?("Context")
23
- self::Context = Class.new do
24
- include(JSONAPI::Materializer::Context)
25
-
26
- def initialize(**keyword_arguments)
27
- keyword_arguments.keys.each(&singleton_class.method(:attr_accessor))
28
-
29
- super(**keyword_arguments)
30
- end
31
- end
32
- end
33
-
34
- validates_presence_of(:object)
24
+ validates_presence_of(:object, allow_blank: true)
35
25
 
36
26
  origin(JSONAPI::Materializer.configuration.default_origin)
37
27
  identifier(JSONAPI::Materializer.configuration.default_identifier)
@@ -42,7 +32,6 @@ module JSONAPI
42
32
  attr_accessor(:object)
43
33
  attr_writer(:selects)
44
34
  attr_writer(:includes)
45
- attr_writer(:context)
46
35
  attr_reader(:raw)
47
36
 
48
37
  def initialize(**keyword_arguments)
@@ -50,69 +39,38 @@ module JSONAPI
50
39
 
51
40
  @raw = keyword_arguments
52
41
 
53
- context.validate!
54
42
  validate!
55
43
  end
56
44
 
57
45
  def as_data
58
46
  {
59
- :id => id,
60
- :type => type,
61
- :attributes => exposed(attributes.except(:id)).
62
- transform_values {|attribute| object.public_send(attribute.from)},
63
- :relationships => exposed(relations).
64
- transform_values {|relation| relation.using(self).as_json},
65
- :links => {
66
- :self => links_self
47
+ id:,
48
+ type:,
49
+ attributes: exposed(attributes.except(:id))
50
+ .transform_values { |attribute| object.public_send(attribute.from) },
51
+ relationships: exposed(relations)
52
+ .transform_values { |relation| relation.using(self).as_json },
53
+ links: {
54
+ self: links_self
67
55
  }
68
56
  }.transform_values(&:presence).compact
69
57
  end
70
-
71
- private def exposed(mapping)
72
- if selects.any?
73
- mapping.
74
- select {|_, value| value.visible?(self)}.
75
- slice(*selects.dig(type))
76
- else
77
- mapping.
78
- select {|_, value| value.visible?(self)}
79
- end
80
- end
58
+ # rubocop:enable Metrics/AbcSize
81
59
 
82
60
  def as_json(*)
83
61
  {
84
- :links => {
85
- :self => links_self
62
+ links: {
63
+ self: links_self
86
64
  },
87
- :data => as_data,
88
- :included => included
65
+ data: as_data,
66
+ included:
89
67
  }.transform_values(&:presence).compact
90
68
  end
91
69
 
92
- private def id
93
- object.public_send(identifier).to_s
94
- end
95
-
96
70
  def type
97
71
  self.class.configuration.type.to_s
98
72
  end
99
73
 
100
- private def attributes
101
- self.class.configuration.attributes
102
- end
103
-
104
- private def origin
105
- self.class.configuration.origin
106
- end
107
-
108
- private def identifier
109
- self.class.configuration.identifier
110
- end
111
-
112
- private def relations
113
- self.class.configuration.relations
114
- end
115
-
116
74
  def attribute(name)
117
75
  self.class.attribute(name)
118
76
  end
@@ -128,35 +86,20 @@ module JSONAPI
128
86
  end
129
87
 
130
88
  def selects
131
- (@selects || {}).transform_values {|list| list.map(&:to_sym)}
89
+ (@selects || {}).transform_values { |list| list.map(&:to_sym) }
132
90
  end
133
91
 
134
92
  def includes
135
93
  @includes || []
136
94
  end
137
95
 
138
- def context
139
- self.class.const_get("Context").new(**@context || {})
140
- end
141
-
142
- private def included
143
- @included ||= includes.flat_map do |path|
144
- path.reduce(self) do |subject, key|
145
- if subject.is_a?(Array)
146
- subject.map {|related_subject| related_subject.relation(key).for(subject)}
147
- else
148
- subject.relation(key).for(subject)
149
- end
150
- end
151
- end.map(&:as_data)
152
- end
153
-
154
96
  included do
155
97
  class_eval(&MIXIN_HOOK) unless @abstract_class
156
98
  end
157
99
 
158
100
  class_methods do
159
101
  def inherited(object)
102
+ super
160
103
  object.class_eval(&MIXIN_HOOK) unless object.instance_variable_defined?(:@abstract_class)
161
104
  end
162
105
 
@@ -172,60 +115,97 @@ module JSONAPI
172
115
  @type = value.to_sym
173
116
  end
174
117
 
175
- def has(name, from: name, visible: true)
118
+ def has(name, from: name)
176
119
  @attributes[name] = Attribute.new(
177
- :owner => self,
178
- :name => name,
179
- :from => from,
180
- :visible => visible
120
+ owner: self,
121
+ name:,
122
+ from:
181
123
  )
182
124
  end
183
125
 
184
- def has_one(name, from: name, class_name:, visible: true)
126
+ # rubocop:disable Naming/PredicateName
127
+ def has_one(name, class_name:, from: name)
185
128
  @relations[name] = Relation.new(
186
- :owner => self,
187
- :type => :one,
188
- :name => name,
189
- :from => from,
190
- :class_name => class_name,
191
- :visible => visible
129
+ owner: self,
130
+ type: :one,
131
+ name:,
132
+ from:,
133
+ class_name:
192
134
  )
193
135
  end
136
+ # rubocop:enable Naming/PredicateName
194
137
 
195
- def has_many(name, from: name, class_name:, visible: true)
138
+ # rubocop:disable Naming/PredicateName
139
+ def has_many(name, class_name:, from: name)
196
140
  @relations[name] = Relation.new(
197
- :owner => self,
198
- :type => :many,
199
- :name => name,
200
- :from => from,
201
- :class_name => class_name,
202
- :visible => visible
141
+ owner: self,
142
+ type: :many,
143
+ name:,
144
+ from:,
145
+ class_name:
203
146
  )
204
147
  end
205
-
206
- def context
207
- const_get("Context")
208
- end
148
+ # rubocop:enable Naming/PredicateName
209
149
 
210
150
  def configuration
211
151
  @configuration ||= Configuration.new(
212
- :owner => self,
213
- :type => @type,
214
- :origin => @origin,
215
- :identifier => @identifier,
216
- :attributes => @attributes,
217
- :relations => @relations
152
+ owner: self,
153
+ type: @type,
154
+ origin: @origin,
155
+ identifier: @identifier,
156
+ attributes: @attributes,
157
+ relations: @relations
218
158
  )
219
159
  end
220
160
 
221
161
  def attribute(name)
222
- configuration.attributes.fetch(name.to_sym) {raise(Error::ResourceRelationshipNotFound, :name => name, :materializer => self)}
162
+ configuration.attributes.fetch(name.to_sym) { raise(Error::ResourceAttributeNotFound, name:, materializer: self) }
223
163
  end
224
164
 
225
165
  def relation(name)
226
- configuration.relations.fetch(name.to_sym) {raise(Error::ResourceRelationshipNotFound, :name => name, :materializer => self)}
166
+ configuration.relations.fetch(name.to_sym) { raise(Error::ResourceRelationshipNotFound, name:, materializer: self) }
167
+ end
168
+ end
169
+
170
+ private def exposed(mapping)
171
+ if selects.any?
172
+ mapping.slice(*selects[type])
173
+ else
174
+ mapping
227
175
  end
228
176
  end
177
+
178
+ private def id
179
+ object.public_send(identifier).to_s
180
+ end
181
+
182
+ private def attributes
183
+ self.class.configuration.attributes
184
+ end
185
+
186
+ private def origin
187
+ self.class.configuration.origin
188
+ end
189
+
190
+ private def identifier
191
+ self.class.configuration.identifier
192
+ end
193
+
194
+ private def relations
195
+ self.class.configuration.relations
196
+ end
197
+
198
+ private def included
199
+ @included ||= includes.flat_map do |path|
200
+ path.reduce(self) do |subject, key|
201
+ if subject.is_a?(Array)
202
+ subject.map { |related_subject| related_subject.relation(key).for(subject) }
203
+ else
204
+ subject.relation(key).for(subject)
205
+ end
206
+ end
207
+ end.map(&:as_data)
208
+ end
229
209
  end
230
210
  end
231
211
  end
@@ -1,18 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require("spec_helper")
2
4
 
3
5
  RSpec.describe(JSONAPI::Materializer::Resource) do
4
- let(:resource) {ArticleMaterializer.new(:object => Article.find(1), :context => {:policy => true})}
6
+ let(:resource) { ArticleMaterializer.new(object: Article.find(1)) }
5
7
 
6
8
  before do
7
- Account.create!(:id => 9, :name => "Dan Gebhardt", :twitter => "dgeb")
8
- Account.create!(:id => 2, :name => "DHH", :twitter => "DHH")
9
- Article.create!(:id => 1, :title => "JSON API paints my bikeshed!", :account => Account.find(9))
10
- Comment.create!(:id => 5, :body => "First!", :article => Article.find(1), :account => Account.find(2))
11
- Comment.create!(:id => 12, :body => "I like XML better", :article => Article.find(1), :account => Account.find(9))
9
+ Account.create!(id: 9, name: "Dan Gebhardt", twitter: "dgeb")
10
+ Account.create!(id: 2, name: "DHH", twitter: "DHH")
11
+ Article.create!(id: 1, title: "JSON API paints my bikeshed!", account: Account.find(9))
12
+ Comment.create!(id: 5, body: "First!", article: Article.find(1), account: Account.find(2))
13
+ Comment.create!(id: 12, body: "I like XML better", article: Article.find(1), account: Account.find(9))
12
14
  end
13
15
 
14
16
  describe("#to_json") do
15
- subject {resource.as_json.deep_stringify_keys}
17
+ subject { resource.as_json.deep_stringify_keys }
16
18
 
17
19
  it("returns a JSON:API standards compliant payload") do
18
20
  expect(subject).to(
@@ -55,7 +57,7 @@ RSpec.describe(JSONAPI::Materializer::Resource) do
55
57
  }
56
58
  },
57
59
  "links" => {
58
- "self" => "http://example.com/articles/1"
60
+ "self" => "http://example.com/articles/1"
59
61
  }
60
62
  }
61
63
  )
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JSONAPI
2
4
  module Materializer
3
- VERSION = "1.0.0.rc-1".freeze
5
+ VERSION = "1.0.0"
4
6
  end
5
7
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require("ostruct")
2
4
  require("addressable")
3
5
  require("active_model")
@@ -8,7 +10,7 @@ require("active_support/core_ext/string")
8
10
  require("active_support/core_ext/module")
9
11
 
10
12
  module JSONAPI
11
- MEDIA_TYPE = "application/vnd.api+json".freeze unless const_defined?("MEDIA_TYPE")
13
+ MEDIA_TYPE = "application/vnd.api+json" unless const_defined?(:MEDIA_TYPE)
12
14
 
13
15
  module Materializer
14
16
  require_relative("materializer/version")
@@ -17,12 +19,11 @@ module JSONAPI
17
19
  require_relative("materializer/controller")
18
20
 
19
21
  @configuration ||= Configuration.new(
20
- :default_invalid_accept_exception => JSONAPI::Materializer::Error::InvalidAcceptHeader,
21
- :default_missing_accept_exception => JSONAPI::Materializer::Error::MissingAcceptHeader,
22
- :default_identifier => :id
22
+ default_invalid_accept_exception: JSONAPI::Materializer::Error::InvalidAcceptHeader,
23
+ default_missing_accept_exception: JSONAPI::Materializer::Error::MissingAcceptHeader,
24
+ default_identifier: :id
23
25
  )
24
26
  require_relative("materializer/collection")
25
- require_relative("materializer/context")
26
27
  require_relative("materializer/resource")
27
28
 
28
29
  def self.configuration
@@ -1,4 +1,3 @@
1
- require("spec_helper")
1
+ # frozen_string_literal: true
2
2
 
3
- RSpec.describe(JSONAPI::Materializer) do
4
- end
3
+ require("spec_helper")
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JSONAPI
2
4
  require_relative("jsonapi/materializer")
3
5
  end
metadata CHANGED
@@ -1,157 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi-materializer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc.pre.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kurtis Rainbolt-Greene
8
- autorequire:
9
- bindir: exe
8
+ autorequire:
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-28 00:00:00.000000000 Z
11
+ date: 2023-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activemodel
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 4.0.0
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: '4.2'
23
- - - ">="
24
- - !ruby/object:Gem::Version
25
- version: 5.0.0
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- version: '5.1'
29
- type: :development
30
- prerelease: false
31
- version_requirements: !ruby/object:Gem::Requirement
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: 4.0.0
36
- - - ">="
37
- - !ruby/object:Gem::Version
38
- version: '4.2'
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: 5.0.0
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- version: '5.1'
45
- - !ruby/object:Gem::Dependency
46
- name: activerecord
47
- requirement: !ruby/object:Gem::Requirement
48
- requirements:
49
- - - ">="
50
- - !ruby/object:Gem::Version
51
- version: 4.0.0
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '4.2'
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- version: 5.0.0
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: '5.1'
61
- type: :development
62
- prerelease: false
63
- version_requirements: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: 4.0.0
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- version: '4.2'
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- version: 5.0.0
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: '5.1'
77
- - !ruby/object:Gem::Dependency
78
- name: bundler
79
- requirement: !ruby/object:Gem::Requirement
80
- requirements:
81
- - - "~>"
82
- - !ruby/object:Gem::Version
83
- version: '1.16'
84
- type: :development
85
- prerelease: false
86
- version_requirements: !ruby/object:Gem::Requirement
87
- requirements:
88
- - - "~>"
89
- - !ruby/object:Gem::Version
90
- version: '1.16'
91
- - !ruby/object:Gem::Dependency
92
- name: pry
93
- requirement: !ruby/object:Gem::Requirement
94
- requirements:
95
- - - "~>"
96
- - !ruby/object:Gem::Version
97
- version: '0.11'
98
- type: :development
99
- prerelease: false
100
- version_requirements: !ruby/object:Gem::Requirement
101
- requirements:
102
- - - "~>"
103
- - !ruby/object:Gem::Version
104
- version: '0.11'
105
- - !ruby/object:Gem::Dependency
106
- name: pry-doc
107
- requirement: !ruby/object:Gem::Requirement
108
- requirements:
109
- - - "~>"
110
- - !ruby/object:Gem::Version
111
- version: '0.11'
112
- type: :development
113
- prerelease: false
114
- version_requirements: !ruby/object:Gem::Requirement
115
- requirements:
116
- - - "~>"
117
- - !ruby/object:Gem::Version
118
- version: '0.11'
119
- - !ruby/object:Gem::Dependency
120
- name: rake
121
- requirement: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - "~>"
124
- - !ruby/object:Gem::Version
125
- version: '12.2'
126
- type: :development
127
- prerelease: false
128
- version_requirements: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - "~>"
131
- - !ruby/object:Gem::Version
132
- version: '12.2'
133
- - !ruby/object:Gem::Dependency
134
- name: rspec
135
- requirement: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - "~>"
138
- - !ruby/object:Gem::Version
139
- version: '3.7'
140
- type: :development
141
- prerelease: false
142
- version_requirements: !ruby/object:Gem::Requirement
143
- requirements:
144
- - - "~>"
145
- - !ruby/object:Gem::Version
146
- version: '3.7'
147
- - !ruby/object:Gem::Dependency
148
- name: rubocop
14
+ name: activesupport
149
15
  requirement: !ruby/object:Gem::Requirement
150
16
  requirements:
151
17
  - - ">="
152
18
  - !ruby/object:Gem::Version
153
19
  version: '0'
154
- type: :development
20
+ type: :runtime
155
21
  prerelease: false
156
22
  version_requirements: !ruby/object:Gem::Requirement
157
23
  requirements:
@@ -159,79 +25,33 @@ dependencies:
159
25
  - !ruby/object:Gem::Version
160
26
  version: '0'
161
27
  - !ruby/object:Gem::Dependency
162
- name: sqlite3
163
- requirement: !ruby/object:Gem::Requirement
164
- requirements:
165
- - - "~>"
166
- - !ruby/object:Gem::Version
167
- version: '1.3'
168
- type: :development
169
- prerelease: false
170
- version_requirements: !ruby/object:Gem::Requirement
171
- requirements:
172
- - - "~>"
173
- - !ruby/object:Gem::Version
174
- version: '1.3'
175
- - !ruby/object:Gem::Dependency
176
- name: activesupport
28
+ name: addressable
177
29
  requirement: !ruby/object:Gem::Requirement
178
30
  requirements:
179
31
  - - ">="
180
32
  - !ruby/object:Gem::Version
181
- version: 4.0.0
182
- - - ">="
183
- - !ruby/object:Gem::Version
184
- version: '4.2'
185
- - - ">="
186
- - !ruby/object:Gem::Version
187
- version: 5.0.0
188
- - - ">="
189
- - !ruby/object:Gem::Version
190
- version: '5.1'
33
+ version: '0'
191
34
  type: :runtime
192
35
  prerelease: false
193
36
  version_requirements: !ruby/object:Gem::Requirement
194
37
  requirements:
195
38
  - - ">="
196
39
  - !ruby/object:Gem::Version
197
- version: 4.0.0
198
- - - ">="
199
- - !ruby/object:Gem::Version
200
- version: '4.2'
201
- - - ">="
202
- - !ruby/object:Gem::Version
203
- version: 5.0.0
204
- - - ">="
205
- - !ruby/object:Gem::Version
206
- version: '5.1'
207
- - !ruby/object:Gem::Dependency
208
- name: addressable
209
- requirement: !ruby/object:Gem::Requirement
210
- requirements:
211
- - - "~>"
212
- - !ruby/object:Gem::Version
213
- version: '2.5'
214
- type: :runtime
215
- prerelease: false
216
- version_requirements: !ruby/object:Gem::Requirement
217
- requirements:
218
- - - "~>"
219
- - !ruby/object:Gem::Version
220
- version: '2.5'
40
+ version: '0'
221
41
  - !ruby/object:Gem::Dependency
222
42
  name: kaminari
223
43
  requirement: !ruby/object:Gem::Requirement
224
44
  requirements:
225
- - - "~>"
45
+ - - ">="
226
46
  - !ruby/object:Gem::Version
227
- version: '1.1'
47
+ version: '0'
228
48
  type: :runtime
229
49
  prerelease: false
230
50
  version_requirements: !ruby/object:Gem::Requirement
231
51
  requirements:
232
- - - "~>"
52
+ - - ">="
233
53
  - !ruby/object:Gem::Version
234
- version: '1.1'
54
+ version: '0'
235
55
  description: A way to turn data models into outbound json:api responses
236
56
  email:
237
57
  - kurtis@rainbolt-greene.online
@@ -239,6 +59,7 @@ executables: []
239
59
  extensions: []
240
60
  extra_rdoc_files: []
241
61
  files:
62
+ - LICENSE
242
63
  - README.md
243
64
  - Rakefile
244
65
  - lib/jsonapi-materializer.rb
@@ -246,7 +67,6 @@ files:
246
67
  - lib/jsonapi/materializer/collection.rb
247
68
  - lib/jsonapi/materializer/collection_spec.rb
248
69
  - lib/jsonapi/materializer/configuration.rb
249
- - lib/jsonapi/materializer/context.rb
250
70
  - lib/jsonapi/materializer/controller.rb
251
71
  - lib/jsonapi/materializer/error.rb
252
72
  - lib/jsonapi/materializer/error/invalid_accept_header.rb
@@ -260,30 +80,29 @@ files:
260
80
  - lib/jsonapi/materializer/resource/relationship.rb
261
81
  - lib/jsonapi/materializer/resource_spec.rb
262
82
  - lib/jsonapi/materializer/version.rb
263
- - lib/jsonapi/materializer/version_spec.rb
264
83
  - lib/jsonapi/materializer_spec.rb
265
- homepage: http://krainboltgreene.github.io/jsonapi-materializer
84
+ homepage: http://krainboltgreene.github.io/jsonapi-materializer.rb
266
85
  licenses:
267
- - ISC
268
- metadata: {}
269
- post_install_message:
86
+ - HL3
87
+ metadata:
88
+ rubygems_mfa_required: 'true'
89
+ post_install_message:
270
90
  rdoc_options: []
271
91
  require_paths:
272
92
  - lib
273
93
  required_ruby_version: !ruby/object:Gem::Requirement
274
94
  requirements:
275
- - - ">="
95
+ - - "~>"
276
96
  - !ruby/object:Gem::Version
277
- version: '0'
97
+ version: '3.2'
278
98
  required_rubygems_version: !ruby/object:Gem::Requirement
279
99
  requirements:
280
- - - ">"
100
+ - - ">="
281
101
  - !ruby/object:Gem::Version
282
- version: 1.3.1
102
+ version: '0'
283
103
  requirements: []
284
- rubyforge_project:
285
- rubygems_version: 2.7.7
286
- signing_key:
104
+ rubygems_version: 3.4.10
105
+ signing_key:
287
106
  specification_version: 4
288
107
  summary: A way to turn data models into outbound json:api responses
289
108
  test_files: []