ruby_json_api_client 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +25 -0
- data/Rakefile +2 -0
- data/lib/ruby_json_api_client/adapters/ams_adapter.rb +15 -0
- data/lib/ruby_json_api_client/adapters/json_api_adapter.rb +15 -0
- data/lib/ruby_json_api_client/adapters/rest_adapter.rb +80 -0
- data/lib/ruby_json_api_client/base.rb +98 -0
- data/lib/ruby_json_api_client/collection.rb +13 -0
- data/lib/ruby_json_api_client/serializers/ams_serializer.rb +187 -0
- data/lib/ruby_json_api_client/serializers/json_api_serializer.rb +93 -0
- data/lib/ruby_json_api_client/store.rb +171 -0
- data/lib/ruby_json_api_client/version.rb +3 -0
- data/lib/ruby_json_api_client.rb +14 -0
- data/ruby_json_api_client.gemspec +34 -0
- data/spec/integration/ams/find_spec.rb +46 -0
- data/spec/integration/ams/has_many_links_spec.rb +161 -0
- data/spec/integration/ams/has_many_sideload_spec.rb +170 -0
- data/spec/integration/ams/has_one_links_spec.rb +57 -0
- data/spec/integration/ams/has_one_sideload_spec.rb +87 -0
- data/spec/integration/ams/query_spec.rb +65 -0
- data/spec/integration/json_api/find_spec.rb +44 -0
- data/spec/integration/json_api/query_spec.rb +65 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/classes.rb +26 -0
- data/spec/unit/adapters/json_api_spec.rb +4 -0
- data/spec/unit/adapters/rest_spec.rb +109 -0
- data/spec/unit/base_spec.rb +60 -0
- data/spec/unit/collection_spec.rb +17 -0
- data/spec/unit/serializers/ams_spec.rb +480 -0
- data/spec/unit/serializers/json_api_spec.rb +114 -0
- data/spec/unit/store_spec.rb +243 -0
- metadata +262 -0
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RubyJsonApiClient
|
4
|
+
class Store
|
5
|
+
def self.register_adapter(name, klass = nil, options = {})
|
6
|
+
@adapters ||= {}
|
7
|
+
|
8
|
+
# allow for 2 arguments (automatically figure out class if so)
|
9
|
+
if !klass.is_a?(Class)
|
10
|
+
# klass is options. autoamtically figure out klass and set options
|
11
|
+
temp = klass || options
|
12
|
+
class_name = name.to_s.camelize
|
13
|
+
klass = Kernel.const_get("RubyJsonApiClient::#{class_name}Adapter")
|
14
|
+
options = temp
|
15
|
+
end
|
16
|
+
|
17
|
+
@adapters[name] = OpenStruct.new({ klass: klass, options: options })
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def self.register_serializer(name, klass = nil)
|
22
|
+
@serializers ||= {}
|
23
|
+
|
24
|
+
if klass.nil?
|
25
|
+
class_name = name.to_s.camelize
|
26
|
+
klass = Kernel.const_get("RubyJsonApiClient::#{class_name}Serializer")
|
27
|
+
end
|
28
|
+
|
29
|
+
@serializers[name] = OpenStruct.new({ klass: klass })
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.get_serializer(name)
|
33
|
+
@serializers ||= {}
|
34
|
+
if @serializers[name]
|
35
|
+
@serializers[name].klass.new
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.get_adapter(name)
|
40
|
+
@adapters ||= {}
|
41
|
+
if @adapters[name]
|
42
|
+
@adapters[name].klass.new(@adapters[name].options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.default(format)
|
47
|
+
@store = new(format: format)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.instance
|
51
|
+
@store
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_accessor :default_adapter
|
55
|
+
attr_accessor :default_serializer
|
56
|
+
|
57
|
+
def initialize(options)
|
58
|
+
if options[:format]
|
59
|
+
options[:adapter] = options[:format]
|
60
|
+
options[:serializer] = options[:format]
|
61
|
+
end
|
62
|
+
|
63
|
+
@default_adapter = self.class.get_adapter(options[:adapter])
|
64
|
+
@default_serializer = self.class.get_serializer(options[:serializer])
|
65
|
+
|
66
|
+
if @default_serializer && @default_serializer.respond_to?(:store=)
|
67
|
+
@default_serializer.store = self
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def adapter_for_class(klass)
|
72
|
+
@default_adapter
|
73
|
+
end
|
74
|
+
|
75
|
+
def serializer_for_class(klass)
|
76
|
+
@default_serializer
|
77
|
+
end
|
78
|
+
|
79
|
+
def find(klass, id)
|
80
|
+
adapter = adapter_for_class(klass)
|
81
|
+
serializer = serializer_for_class(klass)
|
82
|
+
|
83
|
+
response = adapter.find(klass, id)
|
84
|
+
serializer.extract_single(klass, id, response).tap do |model|
|
85
|
+
model.__origin__ = response
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def query(klass, params)
|
90
|
+
adapter = adapter_for_class(klass)
|
91
|
+
serializer = serializer_for_class(klass)
|
92
|
+
|
93
|
+
response = adapter.find_many(klass, params)
|
94
|
+
list = serializer.extract_many(klass, response)
|
95
|
+
|
96
|
+
list.each do |model|
|
97
|
+
# let the model know where it came from
|
98
|
+
model.__origin__ = response
|
99
|
+
end
|
100
|
+
|
101
|
+
# cant tap proxy
|
102
|
+
collection = RubyJsonApiClient::Collection.new(list)
|
103
|
+
collection.__origin__ = response
|
104
|
+
collection
|
105
|
+
end
|
106
|
+
|
107
|
+
def find_many_relationship(parent, name, options)
|
108
|
+
# needs to use adapter_for_class
|
109
|
+
serializer = @default_serializer
|
110
|
+
|
111
|
+
# ensure parent is loaded
|
112
|
+
reload(parent) if parent.__origin__.nil?
|
113
|
+
|
114
|
+
response = parent.__origin__
|
115
|
+
|
116
|
+
# find the relationship
|
117
|
+
list = serializer.extract_many_relationship(parent, name, options, response)
|
118
|
+
|
119
|
+
# wrap in enumerable proxy to allow reloading
|
120
|
+
collection = RubyJsonApiClient::Collection.new(list)
|
121
|
+
collection.__origin__ = response
|
122
|
+
collection
|
123
|
+
end
|
124
|
+
|
125
|
+
def find_single_relationship(parent, name, options)
|
126
|
+
# needs to use serializer_for_class
|
127
|
+
serializer = @default_serializer
|
128
|
+
|
129
|
+
reload(parent) if parent.__origin__.nil?
|
130
|
+
|
131
|
+
response = parent.__origin__
|
132
|
+
|
133
|
+
serializer.extract_single_relationship(parent, name, options, response)
|
134
|
+
end
|
135
|
+
|
136
|
+
def load_collection(klass, url)
|
137
|
+
adapter = adapter_for_class(klass)
|
138
|
+
serializer = serializer_for_class(klass)
|
139
|
+
response = adapter.get(url)
|
140
|
+
serializer.extract_many(klass, response)
|
141
|
+
end
|
142
|
+
|
143
|
+
def load_single(klass, id, url)
|
144
|
+
adapter = adapter_for_class(klass)
|
145
|
+
serializer = serializer_for_class(klass)
|
146
|
+
response = adapter.get(url)
|
147
|
+
serializer.extract_single(klass, id, response)
|
148
|
+
end
|
149
|
+
|
150
|
+
def load(klass, data)
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
def reload(model)
|
155
|
+
new_model = find(model.class, model.id)
|
156
|
+
merge(model, new_model)
|
157
|
+
end
|
158
|
+
|
159
|
+
def merge(into, from)
|
160
|
+
into.__origin__ = from.__origin__
|
161
|
+
into.meta = from.meta
|
162
|
+
|
163
|
+
from.class.fields.reduce(into) do |model, attr|
|
164
|
+
call = "#{attr}="
|
165
|
+
model.send(call, from.send(attr)) if model.respond_to?(call)
|
166
|
+
model
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module RubyJsonApiClient
|
4
|
+
end
|
5
|
+
|
6
|
+
require "ruby_json_api_client/version"
|
7
|
+
require 'ruby_json_api_client/serializers/json_api_serializer'
|
8
|
+
require 'ruby_json_api_client/serializers/ams_serializer'
|
9
|
+
require 'ruby_json_api_client/adapters/rest_adapter'
|
10
|
+
require 'ruby_json_api_client/adapters/json_api_adapter'
|
11
|
+
require 'ruby_json_api_client/adapters/ams_adapter'
|
12
|
+
require 'ruby_json_api_client/collection'
|
13
|
+
require 'ruby_json_api_client/store'
|
14
|
+
require 'ruby_json_api_client/base'
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ruby_json_api_client/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ruby_json_api_client"
|
8
|
+
spec.version = RubyJsonApiClient::VERSION
|
9
|
+
spec.authors = ["Ryan Toronto"]
|
10
|
+
spec.email = ["ryanto@gmail.com"]
|
11
|
+
spec.summary = %q{API client for activemodel instances}
|
12
|
+
spec.description = %q{API client for activemodel instances}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'json', '>= 1.8.1'
|
22
|
+
spec.add_dependency 'faraday', '>= 0.9.0'
|
23
|
+
spec.add_dependency 'addressable', '>= 2.3.6'
|
24
|
+
spec.add_dependency 'activemodel', '>= 4.0'
|
25
|
+
spec.add_dependency 'activesupport', '>= 4.0'
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency "pry"
|
30
|
+
spec.add_development_dependency "rspec", "~> 3.0.0"
|
31
|
+
spec.add_development_dependency 'rspec-collection_matchers', '~> 1.0.0'
|
32
|
+
spec.add_development_dependency 'rspec-its', '~> 1.0.1'
|
33
|
+
spec.add_development_dependency 'webmock', '~> 1.18.0'
|
34
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "AMS find single" do
|
4
|
+
context "person" do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
RubyJsonApiClient::Store.register_adapter(:ams, {
|
8
|
+
hostname: 'www.example.com',
|
9
|
+
namespace: 'testing',
|
10
|
+
secure: true
|
11
|
+
});
|
12
|
+
|
13
|
+
RubyJsonApiClient::Store.register_serializer(:ams)
|
14
|
+
|
15
|
+
RubyJsonApiClient::Store.default(:ams)
|
16
|
+
end
|
17
|
+
|
18
|
+
context "it exists" do
|
19
|
+
before(:each) do
|
20
|
+
response = {
|
21
|
+
person: {
|
22
|
+
id: 123,
|
23
|
+
firstname: 'ryan',
|
24
|
+
lastname: 'test'
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
json = response.to_json
|
29
|
+
|
30
|
+
stub_request(:get, "https://www.example.com/testing/people/123")
|
31
|
+
.to_return(
|
32
|
+
status: 200,
|
33
|
+
headers: { 'Content-Length' => json.size },
|
34
|
+
body: json,
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
context "loads the right model" do
|
39
|
+
subject { Person.find(123) }
|
40
|
+
its(:id) { should eq(123) }
|
41
|
+
its(:firstname) { should eq("ryan") }
|
42
|
+
its(:full_name) { should eq("ryan test") }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "AMS load has_many linked records" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
RubyJsonApiClient::Store.register_adapter(:ams, {
|
7
|
+
hostname: 'www.example.com'
|
8
|
+
});
|
9
|
+
|
10
|
+
RubyJsonApiClient::Store.register_serializer(:ams)
|
11
|
+
|
12
|
+
RubyJsonApiClient::Store.default(:ams)
|
13
|
+
end
|
14
|
+
|
15
|
+
context "that are loaded" do
|
16
|
+
before(:each) do
|
17
|
+
people_response = {
|
18
|
+
people: [{
|
19
|
+
id: 123,
|
20
|
+
firstname: 'ryan',
|
21
|
+
lastname: 'test',
|
22
|
+
links: {
|
23
|
+
items: "http://www.example.com/items?person=123"
|
24
|
+
}
|
25
|
+
},{
|
26
|
+
id: 456,
|
27
|
+
firstname: 'testing',
|
28
|
+
lastname: 'again',
|
29
|
+
links: {
|
30
|
+
items: "/items?person=456"
|
31
|
+
}
|
32
|
+
}]
|
33
|
+
}.to_json
|
34
|
+
|
35
|
+
items_response = {
|
36
|
+
items: [{
|
37
|
+
id: 10,
|
38
|
+
name: "testing"
|
39
|
+
},{
|
40
|
+
id: 11,
|
41
|
+
name: "another test"
|
42
|
+
}]
|
43
|
+
}.to_json
|
44
|
+
|
45
|
+
no_items_response = {
|
46
|
+
items: []
|
47
|
+
}.to_json
|
48
|
+
|
49
|
+
stub_request(:get, "http://www.example.com/people")
|
50
|
+
.to_return(
|
51
|
+
status: 200,
|
52
|
+
body: people_response,
|
53
|
+
)
|
54
|
+
|
55
|
+
stub_request(:get, "http://www.example.com/items?person=123")
|
56
|
+
.to_return(
|
57
|
+
status: 200,
|
58
|
+
body: items_response
|
59
|
+
)
|
60
|
+
|
61
|
+
stub_request(:get, "http://www.example.com/items?person=456")
|
62
|
+
.to_return(
|
63
|
+
status: 200,
|
64
|
+
body: no_items_response
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
let(:collection) { Person.all }
|
69
|
+
let(:person1) { collection[0] }
|
70
|
+
let(:person2) { collection[1] }
|
71
|
+
|
72
|
+
context "using the first person" do
|
73
|
+
subject { person1 }
|
74
|
+
its(:id) { should eq(123) }
|
75
|
+
its(:items) { should have(2).items }
|
76
|
+
|
77
|
+
it "should have mappable items" do
|
78
|
+
expect(person1.items.map(&:name))
|
79
|
+
.to match_array(['testing', 'another test'])
|
80
|
+
end
|
81
|
+
|
82
|
+
context "and their first item" do
|
83
|
+
subject { person1.items[0] }
|
84
|
+
its(:id) { should eq(10) }
|
85
|
+
its(:name) { should eq("testing") }
|
86
|
+
end
|
87
|
+
|
88
|
+
context "and their second item" do
|
89
|
+
subject { person1.items[1] }
|
90
|
+
its(:id) { should eq(11) }
|
91
|
+
its(:name) { should eq("another test") }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "that are not loaded" do
|
97
|
+
# this tests Person.new(id: 123).items will load the person
|
98
|
+
# then load the items
|
99
|
+
|
100
|
+
before(:each) do
|
101
|
+
person_response = {
|
102
|
+
person: {
|
103
|
+
id: 123,
|
104
|
+
firstname: "ryan",
|
105
|
+
links: {
|
106
|
+
# use a strange url
|
107
|
+
items: "/testing/items?p_id=123"
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}.to_json
|
111
|
+
|
112
|
+
items_response = {
|
113
|
+
items: [{
|
114
|
+
id: 1,
|
115
|
+
name: "first"
|
116
|
+
}, {
|
117
|
+
id: 2,
|
118
|
+
name: "second"
|
119
|
+
}]
|
120
|
+
}.to_json
|
121
|
+
|
122
|
+
stub_request(:get, "http://www.example.com/people/123")
|
123
|
+
.to_return(
|
124
|
+
status: 200,
|
125
|
+
body: person_response,
|
126
|
+
)
|
127
|
+
|
128
|
+
stub_request(:get, "http://www.example.com/testing/items?p_id=123")
|
129
|
+
.to_return(
|
130
|
+
status: 200,
|
131
|
+
body: items_response,
|
132
|
+
)
|
133
|
+
end
|
134
|
+
|
135
|
+
let(:person) { Person.new(id: 123) }
|
136
|
+
let(:items) { person.items }
|
137
|
+
|
138
|
+
context "the person" do
|
139
|
+
subject { person }
|
140
|
+
|
141
|
+
before(:each) do
|
142
|
+
# load items (which should load person)
|
143
|
+
person.items
|
144
|
+
end
|
145
|
+
|
146
|
+
its(:id) { should eq(123) }
|
147
|
+
its(:firstname) { should eq('ryan') }
|
148
|
+
end
|
149
|
+
|
150
|
+
context "the items" do
|
151
|
+
subject { items }
|
152
|
+
it { should have(2).items }
|
153
|
+
|
154
|
+
context "the first item" do
|
155
|
+
subject { items[0] }
|
156
|
+
its(:name) { should eq('first') }
|
157
|
+
its(:id) { should eq(1) }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "AMS load has_many sideloaded records" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
RubyJsonApiClient::Store.register_adapter(:ams, {
|
7
|
+
hostname: 'www.example.com'
|
8
|
+
});
|
9
|
+
|
10
|
+
RubyJsonApiClient::Store.register_serializer(:ams)
|
11
|
+
|
12
|
+
RubyJsonApiClient::Store.default(:ams)
|
13
|
+
end
|
14
|
+
|
15
|
+
context "that are loaded" do
|
16
|
+
before(:each) do
|
17
|
+
response = {
|
18
|
+
people: [{
|
19
|
+
id: 123,
|
20
|
+
firstname: 'ryan',
|
21
|
+
lastname: 'test',
|
22
|
+
item_ids: [1,2]
|
23
|
+
},{
|
24
|
+
id: 456,
|
25
|
+
firstname: 'testing',
|
26
|
+
lastname: 'again',
|
27
|
+
item_ids: [2,3]
|
28
|
+
}],
|
29
|
+
items: [{
|
30
|
+
id: 1,
|
31
|
+
name: 'test 1'
|
32
|
+
},{
|
33
|
+
id: 2,
|
34
|
+
name: 'test 2'
|
35
|
+
},{
|
36
|
+
id: 3,
|
37
|
+
name: 'test 3'
|
38
|
+
},{
|
39
|
+
id: 4,
|
40
|
+
name: 'test 4'
|
41
|
+
}]
|
42
|
+
}.to_json
|
43
|
+
|
44
|
+
stub_request(:get, "http://www.example.com/people")
|
45
|
+
.to_return(
|
46
|
+
status: 200,
|
47
|
+
body: response,
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
let(:collection) { Person.all }
|
52
|
+
let(:person1) { collection[0] }
|
53
|
+
let(:person2) { collection[1] }
|
54
|
+
|
55
|
+
context "using the first person" do
|
56
|
+
subject { person1 }
|
57
|
+
its(:id) { should eq(123) }
|
58
|
+
its(:items) { should have(2).items }
|
59
|
+
|
60
|
+
it "should have mappable items" do
|
61
|
+
expect(person1.items.map(&:name))
|
62
|
+
.to match_array(['test 1', 'test 2'])
|
63
|
+
end
|
64
|
+
|
65
|
+
context "and their first item" do
|
66
|
+
subject { person1.items[0] }
|
67
|
+
its(:id) { should eq(1) }
|
68
|
+
its(:name) { should eq("test 1") }
|
69
|
+
end
|
70
|
+
|
71
|
+
context "and their second item" do
|
72
|
+
subject { person1.items[1] }
|
73
|
+
its(:id) { should eq(2) }
|
74
|
+
its(:name) { should eq("test 2") }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "that are not loaded" do
|
80
|
+
# this tests Person.new(id: 123).items will load the person
|
81
|
+
# then load the items
|
82
|
+
|
83
|
+
before(:each) do
|
84
|
+
response = {
|
85
|
+
person: {
|
86
|
+
id: 123,
|
87
|
+
firstname: "ryan",
|
88
|
+
item_ids: [1, 2]
|
89
|
+
},
|
90
|
+
items: [{
|
91
|
+
id: 1,
|
92
|
+
name: "first"
|
93
|
+
}, {
|
94
|
+
id: 2,
|
95
|
+
name: "second"
|
96
|
+
}]
|
97
|
+
}.to_json
|
98
|
+
|
99
|
+
stub_request(:get, "http://www.example.com/people/123")
|
100
|
+
.to_return(
|
101
|
+
status: 200,
|
102
|
+
body: response,
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
let(:person) { Person.new(id: 123) }
|
107
|
+
let(:items) { person.items }
|
108
|
+
|
109
|
+
context "the person" do
|
110
|
+
subject { person }
|
111
|
+
|
112
|
+
before(:each) do
|
113
|
+
# load items (which should load person)
|
114
|
+
person.items
|
115
|
+
end
|
116
|
+
|
117
|
+
its(:id) { should eq(123) }
|
118
|
+
its(:firstname) { should eq('ryan') }
|
119
|
+
end
|
120
|
+
|
121
|
+
context "the items" do
|
122
|
+
subject { items }
|
123
|
+
it { should have(2).items }
|
124
|
+
|
125
|
+
context "the first item" do
|
126
|
+
subject { items[0] }
|
127
|
+
its(:name) { should eq('first') }
|
128
|
+
its(:id) { should eq(1) }
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "using a different relationship class name" do
|
134
|
+
before(:each) do
|
135
|
+
response = {
|
136
|
+
person: {
|
137
|
+
id: 123,
|
138
|
+
firstname: "ryan",
|
139
|
+
other_item_ids: [1, 2]
|
140
|
+
},
|
141
|
+
other_items: [{
|
142
|
+
id: 1,
|
143
|
+
name: "first"
|
144
|
+
},{
|
145
|
+
id: 2,
|
146
|
+
name: "second"
|
147
|
+
}]
|
148
|
+
}.to_json
|
149
|
+
|
150
|
+
stub_request(:get, "http://www.example.com/people/123")
|
151
|
+
.to_return(
|
152
|
+
status: 200,
|
153
|
+
body: response,
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
let(:person) { Person.new(id: 123) }
|
158
|
+
let(:other_items) { person.other_items }
|
159
|
+
|
160
|
+
subject { other_items }
|
161
|
+
it { should have(2).items }
|
162
|
+
|
163
|
+
context "the first item" do
|
164
|
+
subject { other_items[0] }
|
165
|
+
its(:name) { should eq('first') }
|
166
|
+
its(:id) { should eq(1) }
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "AMS load has_one linked record" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
RubyJsonApiClient::Store.register_adapter(:ams, {
|
7
|
+
hostname: 'www.example.com'
|
8
|
+
});
|
9
|
+
|
10
|
+
RubyJsonApiClient::Store.register_serializer(:ams)
|
11
|
+
|
12
|
+
RubyJsonApiClient::Store.default(:ams)
|
13
|
+
end
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
person_response = {
|
17
|
+
person: {
|
18
|
+
id: 123,
|
19
|
+
firstname: 'ryan',
|
20
|
+
lastname: 'test',
|
21
|
+
links: {
|
22
|
+
item: "http://www.example.com/items/10"
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}.to_json
|
26
|
+
|
27
|
+
item_response = {
|
28
|
+
item: {
|
29
|
+
id: 10,
|
30
|
+
name: "testing"
|
31
|
+
}
|
32
|
+
}.to_json
|
33
|
+
|
34
|
+
stub_request(:get, "http://www.example.com/people/123")
|
35
|
+
.to_return(
|
36
|
+
status: 200,
|
37
|
+
body: person_response,
|
38
|
+
)
|
39
|
+
|
40
|
+
stub_request(:get, "http://www.example.com/items/10")
|
41
|
+
.to_return(
|
42
|
+
status: 200,
|
43
|
+
body: item_response
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
let(:person) { Person.find(123) }
|
49
|
+
let(:item) { person.item }
|
50
|
+
|
51
|
+
context "the item" do
|
52
|
+
subject { item }
|
53
|
+
it { should be_instance_of(Item) }
|
54
|
+
its(:id) { should eq(10) }
|
55
|
+
its(:name) { should eq('testing') }
|
56
|
+
end
|
57
|
+
end
|