jsonapi-realizer 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 161aa73d85429aefb08d235f632784acb2275bd05516394b77053b224acbfbd0
4
- data.tar.gz: 33731346eaf5fbd9e8bdba67100208762b3848702d9a761c005bd68548384379
3
+ metadata.gz: 233431a77cbb99ea5b1fb51dc5840217f6041eb79e054e23074dbd84fa26517b
4
+ data.tar.gz: 21000506a07d24308f1f22ebb739a3b1e3863d377a1b9ae424fa8b266ff2f44e
5
5
  SHA512:
6
- metadata.gz: d2e2a566ec1566f01174e21acea1a9ebe28b6eeddb2795eb7be29b3598e41e6cfe8c9762d662cb460177a3ea4136cc86855da84ad39227b51703c30e4613e881
7
- data.tar.gz: 65c70a8803f5e66496cb807ae42571b3a3535272a8e8df7c86d087ce27256446f90ab66cc7ef869b14eff8c70c1c7dc963690a1b716dc338b31f368df7e7f1ce
6
+ metadata.gz: c8ab9db2090e5c1208c57c27a63ba5959e33aa5fc27bebfd7d5b3b452d2a16c2e0af23b50e5b5dc8fd12738adfdb39edcab3edb70318db235559cc2850b0b5d0
7
+ data.tar.gz: d2128c6ddfa8318c441b48e8beb27d785239a8737ccdd9cfa6f758b4de7981247e35680e8643dd636c0f8719fbdbd3a8cb48b243031101c89100a05abf21599d
data/README.md CHANGED
@@ -69,15 +69,13 @@ class PhotosController < ApplicationController
69
69
  def index
70
70
  realization = JSONAPI::Realizer.index(params, headers: request.headers, type: :photos)
71
71
 
72
- # See: pundit for `authorize()`
73
- authorize realization.models
74
-
75
- # See: pundit for `policy_scope()`
76
- render json: JSONAPI::Serializer.serialize(policy_scope(record), is_collection: true)
72
+ render json: JSONAPI::Serializer.serialize(realization.models, is_collection: true)
77
73
  end
78
74
  end
79
75
  ```
80
76
 
77
+ Notice that we pass `realization.model` to `ProcessPhotosService`, that's because `jsonapi-realizer` doesn't do the act of saving, creating, or destroying! We just ready up the records for you to handle (including errors).
78
+
81
79
  ### Policies
82
80
 
83
81
  Most times you will want to control what a person sees when they as for your data. We have created interfaces for this use-case and we'll show how you can use pundit (or any PORO) to constrain your in/out.
@@ -130,11 +128,16 @@ end
130
128
  ``` ruby
131
129
  class PhotosController < ApplicationController
132
130
  def index
133
- realization = JSONAPI::Realizer.index(policy(Photo).sanitize(:index, params), headers: request.headers, type: :posts)
131
+ realization = JSONAPI::Realizer.index(
132
+ policy(Photo).sanitize(:index, params),
133
+ headers: request.headers,
134
+ type: :posts,
135
+ relation: policy_scope(Photo)
136
+ )
134
137
 
135
138
  # See: pundit for `policy_scope()`
136
139
  # See: pundit for `authorize()`
137
- render json: JSONAPI::Serializer.serialize(authorize(policy_scope(realization.models)), is_collection: true)
140
+ render json: JSONAPI::Serializer.serialize(authorize(realization.models), is_collection: true)
138
141
  end
139
142
  end
140
143
  ```
@@ -152,8 +155,6 @@ An adapter must provide the following interfaces:
152
155
  0. `find_many_via`, describes how to find many models
153
156
  0. `assign_attributes_via`, describes how to write a set of properties
154
157
  0. `assign_relationships_via`, describes how to write a set of relationships
155
- 0. `create_via`, describes how to create the model
156
- 0. `update_via`, describes how to update the model
157
158
  0. `includes_via`, describes how to eager include related models
158
159
  0. `sparse_fields_via`, describes how to only return certain fields
159
160
 
@@ -173,11 +174,6 @@ class PhotoRealizer
173
174
  model.update_columns(attributes)
174
175
  end
175
176
 
176
- adapter.create_via do |model|
177
- model.save!
178
- Rails.cache.write(model.cache_key, model)
179
- end
180
-
181
177
  has_one :photographer, as: :profiles
182
178
 
183
179
  has :title
@@ -4,14 +4,11 @@ module JSONAPI
4
4
  class Create < Action
5
5
  attr_accessor :resource
6
6
 
7
- def initialize(payload:, headers:)
8
- @payload = payload
9
- @headers = headers
10
-
7
+ def initialize(payload:, headers:, scope: nil)
11
8
  raise Error::MissingContentTypeHeader unless headers.key?("Content-Type")
12
- raise Error::InvalidContentTypeHeader unless headers.fetch("Content-Type") == "application/vnd.api+json"
9
+ raise Error::InvalidContentTypeHeader unless headers.fetch("Content-Type") == JSONAPI::MEDIA_TYPE
13
10
 
14
- super(payload: payload, headers: headers)
11
+ super(payload: payload, headers: headers, scope: scope)
15
12
 
16
13
  @resource = resource_class.new(relation.new)
17
14
 
@@ -24,7 +21,6 @@ module JSONAPI
24
21
  adapter.assign_attributes_via_call(resource.model, {id: id}) if id
25
22
  adapter.assign_attributes_via_call(resource.model, attributes)
26
23
  adapter.assign_relationships_via_call(resource.model, relationships)
27
- adapter.create_via_call(resource.model)
28
24
  end
29
25
 
30
26
  def model
@@ -4,11 +4,84 @@ RSpec.describe JSONAPI::Realizer::Action::Create do
4
4
  let(:action) { described_class.new(payload: payload, headers: headers) }
5
5
 
6
6
  describe "#call" do
7
- subject { action.call }
7
+ subject { action.tap(&:call) }
8
8
 
9
- context "with no top-level data and good headers"
10
- context "with no top-level data and bad headers"
11
- context "with a good payload and bad headers"
9
+ context "with no top-level data and no content-type header no accept headers" do
10
+ let(:payload) do
11
+ {}
12
+ end
13
+ let(:headers) do
14
+ {}
15
+ end
16
+
17
+ it "raises an exception" do
18
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingContentTypeHeader)
19
+ end
20
+ end
21
+
22
+ context "with no top-level data and good content-type header no accept headers" do
23
+ let(:payload) do
24
+ {}
25
+ end
26
+ let(:headers) do
27
+ {
28
+ "Content-Type" => "application/vnd.api+json",
29
+ }
30
+ end
31
+
32
+ it "raises an exception" do
33
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingAcceptHeader)
34
+ end
35
+ end
36
+
37
+ context "with no top-level data and wrong content-type header" do
38
+ let(:payload) do
39
+ {}
40
+ end
41
+ let(:headers) do
42
+ {
43
+ "Content-Type" => "application/json"
44
+ }
45
+ end
46
+
47
+ it "raises an exception" do
48
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidContentTypeHeader)
49
+ end
50
+ end
51
+
52
+ context "with no top-level data and good content-type header and wrong accept header" do
53
+ let(:payload) do
54
+ {}
55
+ end
56
+ let(:headers) do
57
+ {
58
+ "Content-Type" => "application/vnd.api+json",
59
+ "Accept" => "application/json"
60
+ }
61
+ end
62
+
63
+ it "raises an exception" do
64
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidAcceptHeader)
65
+ end
66
+ end
67
+
68
+ context "with wrong top-level data and good headers" do
69
+ let(:payload) do
70
+ {
71
+ "data" => ""
72
+ }
73
+ end
74
+ let(:headers) do
75
+ {
76
+ "Content-Type" => "application/vnd.api+json",
77
+ "Accept" => "application/vnd.api+json"
78
+ }
79
+ end
80
+
81
+ it "raises an exception" do
82
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MalformedDataRootProperty)
83
+ end
84
+ end
12
85
 
13
86
  context "with a good payload and good headers" do
14
87
  let(:payload) do
@@ -44,12 +117,6 @@ RSpec.describe JSONAPI::Realizer::Action::Create do
44
117
  expect(action.model).to be_a_kind_of(Photo)
45
118
  end
46
119
 
47
- it "assigns the id attribute" do
48
- subject
49
-
50
- expect(action.model).to have_attributes(id: "550e8400-e29b-41d4-a716-446655440000")
51
- end
52
-
53
120
  it "assigns the title attribute" do
54
121
  subject
55
122
 
@@ -68,12 +135,6 @@ RSpec.describe JSONAPI::Realizer::Action::Create do
68
135
  expect(action.model).to have_attributes(src: "http://example.com/images/productivity.png")
69
136
  end
70
137
 
71
- it "assigns the updated_at attribute" do
72
- subject
73
-
74
- expect(action.model).to have_attributes(updated_at: a_kind_of(Time))
75
- end
76
-
77
138
  it "assigns the active_photographer attribute" do
78
139
  subject
79
140
 
@@ -92,21 +153,10 @@ RSpec.describe JSONAPI::Realizer::Action::Create do
92
153
  include_examples "api"
93
154
 
94
155
  it "creates the new record" do
95
- expect {
96
- subject
97
- }.to change {
98
- Photo::STORE
99
- }.from(
100
- {}
101
- ).to(
102
- {
103
- "550e8400-e29b-41d4-a716-446655440000" => hash_including(
104
- id: "550e8400-e29b-41d4-a716-446655440000",
105
- title: "Ember Hamster",
106
- alt_text: "A hamster logo.",
107
- src: "http://example.com/images/productivity.png"
108
- )
109
- }
156
+ expect(subject.model).to have_attributes(
157
+ title: "Ember Hamster",
158
+ alt_text: "A hamster logo.",
159
+ src: "http://example.com/images/productivity.png"
110
160
  )
111
161
  end
112
162
  end
@@ -0,0 +1,27 @@
1
+ module JSONAPI
2
+ module Realizer
3
+ class Action
4
+ class Destroy < Action
5
+ attr_accessor :resource
6
+
7
+ def initialize(payload:, headers:, scope: nil, type:)
8
+ @type = type
9
+
10
+ super(payload: payload, headers: headers, scope: scope)
11
+
12
+ @resource = resource_class.new(adapter.find_via_call(relation, id))
13
+ end
14
+
15
+ def model
16
+ resource.model
17
+ end
18
+
19
+ private def id
20
+ return data.fetch("id", nil) if data
21
+
22
+ payload.fetch("id", nil)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe JSONAPI::Realizer::Action::Destroy do
4
+ let(:action) { described_class.new(payload: payload, headers: headers, type: :photos) }
5
+
6
+ describe "#model" do
7
+ subject { action.model }
8
+
9
+ context "with no top-level data and good content-type header no accept headers" do
10
+ let(:payload) do
11
+ {}
12
+ end
13
+ let(:headers) do
14
+ {
15
+ "Content-Type" => "application/vnd.api+json",
16
+ }
17
+ end
18
+
19
+ it "raises an exception" do
20
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingAcceptHeader)
21
+ end
22
+ end
23
+
24
+ context "with no top-level data and good content-type header and wrong accept header" do
25
+ let(:payload) do
26
+ {}
27
+ end
28
+ let(:headers) do
29
+ {
30
+ "Content-Type" => "application/vnd.api+json",
31
+ "Accept" => "application/json"
32
+ }
33
+ end
34
+
35
+ it "raises an exception" do
36
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidAcceptHeader)
37
+ end
38
+ end
39
+
40
+ context "with a good payload and good headers" do
41
+ let(:payload) do
42
+ {
43
+ "id" => "d09ae4c6-0fc3-4c42-8fe8-6029530c3bed"
44
+ }
45
+ end
46
+ let(:headers) do
47
+ {
48
+ "Content-Type" => "application/vnd.api+json",
49
+ "Accept" => "application/vnd.api+json"
50
+ }
51
+ end
52
+
53
+ shared_examples "api" do
54
+ it "returns a photo model" do
55
+ expect(subject).to be_a_kind_of(Photo)
56
+ end
57
+
58
+ it "returns the photos attributes" do
59
+ expect(subject).to have_attributes(title: "Ember Fox", src: "http://example.com/images/productivity-2.png")
60
+ end
61
+ end
62
+
63
+ context "in a memory store", memory: true do
64
+ before do
65
+ Photo::STORE["550e8400-e29b-41d4-a716-446655440000"] = {
66
+ id: "550e8400-e29b-41d4-a716-446655440000",
67
+ title: "Ember Hamster",
68
+ src: "http://example.com/images/productivity.png"
69
+ }
70
+ Photo::STORE["d09ae4c6-0fc3-4c42-8fe8-6029530c3bed"] = {
71
+ id: "d09ae4c6-0fc3-4c42-8fe8-6029530c3bed",
72
+ title: "Ember Fox",
73
+ src: "http://example.com/images/productivity-2.png"
74
+ }
75
+ end
76
+
77
+ include_examples "api"
78
+ end
79
+ end
80
+ end
81
+ end
@@ -4,12 +4,10 @@ module JSONAPI
4
4
  class Index < Action
5
5
  attr_accessor :resources
6
6
 
7
- def initialize(payload:, headers:, type:)
8
- @payload = payload
9
- @headers = headers
7
+ def initialize(payload:, headers:, scope: nil, type:)
10
8
  @type = type
11
9
 
12
- super(payload: payload, headers: headers)
10
+ super(payload: payload, headers: headers, scope: scope)
13
11
 
14
12
  @resources = adapter.find_many_via_call(relation).map(&resource_class.method(:new))
15
13
  end
@@ -6,9 +6,36 @@ RSpec.describe JSONAPI::Realizer::Action::Index do
6
6
  describe "#models" do
7
7
  subject { action.models }
8
8
 
9
- context "with no top-level data and good headers"
10
- context "with no top-level data and bad headers"
11
- context "with a good payload and bad headers"
9
+ context "with no top-level data and good content-type header no accept headers" do
10
+ let(:payload) do
11
+ {}
12
+ end
13
+ let(:headers) do
14
+ {
15
+ "Content-Type" => "application/vnd.api+json",
16
+ }
17
+ end
18
+
19
+ it "raises an exception" do
20
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingAcceptHeader)
21
+ end
22
+ end
23
+
24
+ context "with no top-level data and good content-type header and wrong accept header" do
25
+ let(:payload) do
26
+ {}
27
+ end
28
+ let(:headers) do
29
+ {
30
+ "Content-Type" => "application/vnd.api+json",
31
+ "Accept" => "application/json"
32
+ }
33
+ end
34
+
35
+ it "raises an exception" do
36
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidAcceptHeader)
37
+ end
38
+ end
12
39
 
13
40
  context "with a good payload and good headers" do
14
41
  let(:payload) do
@@ -2,15 +2,12 @@ module JSONAPI
2
2
  module Realizer
3
3
  class Action
4
4
  class Show < Action
5
-
6
5
  attr_accessor :resource
7
6
 
8
- def initialize(payload:, headers:, type:)
9
- @payload = payload
10
- @headers = headers
7
+ def initialize(payload:, headers:, scope: nil, type:)
11
8
  @type = type
12
9
 
13
- super(payload: payload, headers: headers)
10
+ super(payload: payload, headers: headers, scope: scope)
14
11
 
15
12
  @resource = resource_class.new(adapter.find_via_call(relation, id))
16
13
  end
@@ -6,9 +6,36 @@ RSpec.describe JSONAPI::Realizer::Action::Show do
6
6
  describe "#model" do
7
7
  subject { action.model }
8
8
 
9
- context "with no top-level data and good headers"
10
- context "with no top-level data and bad headers"
11
- context "with a good payload and bad headers"
9
+ context "with no top-level data and good content-type header no accept headers" do
10
+ let(:payload) do
11
+ {}
12
+ end
13
+ let(:headers) do
14
+ {
15
+ "Content-Type" => "application/vnd.api+json",
16
+ }
17
+ end
18
+
19
+ it "raises an exception" do
20
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::MissingAcceptHeader)
21
+ end
22
+ end
23
+
24
+ context "with no top-level data and good content-type header and wrong accept header" do
25
+ let(:payload) do
26
+ {}
27
+ end
28
+ let(:headers) do
29
+ {
30
+ "Content-Type" => "application/vnd.api+json",
31
+ "Accept" => "application/json"
32
+ }
33
+ end
34
+
35
+ it "raises an exception" do
36
+ expect {subject}.to raise_exception(JSONAPI::Realizer::Error::InvalidAcceptHeader)
37
+ end
38
+ end
12
39
 
13
40
  context "with a good payload and good headers" do
14
41
  let(:payload) do
@@ -4,26 +4,22 @@ module JSONAPI
4
4
  class Update < Action
5
5
  attr_accessor :resource
6
6
 
7
- def initialize(payload:, headers:)
8
- @payload = payload
9
- @headers = headers
10
-
7
+ def initialize(payload:, headers:, scope: nil)
11
8
  raise Error::MissingContentTypeHeader unless headers.key?("Content-Type")
12
- raise Error::InvalidContentTypeHeader unless headers.fetch("Content-Type") == "application/vnd.api+json"
9
+ raise Error::InvalidContentTypeHeader unless headers.fetch("Content-Type") == JSONAPI::MEDIA_TYPE
13
10
 
14
- super(payload: payload, headers: headers)
11
+ super(payload: payload, headers: headers, scope: scope)
15
12
 
16
13
  @resource = resource_class.new(adapter.find_via_call(relation, id))
17
14
 
18
- raise Error::MissingRootProperty unless payload.key?("data") || payload.key?("errors") || payload.key?("meta")
19
- raise Error::MissingTypeResourceProperty if payload.key?("data") && data.kind_of?(Hash) && !data.key?("type")
20
- raise Error::MissingTypeResourceProperty if payload.key?("data") && data.kind_of?(Array) && !data.all? {|resource| resource.key?("type")}
15
+ raise Error::MissingRootProperty unless @payload.key?("data") || @payload.key?("errors") || @payload.key?("meta")
16
+ raise Error::MissingTypeResourceProperty if @payload.key?("data") && data.kind_of?(Hash) && !data.key?("type")
17
+ raise Error::MissingTypeResourceProperty if @payload.key?("data") && data.kind_of?(Array) && !data.all? {|resource| resource.key?("type")}
21
18
  end
22
19
 
23
20
  def call
24
21
  adapter.assign_attributes_via_call(resource.model, attributes)
25
22
  adapter.assign_relationships_via_call(resource.model, relationships)
26
- adapter.update_via_call(resource.model)
27
23
  end
28
24
 
29
25
  def model
@@ -4,7 +4,7 @@ RSpec.describe JSONAPI::Realizer::Action::Update do
4
4
  let(:action) { described_class.new(payload: payload, headers: headers) }
5
5
 
6
6
  describe "#call" do
7
- subject { action.call }
7
+ subject { action.tap(&:call) }
8
8
 
9
9
  context "with no top-level data and no content-type header no accept headers" do
10
10
  let(:payload) do
@@ -134,12 +134,6 @@ RSpec.describe JSONAPI::Realizer::Action::Update do
134
134
  expect(action.model).to have_attributes(src: "http://example.com/images/productivity-2.png")
135
135
  end
136
136
 
137
- it "assigns the updated_at attribute" do
138
- subject
139
-
140
- expect(action.model).to have_attributes(updated_at: a_kind_of(Time))
141
- end
142
-
143
137
  it "assigns the active_photographer attribute" do
144
138
  subject
145
139
 
@@ -163,27 +157,11 @@ RSpec.describe JSONAPI::Realizer::Action::Update do
163
157
  include_examples "api"
164
158
 
165
159
  it "updates the record" do
166
- expect {
167
- subject
168
- }.to change {
169
- Photo::STORE
170
- }.from(
171
- {
172
- "550e8400-e29b-41d4-a716-446655440000" => hash_including(
173
- id: "550e8400-e29b-41d4-a716-446655440000",
174
- title: "Ember Hamster",
175
- src: "http://example.com/images/productivity.png"
176
- )
177
- }
178
- ).to(
179
- {
180
- "550e8400-e29b-41d4-a716-446655440000" => hash_including(
181
- id: "550e8400-e29b-41d4-a716-446655440000",
182
- title: "Ember Hamster 2",
183
- alt_text: "A hamster logo.",
184
- src: "http://example.com/images/productivity-2.png"
185
- )
186
- }
160
+ expect(subject.model).to have_attributes(
161
+ id: "550e8400-e29b-41d4-a716-446655440000",
162
+ title: "Ember Hamster 2",
163
+ alt_text: "A hamster logo.",
164
+ src: "http://example.com/images/productivity-2.png"
187
165
  )
188
166
  end
189
167
  end
@@ -5,62 +5,66 @@ module JSONAPI
5
5
  require_relative "action/update"
6
6
  require_relative "action/show"
7
7
  require_relative "action/index"
8
+ require_relative "action/destroy"
8
9
 
9
10
  attr_reader :payload
10
11
  attr_reader :headers
11
12
 
12
- def initialize(payload:, headers:)
13
- raise Error::MissingAcceptHeader unless headers.key?("Accept")
14
- raise Error::InvalidAcceptHeader unless headers.fetch("Accept") == "application/vnd.api+json"
15
- raise Error::TooManyRootProperties if payload.key?("data") && payload.key?("errors")
16
- raise Error::IncludeWithoutDataProperty if payload.key?("include") && !payload.key?("data")
17
- raise Error::MalformedDataRootProperty unless payload.key?("data") && data.kind_of?(Array) || data.kind_of?(Hash) || data.nil?
13
+ def initialize(payload:, headers:, scope: nil)
14
+ @scope = scope
15
+ @headers = headers
16
+ @payload = payload
17
+
18
+ raise Error::MissingAcceptHeader unless @headers.key?("Accept")
19
+ raise Error::InvalidAcceptHeader unless @headers.fetch("Accept") == JSONAPI::MEDIA_TYPE
20
+ raise Error::IncludeWithoutDataProperty if @payload.key?("include") && !@payload.key?("data")
21
+ raise Error::MalformedDataRootProperty if @payload.key?("data") && !(data.kind_of?(Array) || data.kind_of?(Hash) || data.nil?)
18
22
  end
19
23
 
20
24
  def call; end
21
25
 
22
26
  private def model_class
23
- resource_class.model_class
27
+ resource_class.model_class if resource_class
24
28
  end
25
29
 
26
30
  private def resource_class
27
- configuration.resource_class
31
+ configuration.resource_class if configuration
28
32
  end
29
33
 
30
34
  private def adapter
31
- configuration.adapter
35
+ configuration.adapter if configuration
32
36
  end
33
37
 
34
- private def relation_after_inclusion(relation)
38
+ private def relation_after_inclusion(subrelation)
35
39
  if includes.any?
36
- resource_class.include_via_call(relation, includes)
40
+ resource_class.include_via_call(subrelation, includes)
37
41
  else
38
- relation
42
+ subrelation
39
43
  end
40
44
  end
41
45
 
42
- private def relation_after_fields(relation)
46
+ private def relation_after_fields(subrelation)
43
47
  if fields.any?
44
- resource_class.sparse_fields_call(relation, fields)
48
+ resource_class.sparse_fields_call(subrelation, fields)
45
49
  else
46
- relation
50
+ subrelation
47
51
  end
48
52
  end
49
53
 
50
54
  private def relation
51
55
  relation_after_fields(
52
56
  relation_after_inclusion(
53
- model_class
57
+ @scope || model_class
54
58
  )
55
59
  )
56
60
  end
57
61
 
58
62
  private def data
59
- payload.fetch("data")
63
+ payload.fetch("data", nil)
60
64
  end
61
65
 
62
66
  private def type
63
- data["type"].to_s.dasherize if data
67
+ (@type || data["type"]).to_s.dasherize if @type || data
64
68
  end
65
69
 
66
70
  private def attributes
@@ -88,6 +92,7 @@ module JSONAPI
88
92
  end
89
93
 
90
94
  def includes
95
+ return [] unless payload.present?
91
96
  return [] unless payload.key?("include")
92
97
 
93
98
  payload.
@@ -111,6 +116,7 @@ module JSONAPI
111
116
  end
112
117
 
113
118
  def fields
119
+ return [] unless payload.present?
114
120
  return [] unless payload.key?("fields")
115
121
 
116
122
  payload.
@@ -138,7 +144,7 @@ module JSONAPI
138
144
  end
139
145
 
140
146
  private def configuration
141
- JSONAPI::Realizer.type_mapping.fetch(type)
147
+ JSONAPI::Realizer.type_mapping.fetch(type) if type
142
148
  end
143
149
  end
144
150
  end
@@ -1,13 +1,13 @@
1
1
  require "spec_helper"
2
2
 
3
3
  RSpec.describe JSONAPI::Realizer::Action do
4
+ let(:headers) do
5
+ {
6
+ "Accept" => JSONAPI::MEDIA_TYPE
7
+ }
8
+ end
4
9
  let(:action) do
5
- Class.new(described_class) do
6
- def initialize(payload:, type:)
7
- @payload = payload
8
- @type = type
9
- end
10
- end.new(payload: payload, type: :photos)
10
+ ExampleAction.new(payload: payload, headers: headers, type: :photos)
11
11
  end
12
12
 
13
13
  describe "#includes" do
@@ -16,6 +16,7 @@ RSpec.describe JSONAPI::Realizer::Action do
16
16
  context "with a two good and one bad" do
17
17
  let(:payload) do
18
18
  {
19
+ "data" => nil,
19
20
  "include" => "active_photographer,active_photographer.posts.comments,active_photographer.posts"
20
21
  }
21
22
  end
@@ -32,6 +33,7 @@ RSpec.describe JSONAPI::Realizer::Action do
32
33
  context "with a two good and one bad" do
33
34
  let(:payload) do
34
35
  {
36
+ "data" => nil,
35
37
  "fields" => "title,active_photographer.posts.comments.body,active_photographer.name"
36
38
  }
37
39
  end
@@ -31,14 +31,6 @@ module JSONAPI
31
31
  end
32
32
  end)))
33
33
  end
34
-
35
- create_via do |model|
36
- model.create!
37
- end
38
-
39
- update_via do |model|
40
- model.update!
41
- end
42
34
  end
43
35
  end
44
36
  end
@@ -25,21 +25,6 @@ module JSONAPI
25
25
  include_via do |model_class, includes|
26
26
  model_class
27
27
  end
28
-
29
- create_via do |model|
30
- model.assign_attributes(id: model.id || SecureRandom.uuid)
31
- model.assign_attributes(updated_at: Time.now)
32
- model.class.const_get("STORE")[model.id] = model.class.const_get("ATTRIBUTES").inject({}) do |hash, key|
33
- hash.merge({ key => model.public_send(key) })
34
- end
35
- end
36
-
37
- update_via do |model|
38
- model.assign_attributes(updated_at: Time.now)
39
- model.class.const_get("STORE")[model.id] = model.class.const_get("ATTRIBUTES").inject({}) do |hash, key|
40
- hash.merge({ key => model.public_send(key) })
41
- end
42
- end
43
28
  end
44
29
  end
45
30
  end
@@ -20,8 +20,6 @@ module JSONAPI
20
20
  raise ArgumentError, "need to provide a Adapter.find_many_via_call interface" unless instance_variable_defined?(:@find_many_via_call)
21
21
  raise ArgumentError, "need to provide a Adapter.assign_attributes_via interface" unless instance_variable_defined?(:@assign_attributes_via_call)
22
22
  raise ArgumentError, "need to provide a Adapter.assign_relationships_via interface" unless instance_variable_defined?(:@assign_relationships_via_call)
23
- raise ArgumentError, "need to provide a Adapter.create_via interface" unless instance_variable_defined?(:@create_via_call)
24
- raise ArgumentError, "need to provide a Adapter.update_via interface" unless instance_variable_defined?(:@update_via_call)
25
23
  raise ArgumentError, "need to provide a Adapter.sparse_fields interface" unless instance_variable_defined?(:@sparse_fields_call)
26
24
  raise ArgumentError, "need to provide a Adapter.include_via interface" unless instance_variable_defined?(:@include_via_call)
27
25
  end
@@ -34,14 +32,6 @@ module JSONAPI
34
32
  @find_many_via_call = callback
35
33
  end
36
34
 
37
- def create_via(&callback)
38
- @create_via_call = callback
39
- end
40
-
41
- def update_via(&callback)
42
- @update_via_call = callback
43
- end
44
-
45
35
  def assign_attributes_via(&callback)
46
36
  @assign_attributes_via_call = callback
47
37
  end
@@ -66,14 +56,6 @@ module JSONAPI
66
56
  @find_many_via_call.call(model_class)
67
57
  end
68
58
 
69
- def create_via_call(model)
70
- @create_via_call.call(model)
71
- end
72
-
73
- def update_via_call(model)
74
- @update_via_call.call(model)
75
- end
76
-
77
59
  def assign_attributes_via_call(model, attributes)
78
60
  @assign_attributes_via_call.call(model, attributes)
79
61
  end
@@ -26,13 +26,5 @@ RSpec.describe JSONAPI::Realizer::Adapter do
26
26
  context "when the assign_attributes_via interface isn't defined" do
27
27
 
28
28
  end
29
-
30
- context "when the create_via interface isn't defined" do
31
-
32
- end
33
-
34
- context "when the update_via interface isn't defined" do
35
-
36
- end
37
29
  end
38
30
  end
@@ -9,7 +9,6 @@ module JSONAPI
9
9
  require_relative "error/missing_content_type_header"
10
10
  require_relative "error/missing_root_property"
11
11
  require_relative "error/missing_type_resource_property"
12
- require_relative "error/too_many_root_properties"
13
12
  end
14
13
  end
15
14
  end
@@ -1,5 +1,5 @@
1
1
  module JSONAPI
2
2
  module Realizer
3
- VERSION = "3.0.0"
3
+ VERSION = "4.0.0"
4
4
  end
5
5
  end
@@ -4,6 +4,8 @@ require "active_support/core_ext/enumerable"
4
4
  require "active_support/core_ext/string"
5
5
 
6
6
  module JSONAPI
7
+ MEDIA_TYPE = "application/vnd.api+json"
8
+
7
9
  module Realizer
8
10
  require_relative "realizer/version"
9
11
  require_relative "realizer/error"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi-realizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kurtis Rainbolt-Greene
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-03-24 00:00:00.000000000 Z
11
+ date: 2018-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -136,6 +136,8 @@ files:
136
136
  - lib/jsonapi/realizer/action.rb
137
137
  - lib/jsonapi/realizer/action/create.rb
138
138
  - lib/jsonapi/realizer/action/create_spec.rb
139
+ - lib/jsonapi/realizer/action/destroy.rb
140
+ - lib/jsonapi/realizer/action/destroy_spec.rb
139
141
  - lib/jsonapi/realizer/action/index.rb
140
142
  - lib/jsonapi/realizer/action/index_spec.rb
141
143
  - lib/jsonapi/realizer/action/show.rb
@@ -156,7 +158,6 @@ files:
156
158
  - lib/jsonapi/realizer/error/missing_content_type_header.rb
157
159
  - lib/jsonapi/realizer/error/missing_root_property.rb
158
160
  - lib/jsonapi/realizer/error/missing_type_resource_property.rb
159
- - lib/jsonapi/realizer/error/too_many_root_properties.rb
160
161
  - lib/jsonapi/realizer/resource.rb
161
162
  - lib/jsonapi/realizer/version.rb
162
163
  - lib/jsonapi/realizer/version_spec.rb
@@ -181,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
182
  version: '0'
182
183
  requirements: []
183
184
  rubyforge_project:
184
- rubygems_version: 2.7.4
185
+ rubygems_version: 2.7.6
185
186
  signing_key:
186
187
  specification_version: 4
187
188
  summary: A way to take json:api requests and turn them into models
@@ -1,9 +0,0 @@
1
- module JSONAPI
2
- module Realizer
3
- class Error
4
- class TooManyRootProperties < Error
5
-
6
- end
7
- end
8
- end
9
- end