her 0.8.2 → 0.8.3
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.
- checksums.yaml +4 -4
- data/.rspec +1 -1
- data/.rubocop.yml +1291 -0
- data/.travis.yml +1 -0
- data/her.gemspec +1 -3
- data/lib/her/model/orm.rb +4 -1
- data/lib/her/version.rb +1 -1
- data/spec/api_spec.rb +34 -31
- data/spec/collection_spec.rb +25 -10
- data/spec/json_api/model_spec.rb +75 -72
- data/spec/middleware/accept_json_spec.rb +1 -1
- data/spec/middleware/first_level_parse_json_spec.rb +20 -20
- data/spec/middleware/json_api_parser_spec.rb +6 -7
- data/spec/middleware/second_level_parse_json_spec.rb +8 -9
- data/spec/model/associations/association_proxy_spec.rb +2 -5
- data/spec/model/associations_spec.rb +199 -158
- data/spec/model/attributes_spec.rb +98 -99
- data/spec/model/callbacks_spec.rb +58 -26
- data/spec/model/dirty_spec.rb +30 -29
- data/spec/model/http_spec.rb +67 -35
- data/spec/model/introspection_spec.rb +26 -22
- data/spec/model/nested_attributes_spec.rb +31 -31
- data/spec/model/orm_spec.rb +166 -154
- data/spec/model/parse_spec.rb +77 -77
- data/spec/model/paths_spec.rb +109 -109
- data/spec/model/relation_spec.rb +68 -68
- data/spec/model/validations_spec.rb +6 -6
- data/spec/model_spec.rb +17 -17
- data/spec/spec_helper.rb +2 -3
- data/spec/support/macros/model_macros.rb +2 -2
- metadata +32 -59
data/.travis.yml
CHANGED
data/her.gemspec
CHANGED
@@ -18,9 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
20
|
s.add_development_dependency "rake", "~> 10.0"
|
21
|
-
s.add_development_dependency "rspec", "~>
|
22
|
-
s.add_development_dependency "rspec-its", "~> 1.0"
|
23
|
-
s.add_development_dependency "fivemat", "~> 1.2"
|
21
|
+
s.add_development_dependency "rspec", "~> 3.5"
|
24
22
|
s.add_development_dependency "json", "~> 1.8"
|
25
23
|
|
26
24
|
s.add_runtime_dependency "activemodel", ">= 3.0.0", "<= 6.0.0"
|
data/lib/her/model/orm.rb
CHANGED
@@ -160,7 +160,10 @@ module Her
|
|
160
160
|
# # Called via DELETE "/users/1"
|
161
161
|
def destroy_existing(id, params={})
|
162
162
|
request(params.merge(:_method => method_for(:destroy), :_path => build_request_path(params.merge(primary_key => id)))) do |parsed_data, response|
|
163
|
-
|
163
|
+
data = parse(parsed_data[:data])
|
164
|
+
metadata = parsed_data[:metadata]
|
165
|
+
response_errors = parsed_data[:errors]
|
166
|
+
new(data.merge(:_destroyed => true, :metadata => metadata, :response_errors => response_errors))
|
164
167
|
end
|
165
168
|
end
|
166
169
|
|
data/lib/her/version.rb
CHANGED
data/spec/api_spec.rb
CHANGED
@@ -8,21 +8,24 @@ describe Her::API do
|
|
8
8
|
describe "#setup" do
|
9
9
|
context "when setting custom middleware" do
|
10
10
|
before do
|
11
|
-
class Foo; end
|
12
|
-
class Bar; end
|
11
|
+
class Foo; end
|
12
|
+
class Bar; end
|
13
13
|
|
14
|
-
subject.setup :
|
14
|
+
subject.setup url: "https://api.example.com" do |connection|
|
15
15
|
connection.use Foo
|
16
16
|
connection.use Bar
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
specify { subject.connection.builder.handlers.
|
20
|
+
specify { expect(subject.connection.builder.handlers).to eq([Foo, Bar]) }
|
21
21
|
end
|
22
22
|
|
23
23
|
context "when setting custom options" do
|
24
|
-
before { subject.setup :
|
25
|
-
|
24
|
+
before { subject.setup foo: { bar: "baz" }, url: "https://api.example.com" }
|
25
|
+
|
26
|
+
describe "#options" do
|
27
|
+
it { expect(subject.options).to eq(foo: { bar: "baz" }, url: "https://api.example.com") }
|
28
|
+
end
|
26
29
|
end
|
27
30
|
end
|
28
31
|
|
@@ -30,83 +33,83 @@ describe Her::API do
|
|
30
33
|
before do
|
31
34
|
class SimpleParser < Faraday::Response::Middleware
|
32
35
|
def on_complete(env)
|
33
|
-
env[:body] = { :
|
36
|
+
env[:body] = { data: env[:body] }
|
34
37
|
end
|
35
38
|
end
|
36
39
|
end
|
37
40
|
|
38
41
|
context "making HTTP requests" do
|
39
|
-
let(:parsed_data) { subject.request(:
|
42
|
+
let(:parsed_data) { subject.request(_method: :get, _path: "/foo")[:parsed_data] }
|
40
43
|
before do
|
41
|
-
subject.setup :
|
44
|
+
subject.setup url: "https://api.example.com" do |builder|
|
42
45
|
builder.use SimpleParser
|
43
|
-
builder.adapter(:test) { |stub| stub.get("/foo") {
|
46
|
+
builder.adapter(:test) { |stub| stub.get("/foo") { [200, {}, "Foo, it is."] } }
|
44
47
|
end
|
45
48
|
end
|
46
49
|
|
47
|
-
specify { parsed_data[:data].
|
50
|
+
specify { expect(parsed_data[:data]).to eq("Foo, it is.") }
|
48
51
|
end
|
49
52
|
|
50
53
|
context "making HTTP requests while specifying custom HTTP headers" do
|
51
|
-
let(:parsed_data) { subject.request(:
|
54
|
+
let(:parsed_data) { subject.request(_method: :get, _path: "/foo", _headers: { "X-Page" => 2 })[:parsed_data] }
|
52
55
|
|
53
56
|
before do
|
54
|
-
subject.setup :
|
57
|
+
subject.setup url: "https://api.example.com" do |builder|
|
55
58
|
builder.use SimpleParser
|
56
|
-
builder.adapter(:test) { |stub| stub.get("/foo") { |env| [200, {}, "Foo, it is page #{env[:request_headers][
|
59
|
+
builder.adapter(:test) { |stub| stub.get("/foo") { |env| [200, {}, "Foo, it is page #{env[:request_headers]['X-Page']}."] } }
|
57
60
|
end
|
58
61
|
end
|
59
62
|
|
60
|
-
specify { parsed_data[:data].
|
63
|
+
specify { expect(parsed_data[:data]).to eq("Foo, it is page 2.") }
|
61
64
|
end
|
62
65
|
|
63
66
|
context "parsing a request with the default parser" do
|
64
|
-
let(:parsed_data) { subject.request(:
|
67
|
+
let(:parsed_data) { subject.request(_method: :get, _path: "users/1")[:parsed_data] }
|
65
68
|
before do
|
66
|
-
subject.setup :
|
69
|
+
subject.setup url: "https://api.example.com" do |builder|
|
67
70
|
builder.use Her::Middleware::FirstLevelParseJSON
|
68
71
|
builder.adapter :test do |stub|
|
69
|
-
stub.get("/users/1") {
|
72
|
+
stub.get("/users/1") { [200, {}, MultiJson.dump(id: 1, name: "George Michael Bluth", errors: ["This is a single error"], metadata: { page: 1, per_page: 10 })] }
|
70
73
|
end
|
71
74
|
end
|
72
75
|
end
|
73
76
|
|
74
77
|
specify do
|
75
|
-
parsed_data[:data].
|
76
|
-
parsed_data[:errors].
|
77
|
-
parsed_data[:metadata].
|
78
|
+
expect(parsed_data[:data]).to eq(id: 1, name: "George Michael Bluth")
|
79
|
+
expect(parsed_data[:errors]).to eq(["This is a single error"])
|
80
|
+
expect(parsed_data[:metadata]).to eq(page: 1, per_page: 10)
|
78
81
|
end
|
79
82
|
end
|
80
83
|
|
81
84
|
context "parsing a request with a custom parser" do
|
82
|
-
let(:parsed_data) { subject.request(:
|
85
|
+
let(:parsed_data) { subject.request(_method: :get, _path: "users/1")[:parsed_data] }
|
83
86
|
before do
|
84
87
|
class CustomParser < Faraday::Response::Middleware
|
85
88
|
def on_complete(env)
|
86
|
-
json = MultiJson.load(env[:body], :
|
89
|
+
json = MultiJson.load(env[:body], symbolize_keys: true)
|
87
90
|
errors = json.delete(:errors) || []
|
88
91
|
metadata = json.delete(:metadata) || {}
|
89
92
|
env[:body] = {
|
90
|
-
:
|
91
|
-
:
|
92
|
-
:
|
93
|
+
data: json,
|
94
|
+
errors: errors,
|
95
|
+
metadata: metadata
|
93
96
|
}
|
94
97
|
end
|
95
98
|
end
|
96
99
|
|
97
|
-
subject.setup :
|
100
|
+
subject.setup url: "https://api.example.com" do |builder|
|
98
101
|
builder.use CustomParser
|
99
102
|
builder.use Faraday::Request::UrlEncoded
|
100
103
|
builder.adapter :test do |stub|
|
101
|
-
stub.get("/users/1") {
|
104
|
+
stub.get("/users/1") { [200, {}, MultiJson.dump(id: 1, name: "George Michael Bluth")] }
|
102
105
|
end
|
103
106
|
end
|
104
107
|
end
|
105
108
|
|
106
109
|
specify do
|
107
|
-
parsed_data[:data].
|
108
|
-
parsed_data[:errors].
|
109
|
-
parsed_data[:metadata].
|
110
|
+
expect(parsed_data[:data]).to eq(id: 1, name: "George Michael Bluth")
|
111
|
+
expect(parsed_data[:errors]).to eq([])
|
112
|
+
expect(parsed_data[:metadata]).to eq({})
|
110
113
|
end
|
111
114
|
end
|
112
115
|
end
|
data/spec/collection_spec.rb
CHANGED
@@ -1,26 +1,41 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe Her::Collection do
|
4
|
-
|
5
4
|
let(:items) { [1, 2, 3, 4] }
|
6
|
-
let(:metadata) { { :
|
7
|
-
let(:errors) { { :
|
5
|
+
let(:metadata) { { name: "Testname" } }
|
6
|
+
let(:errors) { { name: ["not_present"] } }
|
8
7
|
|
9
8
|
describe "#new" do
|
10
9
|
context "without parameters" do
|
11
10
|
subject { Her::Collection.new }
|
12
11
|
|
13
|
-
it {
|
14
|
-
|
15
|
-
|
12
|
+
it { is_expected.to eq([]) }
|
13
|
+
|
14
|
+
describe "#metadata" do
|
15
|
+
subject { super().metadata }
|
16
|
+
it { is_expected.to eq({}) }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#errors" do
|
20
|
+
subject { super().errors }
|
21
|
+
it { is_expected.to eq({}) }
|
22
|
+
end
|
16
23
|
end
|
17
24
|
|
18
25
|
context "with parameters" do
|
19
26
|
subject { Her::Collection.new(items, metadata, errors) }
|
20
27
|
|
21
|
-
it {
|
22
|
-
|
23
|
-
|
28
|
+
it { is_expected.to eq([1, 2, 3, 4]) }
|
29
|
+
|
30
|
+
describe "#metadata" do
|
31
|
+
subject { super().metadata }
|
32
|
+
it { is_expected.to eq(name: "Testname") }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#errors" do
|
36
|
+
subject { super().errors }
|
37
|
+
it { is_expected.to eq(name: ["not_present"]) }
|
38
|
+
end
|
24
39
|
end
|
25
40
|
end
|
26
41
|
end
|
data/spec/json_api/model_spec.rb
CHANGED
@@ -1,163 +1,166 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe Her::JsonApi::Model do
|
4
4
|
before do
|
5
|
-
Her::API.setup :
|
5
|
+
Her::API.setup url: "https://api.example.com" do |connection|
|
6
6
|
connection.use Her::Middleware::JsonApiParser
|
7
7
|
connection.adapter :test do |stub|
|
8
|
-
stub.get("/users/1") do
|
9
|
-
[
|
8
|
+
stub.get("/users/1") do
|
9
|
+
[
|
10
10
|
200,
|
11
11
|
{},
|
12
12
|
{
|
13
13
|
data: {
|
14
14
|
id: 1,
|
15
|
-
type:
|
15
|
+
type: "users",
|
16
16
|
attributes: {
|
17
|
-
name: "Roger Federer"
|
18
|
-
}
|
17
|
+
name: "Roger Federer"
|
18
|
+
}
|
19
19
|
}
|
20
|
-
|
20
|
+
|
21
21
|
}.to_json
|
22
|
-
]
|
22
|
+
]
|
23
23
|
end
|
24
24
|
|
25
|
-
stub.get("/users") do
|
26
|
-
[
|
25
|
+
stub.get("/users") do
|
26
|
+
[
|
27
27
|
200,
|
28
28
|
{},
|
29
29
|
{
|
30
30
|
data: [
|
31
31
|
{
|
32
32
|
id: 1,
|
33
|
-
type:
|
33
|
+
type: "users",
|
34
34
|
attributes: {
|
35
|
-
name: "Roger Federer"
|
36
|
-
}
|
37
|
-
},
|
35
|
+
name: "Roger Federer"
|
36
|
+
}
|
37
|
+
},
|
38
38
|
{
|
39
39
|
id: 2,
|
40
|
-
type:
|
40
|
+
type: "users",
|
41
41
|
attributes: {
|
42
|
-
name: "Kei Nishikori"
|
43
|
-
}
|
42
|
+
name: "Kei Nishikori"
|
43
|
+
}
|
44
44
|
}
|
45
45
|
]
|
46
46
|
}.to_json
|
47
|
-
]
|
47
|
+
]
|
48
48
|
end
|
49
49
|
|
50
|
-
stub.post("/users", data:
|
51
|
-
|
50
|
+
stub.post("/users", data:
|
51
|
+
{
|
52
|
+
type: "users",
|
52
53
|
attributes: {
|
53
|
-
name: "Jeremy Lin"
|
54
|
-
}
|
55
|
-
}) do
|
56
|
-
[
|
54
|
+
name: "Jeremy Lin"
|
55
|
+
}
|
56
|
+
}) do
|
57
|
+
[
|
57
58
|
201,
|
58
59
|
{},
|
59
60
|
{
|
60
61
|
data: {
|
61
62
|
id: 3,
|
62
|
-
type:
|
63
|
+
type: "users",
|
63
64
|
attributes: {
|
64
|
-
name:
|
65
|
-
}
|
65
|
+
name: "Jeremy Lin"
|
66
|
+
}
|
66
67
|
}
|
67
|
-
|
68
|
+
|
68
69
|
}.to_json
|
69
|
-
]
|
70
|
+
]
|
70
71
|
end
|
71
72
|
|
72
|
-
stub.patch("/users/1", data:
|
73
|
-
|
73
|
+
stub.patch("/users/1", data:
|
74
|
+
{
|
75
|
+
type: "users",
|
74
76
|
id: 1,
|
75
77
|
attributes: {
|
76
|
-
name: "Fed GOAT"
|
77
|
-
}
|
78
|
-
}) do
|
79
|
-
[
|
78
|
+
name: "Fed GOAT"
|
79
|
+
}
|
80
|
+
}) do
|
81
|
+
[
|
80
82
|
200,
|
81
83
|
{},
|
82
84
|
{
|
83
85
|
data: {
|
84
86
|
id: 1,
|
85
|
-
type:
|
87
|
+
type: "users",
|
86
88
|
attributes: {
|
87
|
-
name:
|
88
|
-
}
|
89
|
+
name: "Fed GOAT"
|
90
|
+
}
|
89
91
|
}
|
90
|
-
|
92
|
+
|
91
93
|
}.to_json
|
92
|
-
]
|
94
|
+
]
|
93
95
|
end
|
94
96
|
|
95
|
-
stub.delete("/users/1")
|
96
|
-
[
|
97
|
-
|
97
|
+
stub.delete("/users/1") do
|
98
|
+
[204, {}, {}]
|
99
|
+
end
|
98
100
|
end
|
99
|
-
|
100
101
|
end
|
101
102
|
|
102
103
|
spawn_model("Foo::User", type: Her::JsonApi::Model)
|
103
104
|
end
|
104
105
|
|
105
|
-
it
|
106
|
+
it "allows configuration of type" do
|
106
107
|
spawn_model("Foo::Bar", type: Her::JsonApi::Model) do
|
107
108
|
type :foobars
|
108
109
|
end
|
109
110
|
|
110
|
-
expect(Foo::Bar.instance_variable_get(
|
111
|
+
expect(Foo::Bar.instance_variable_get("@type")).to eql("foobars")
|
111
112
|
end
|
112
113
|
|
113
|
-
it
|
114
|
+
it "finds models by id" do
|
114
115
|
user = Foo::User.find(1)
|
115
116
|
expect(user.attributes).to eql(
|
116
|
-
|
117
|
-
|
117
|
+
"id" => 1,
|
118
|
+
"name" => "Roger Federer"
|
118
119
|
)
|
119
120
|
end
|
120
121
|
|
121
|
-
it
|
122
|
+
it "finds a collection of models" do
|
122
123
|
users = Foo::User.all
|
123
|
-
expect(users.map(&:attributes)).to match_array(
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
124
|
+
expect(users.map(&:attributes)).to match_array(
|
125
|
+
[
|
126
|
+
{
|
127
|
+
"id" => 1,
|
128
|
+
"name" => "Roger Federer"
|
129
|
+
},
|
130
|
+
{
|
131
|
+
"id" => 2,
|
132
|
+
"name" => "Kei Nishikori"
|
133
|
+
}
|
134
|
+
]
|
135
|
+
)
|
133
136
|
end
|
134
137
|
|
135
|
-
it
|
136
|
-
user = Foo::User.new(name:
|
138
|
+
it "creates a Foo::User" do
|
139
|
+
user = Foo::User.new(name: "Jeremy Lin")
|
137
140
|
user.save
|
138
141
|
expect(user.attributes).to eql(
|
139
|
-
|
140
|
-
|
142
|
+
"id" => 3,
|
143
|
+
"name" => "Jeremy Lin"
|
141
144
|
)
|
142
145
|
end
|
143
146
|
|
144
|
-
it
|
147
|
+
it "updates a Foo::User" do
|
145
148
|
user = Foo::User.find(1)
|
146
|
-
user.name =
|
149
|
+
user.name = "Fed GOAT"
|
147
150
|
user.save
|
148
151
|
expect(user.attributes).to eql(
|
149
|
-
|
150
|
-
|
152
|
+
"id" => 1,
|
153
|
+
"name" => "Fed GOAT"
|
151
154
|
)
|
152
155
|
end
|
153
156
|
|
154
|
-
it
|
157
|
+
it "destroys a Foo::User" do
|
155
158
|
user = Foo::User.find(1)
|
156
159
|
expect(user.destroy).to be_destroyed
|
157
160
|
end
|
158
161
|
|
159
|
-
context
|
160
|
-
it
|
162
|
+
context "undefined methods" do
|
163
|
+
it "removes methods that are not compatible with json api" do
|
161
164
|
[:parse_root_in_json, :include_root_in_json, :root_element, :primary_key].each do |method|
|
162
165
|
expect { Foo::User.new.send(method, :foo) }.to raise_error NoMethodError, "Her::JsonApi::Model does not support the #{method} configuration option"
|
163
166
|
end
|