jsonapi-realizer 4.4.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -104
  3. data/lib/jsonapi/realizer.rb +26 -25
  4. data/lib/jsonapi/realizer/action.rb +2 -2
  5. data/lib/jsonapi/realizer/adapter.rb +21 -58
  6. data/lib/jsonapi/realizer/adapter/active_record.rb +38 -17
  7. data/lib/jsonapi/realizer/adapter_spec.rb +3 -2
  8. data/lib/jsonapi/realizer/configuration.rb +22 -0
  9. data/lib/jsonapi/realizer/context.rb +8 -0
  10. data/lib/jsonapi/realizer/controller.rb +55 -0
  11. data/lib/jsonapi/realizer/error.rb +10 -9
  12. data/lib/jsonapi/realizer/error/invalid_content_type_header.rb +5 -0
  13. data/lib/jsonapi/realizer/error/invalid_data_type_property.rb +13 -0
  14. data/lib/jsonapi/realizer/error/invalid_root_property.rb +13 -0
  15. data/lib/jsonapi/realizer/error/{duplicate_registration.rb → missing_data_type_property.rb} +1 -1
  16. data/lib/jsonapi/realizer/error/resource_attribute_not_found.rb +14 -0
  17. data/lib/jsonapi/realizer/error/resource_relationship_not_found.rb +14 -0
  18. data/lib/jsonapi/realizer/resource.rb +278 -73
  19. data/lib/jsonapi/realizer/resource/attribute.rb +23 -0
  20. data/lib/jsonapi/realizer/resource/configuration.rb +27 -0
  21. data/lib/jsonapi/realizer/resource/relation.rb +31 -0
  22. data/lib/jsonapi/realizer/resource_spec.rb +55 -8
  23. data/lib/jsonapi/realizer/version.rb +1 -1
  24. data/lib/jsonapi/realizer_spec.rb +22 -119
  25. metadata +70 -20
  26. data/lib/jsonapi/realizer/action/create.rb +0 -36
  27. data/lib/jsonapi/realizer/action/create_spec.rb +0 -165
  28. data/lib/jsonapi/realizer/action/destroy.rb +0 -27
  29. data/lib/jsonapi/realizer/action/destroy_spec.rb +0 -81
  30. data/lib/jsonapi/realizer/action/index.rb +0 -29
  31. data/lib/jsonapi/realizer/action/index_spec.rb +0 -75
  32. data/lib/jsonapi/realizer/action/show.rb +0 -35
  33. data/lib/jsonapi/realizer/action/show_spec.rb +0 -81
  34. data/lib/jsonapi/realizer/action/update.rb +0 -37
  35. data/lib/jsonapi/realizer/action/update_spec.rb +0 -170
  36. data/lib/jsonapi/realizer/action_spec.rb +0 -46
  37. data/lib/jsonapi/realizer/adapter/memory.rb +0 -31
  38. data/lib/jsonapi/realizer/error/invalid_accept_header.rb +0 -9
  39. data/lib/jsonapi/realizer/error/malformed_data_root_property.rb +0 -9
  40. data/lib/jsonapi/realizer/error/missing_accept_header.rb +0 -9
  41. data/lib/jsonapi/realizer/error/missing_type_resource_property.rb +0 -9
@@ -1,81 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe JSONAPI::Realizer::Action::Show 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
@@ -1,37 +0,0 @@
1
- module JSONAPI
2
- module Realizer
3
- class Action
4
- class Update < Action
5
- attr_accessor :resource
6
-
7
- def initialize(payload:, headers:, scope: nil)
8
- raise Error::MissingContentTypeHeader unless headers.key?("Content-Type")
9
- raise Error::InvalidContentTypeHeader unless headers.fetch("Content-Type") == JSONAPI::MEDIA_TYPE
10
-
11
- super(payload: payload, headers: headers, scope: scope)
12
-
13
- @resource = resource_class.new(adapter.find_via_call(relation, id))
14
-
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")}
18
- end
19
-
20
- def call
21
- adapter.assign_attributes_via_call(resource.model, attributes)
22
- adapter.assign_relationships_via_call(resource.model, relationships)
23
- end
24
-
25
- def model
26
- resource.model
27
- end
28
-
29
- private def id
30
- return data.fetch("id", nil) if data
31
-
32
- payload.fetch("id", nil)
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,170 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe JSONAPI::Realizer::Action::Update do
4
- let(:action) { described_class.new(payload: payload, headers: headers) }
5
-
6
- describe "#call" do
7
- subject { action.tap(&:call) }
8
-
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
85
-
86
- context "with a good payload and good headers" do
87
- let(:payload) do
88
- {
89
- "data" => {
90
- "id" => "550e8400-e29b-41d4-a716-446655440000",
91
- "type" => "photos",
92
- "attributes" => {
93
- "title" => "Ember Hamster 2",
94
- "alt-text" => "A hamster logo.",
95
- "src" => "http://example.com/images/productivity-2.png"
96
- },
97
- "relationships" => {
98
- "active-photographer" => {
99
- "data" => { "type" => "photographer-accounts", "id" => "4b8a0af6-953d-4729-8b9a-1fa4eb18f3c9" }
100
- }
101
- }
102
- }
103
- }
104
- end
105
- let(:headers) do
106
- {
107
- "Content-Type" => "application/vnd.api+json",
108
- "Accept" => "application/vnd.api+json"
109
- }
110
- end
111
-
112
- shared_examples "api" do
113
- it "is the right model" do
114
- subject
115
-
116
- expect(action.model).to be_a_kind_of(Photo)
117
- end
118
-
119
- it "assigns the title attribute" do
120
- subject
121
-
122
- expect(action.model).to have_attributes(title: "Ember Hamster 2")
123
- end
124
-
125
- it "assigns the alt_text attribute" do
126
- subject
127
-
128
- expect(action.model).to have_attributes(alt_text: "A hamster logo.")
129
- end
130
-
131
- it "assigns the src attribute" do
132
- subject
133
-
134
- expect(action.model).to have_attributes(src: "http://example.com/images/productivity-2.png")
135
- end
136
-
137
- it "assigns the active_photographer attribute" do
138
- subject
139
-
140
- expect(action.model).to have_attributes(active_photographer: a_kind_of(Account))
141
- end
142
- end
143
-
144
- context "in a memory store", memory: true do
145
- before do
146
- Account::STORE["4b8a0af6-953d-4729-8b9a-1fa4eb18f3c9"] = {
147
- id: "4b8a0af6-953d-4729-8b9a-1fa4eb18f3c9",
148
- name: "Kurtis Rainbolt-Greene"
149
- }
150
- Photo::STORE["550e8400-e29b-41d4-a716-446655440000"] = {
151
- id: "550e8400-e29b-41d4-a716-446655440000",
152
- title: "Ember Hamster",
153
- src: "http://example.com/images/productivity.png"
154
- }
155
- end
156
-
157
- include_examples "api"
158
-
159
- it "updates the record" do
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"
165
- )
166
- end
167
- end
168
- end
169
- end
170
- end
@@ -1,46 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe JSONAPI::Realizer::Action do
4
- let(:headers) do
5
- {
6
- "Accept" => JSONAPI::MEDIA_TYPE
7
- }
8
- end
9
- let(:action) do
10
- ExampleAction.new(payload: payload, headers: headers, type: :photos)
11
- end
12
-
13
- describe "#includes" do
14
- subject { action.includes }
15
-
16
- context "with a two good and one bad" do
17
- let(:payload) do
18
- {
19
- "data" => nil,
20
- "include" => "active_photographer,active_photographer.posts.comments,active_photographer.posts"
21
- }
22
- end
23
-
24
- it "contains only the two good" do
25
- expect(subject).to eq([["active_photographer"], ["active_photographer", "posts"]])
26
- end
27
- end
28
- end
29
-
30
- describe "#fields" do
31
- subject { action.fields }
32
-
33
- context "with a two good and one bad" do
34
- let(:payload) do
35
- {
36
- "data" => nil,
37
- "fields" => "title,active_photographer.posts.comments.body,active_photographer.name"
38
- }
39
- end
40
-
41
- it "contains only the two good" do
42
- expect(subject).to eq([["title"], ["active_photographer", "name"]])
43
- end
44
- end
45
- end
46
- end
@@ -1,31 +0,0 @@
1
- module JSONAPI
2
- module Realizer
3
- class Adapter
4
- MEMORY = Proc.new do
5
- find_many_via do |model_class|
6
- model_class.all
7
- end
8
-
9
- find_via do |model_class, id|
10
- model_class.fetch(id)
11
- end
12
-
13
- assign_attributes_via do |model, attributes|
14
- model.assign_attributes(attributes)
15
- end
16
-
17
- assign_relationships_via do |model, relationships|
18
- model.assign_attributes(relationships)
19
- end
20
-
21
- sparse_fields do |model_class, fields|
22
- model_class
23
- end
24
-
25
- include_via do |model_class, includes|
26
- model_class
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,9 +0,0 @@
1
- module JSONAPI
2
- module Realizer
3
- class Error
4
- class InvalidAcceptHeader < Error
5
-
6
- end
7
- end
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- module JSONAPI
2
- module Realizer
3
- class Error
4
- class MalformedDataRootProperty < Error
5
-
6
- end
7
- end
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- module JSONAPI
2
- module Realizer
3
- class Error
4
- class MissingAcceptHeader < Error
5
-
6
- end
7
- end
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- module JSONAPI
2
- module Realizer
3
- class Error
4
- class MissingTypeResourceProperty < Error
5
-
6
- end
7
- end
8
- end
9
- end