her 0.8.2 → 0.9.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.
- checksums.yaml +4 -4
- data/.rspec +1 -1
- data/.rubocop.yml +1291 -0
- data/.travis.yml +2 -0
- data/README.md +23 -3
- data/her.gemspec +1 -3
- data/lib/her/middleware/json_api_parser.rb +1 -1
- data/lib/her/model/associations/association.rb +31 -0
- data/lib/her/model/associations/association_proxy.rb +1 -1
- data/lib/her/model/attributes.rb +2 -0
- data/lib/her/model/orm.rb +79 -6
- data/lib/her/model/parse.rb +8 -12
- data/lib/her/model/relation.rb +45 -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 +26 -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 +248 -161
- data/spec/model/attributes_spec.rb +106 -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 +312 -155
- data/spec/model/parse_spec.rb +77 -77
- data/spec/model/paths_spec.rb +109 -109
- data/spec/model/relation_spec.rb +76 -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/spec/model/dirty_spec.rb
CHANGED
@@ -4,16 +4,16 @@ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
|
4
4
|
describe "Her::Model and ActiveModel::Dirty" do
|
5
5
|
context "checking dirty attributes" do
|
6
6
|
before do
|
7
|
-
Her::API.setup :
|
7
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
8
8
|
builder.use Her::Middleware::FirstLevelParseJSON
|
9
9
|
builder.use Faraday::Request::UrlEncoded
|
10
10
|
builder.adapter :test do |stub|
|
11
|
-
stub.get("/users/1") {
|
12
|
-
stub.get("/users/2") {
|
13
|
-
stub.get("/users/3") {
|
14
|
-
stub.put("/users/1") {
|
15
|
-
stub.put("/users/2") {
|
16
|
-
stub.post("/users")
|
11
|
+
stub.get("/users/1") { [200, {}, { id: 1, fullname: "Lindsay Fünke" }.to_json] }
|
12
|
+
stub.get("/users/2") { [200, {}, { id: 2, fullname: "Maeby Fünke" }.to_json] }
|
13
|
+
stub.get("/users/3") { [200, {}, { user_id: 3, fullname: "Maeby Fünke" }.to_json] }
|
14
|
+
stub.put("/users/1") { [200, {}, { id: 1, fullname: "Tobias Fünke" }.to_json] }
|
15
|
+
stub.put("/users/2") { [400, {}, { errors: ["Email cannot be blank"] }.to_json] }
|
16
|
+
stub.post("/users") { [200, {}, { id: 1, fullname: "Tobias Fünke" }.to_json] }
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -28,36 +28,36 @@ describe "Her::Model and ActiveModel::Dirty" do
|
|
28
28
|
context "for existing resource" do
|
29
29
|
let(:user) { Foo::User.find(1) }
|
30
30
|
it "has no changes" do
|
31
|
-
user.changes.
|
32
|
-
user.
|
31
|
+
expect(user.changes).to be_empty
|
32
|
+
expect(user).not_to be_changed
|
33
33
|
end
|
34
34
|
context "with successful save" do
|
35
35
|
it "tracks dirty attributes" do
|
36
36
|
user.fullname = "Tobias Fünke"
|
37
|
-
user.fullname_changed
|
38
|
-
user.email_changed
|
39
|
-
user.
|
37
|
+
expect(user.fullname_changed?).to be_truthy
|
38
|
+
expect(user.email_changed?).to be_falsey
|
39
|
+
expect(user).to be_changed
|
40
40
|
user.save
|
41
|
-
user.
|
41
|
+
expect(user).not_to be_changed
|
42
42
|
end
|
43
43
|
|
44
44
|
it "tracks only changed dirty attributes" do
|
45
45
|
user.fullname = user.fullname
|
46
|
-
user.fullname_changed
|
46
|
+
expect(user.fullname_changed?).to be_falsey
|
47
47
|
end
|
48
48
|
|
49
49
|
it "tracks previous changes" do
|
50
50
|
user.fullname = "Tobias Fünke"
|
51
51
|
user.save
|
52
|
-
user.previous_changes.
|
52
|
+
expect(user.previous_changes).to eq("fullname" => ["Lindsay Fünke", "Tobias Fünke"])
|
53
53
|
end
|
54
54
|
|
55
|
-
it
|
55
|
+
it "tracks dirty attribute for mass assign for dynamic created attributes" do
|
56
56
|
user = Dynamic::User.find(3)
|
57
|
-
user.assign_attributes(:
|
58
|
-
user.fullname_changed
|
59
|
-
user.
|
60
|
-
user.changes.length.
|
57
|
+
user.assign_attributes(fullname: "New Fullname")
|
58
|
+
expect(user.fullname_changed?).to be_truthy
|
59
|
+
expect(user).to be_changed
|
60
|
+
expect(user.changes.length).to eq(1)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -65,27 +65,28 @@ describe "Her::Model and ActiveModel::Dirty" do
|
|
65
65
|
it "tracks dirty attributes" do
|
66
66
|
user = Foo::User.find(2)
|
67
67
|
user.fullname = "Tobias Fünke"
|
68
|
-
user.fullname_changed
|
69
|
-
user.email_changed
|
70
|
-
user.
|
68
|
+
expect(user.fullname_changed?).to be_truthy
|
69
|
+
expect(user.email_changed?).to be_falsey
|
70
|
+
expect(user).to be_changed
|
71
71
|
user.save
|
72
|
-
user.
|
72
|
+
expect(user).to be_changed
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
77
|
context "for new resource" do
|
78
|
-
let(:user) { Foo::User.new(:
|
78
|
+
let(:user) { Foo::User.new(fullname: "Lindsay Fünke") }
|
79
79
|
it "has changes" do
|
80
|
-
user.
|
80
|
+
expect(user).to be_changed
|
81
81
|
end
|
82
82
|
it "tracks dirty attributes" do
|
83
83
|
user.fullname = "Tobias Fünke"
|
84
|
-
user.fullname_changed
|
85
|
-
user.
|
84
|
+
expect(user.fullname_changed?).to be_truthy
|
85
|
+
expect(user).to be_changed
|
86
86
|
user.save
|
87
|
-
user.
|
87
|
+
expect(user).not_to be_changed
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
92
|
+
#
|
data/spec/model/http_spec.rb
CHANGED
@@ -3,13 +3,13 @@ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
|
3
3
|
|
4
4
|
describe Her::Model::HTTP do
|
5
5
|
context "binding a model with an API" do
|
6
|
-
let(:api1) { Her::API.new :
|
7
|
-
let(:api2) { Her::API.new :
|
6
|
+
let(:api1) { Her::API.new url: "https://api1.example.com" }
|
7
|
+
let(:api2) { Her::API.new url: "https://api2.example.com" }
|
8
8
|
|
9
9
|
before do
|
10
10
|
spawn_model("Foo::User")
|
11
11
|
spawn_model("Foo::Comment")
|
12
|
-
Her::API.setup :
|
12
|
+
Her::API.setup url: "https://api.example.com"
|
13
13
|
end
|
14
14
|
|
15
15
|
context "when binding a model to its superclass' her_api" do
|
@@ -19,7 +19,7 @@ describe Her::Model::HTTP do
|
|
19
19
|
Foo::Subclass = Class.new(Foo::Superclass)
|
20
20
|
end
|
21
21
|
|
22
|
-
specify { Foo::Subclass.her_api.
|
22
|
+
specify { expect(Foo::Subclass.her_api).to eq(Foo::Superclass.her_api) }
|
23
23
|
end
|
24
24
|
|
25
25
|
context "when changing her_api without changing the parent class' her_api" do
|
@@ -30,23 +30,23 @@ describe Her::Model::HTTP do
|
|
30
30
|
Foo::Subclass.uses_api api2
|
31
31
|
end
|
32
32
|
|
33
|
-
specify { Foo::Subclass.her_api.
|
33
|
+
specify { expect(Foo::Subclass.her_api).not_to eq(Foo::Superclass.her_api) }
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
context "making HTTP requests" do
|
38
38
|
before do
|
39
|
-
Her::API.setup :
|
39
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
40
40
|
builder.use Her::Middleware::FirstLevelParseJSON
|
41
41
|
builder.use Faraday::Request::UrlEncoded
|
42
42
|
builder.adapter :test do |stub|
|
43
|
-
stub.get("/users") {
|
44
|
-
stub.get("/users/1") {
|
43
|
+
stub.get("/users") { [200, {}, [{ id: 1 }].to_json] }
|
44
|
+
stub.get("/users/1") { [200, {}, { id: 1 }.to_json] }
|
45
45
|
stub.get("/users/popular") do |env|
|
46
46
|
if env[:params]["page"] == "2"
|
47
|
-
[200, {}, [{ :
|
47
|
+
[200, {}, [{ id: 3 }, { id: 4 }].to_json]
|
48
48
|
else
|
49
|
-
[200, {}, [{ :
|
49
|
+
[200, {}, [{ id: 1 }, { id: 2 }].to_json]
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
@@ -57,61 +57,85 @@ describe Her::Model::HTTP do
|
|
57
57
|
|
58
58
|
describe :get do
|
59
59
|
subject { Foo::User.get(:popular) }
|
60
|
-
|
61
|
-
|
60
|
+
|
61
|
+
describe "#length" do
|
62
|
+
subject { super().length }
|
63
|
+
it { is_expected.to eq(2) }
|
64
|
+
end
|
65
|
+
specify { expect(subject.first.id).to eq(1) }
|
62
66
|
end
|
63
67
|
|
64
68
|
describe :get_raw do
|
65
69
|
context "with a block" do
|
66
70
|
specify do
|
67
|
-
Foo::User.get_raw("/users") do |parsed_data,
|
68
|
-
parsed_data[:data].
|
71
|
+
Foo::User.get_raw("/users") do |parsed_data, _response|
|
72
|
+
expect(parsed_data[:data]).to eq([{ id: 1 }])
|
69
73
|
end
|
70
74
|
end
|
71
75
|
end
|
72
76
|
|
73
77
|
context "with a return value" do
|
74
78
|
subject { Foo::User.get_raw("/users") }
|
75
|
-
specify { subject[:parsed_data][:data].
|
79
|
+
specify { expect(subject[:parsed_data][:data]).to eq([{ id: 1 }]) }
|
76
80
|
end
|
77
81
|
end
|
78
82
|
|
79
83
|
describe :get_collection do
|
80
84
|
context "with a String path" do
|
81
85
|
subject { Foo::User.get_collection("/users/popular") }
|
82
|
-
|
83
|
-
|
86
|
+
|
87
|
+
describe "#length" do
|
88
|
+
subject { super().length }
|
89
|
+
it { is_expected.to eq(2) }
|
90
|
+
end
|
91
|
+
specify { expect(subject.first.id).to eq(1) }
|
84
92
|
end
|
85
93
|
|
86
94
|
context "with a Symbol" do
|
87
95
|
subject { Foo::User.get_collection(:popular) }
|
88
|
-
|
89
|
-
|
96
|
+
|
97
|
+
describe "#length" do
|
98
|
+
subject { super().length }
|
99
|
+
it { is_expected.to eq(2) }
|
100
|
+
end
|
101
|
+
specify { expect(subject.first.id).to eq(1) }
|
90
102
|
end
|
91
103
|
|
92
104
|
context "with extra parameters" do
|
93
|
-
subject { Foo::User.get_collection(:popular, :
|
94
|
-
|
95
|
-
|
105
|
+
subject { Foo::User.get_collection(:popular, page: 2) }
|
106
|
+
|
107
|
+
describe "#length" do
|
108
|
+
subject { super().length }
|
109
|
+
it { is_expected.to eq(2) }
|
110
|
+
end
|
111
|
+
specify { expect(subject.first.id).to eq(3) }
|
96
112
|
end
|
97
113
|
end
|
98
114
|
|
99
115
|
describe :get_resource do
|
100
116
|
context "with a String path" do
|
101
117
|
subject { Foo::User.get_resource("/users/1") }
|
102
|
-
|
118
|
+
|
119
|
+
describe "#id" do
|
120
|
+
subject { super().id }
|
121
|
+
it { is_expected.to eq(1) }
|
122
|
+
end
|
103
123
|
end
|
104
124
|
|
105
125
|
context "with a Symbol" do
|
106
126
|
subject { Foo::User.get_resource(:"1") }
|
107
|
-
|
127
|
+
|
128
|
+
describe "#id" do
|
129
|
+
subject { super().id }
|
130
|
+
it { is_expected.to eq(1) }
|
131
|
+
end
|
108
132
|
end
|
109
133
|
end
|
110
134
|
|
111
135
|
describe :get_raw do
|
112
136
|
specify do
|
113
|
-
Foo::User.get_raw(:popular) do |parsed_data,
|
114
|
-
parsed_data[:data].
|
137
|
+
Foo::User.get_raw(:popular) do |parsed_data, _response|
|
138
|
+
expect(parsed_data[:data]).to eq([{ id: 1 }, { id: 2 }])
|
115
139
|
end
|
116
140
|
end
|
117
141
|
end
|
@@ -119,11 +143,11 @@ describe Her::Model::HTTP do
|
|
119
143
|
|
120
144
|
context "setting custom HTTP requests" do
|
121
145
|
before do
|
122
|
-
Her::API.setup :
|
146
|
+
Her::API.setup url: "https://api.example.com" do |connection|
|
123
147
|
connection.use Her::Middleware::FirstLevelParseJSON
|
124
148
|
connection.adapter :test do |stub|
|
125
|
-
stub.get("/users/popular") {
|
126
|
-
stub.post("/users/from_default") {
|
149
|
+
stub.get("/users/popular") { [200, {}, [{ id: 1 }, { id: 2 }].to_json] }
|
150
|
+
stub.post("/users/from_default") { [200, {}, { id: 4 }.to_json] }
|
127
151
|
end
|
128
152
|
end
|
129
153
|
|
@@ -135,23 +159,31 @@ describe Her::Model::HTTP do
|
|
135
159
|
describe :custom_get do
|
136
160
|
context "without cache" do
|
137
161
|
before { Foo::User.custom_get :popular, :recent }
|
138
|
-
it {
|
139
|
-
it {
|
162
|
+
it { is_expected.to respond_to(:popular) }
|
163
|
+
it { is_expected.to respond_to(:recent) }
|
140
164
|
|
141
165
|
context "making the HTTP request" do
|
142
166
|
subject { Foo::User.popular }
|
143
|
-
|
167
|
+
|
168
|
+
describe "#length" do
|
169
|
+
subject { super().length }
|
170
|
+
it { is_expected.to eq(2) }
|
171
|
+
end
|
144
172
|
end
|
145
173
|
end
|
146
174
|
end
|
147
175
|
|
148
176
|
describe :custom_post do
|
149
177
|
before { Foo::User.custom_post :from_default }
|
150
|
-
it {
|
178
|
+
it { is_expected.to respond_to(:from_default) }
|
151
179
|
|
152
180
|
context "making the HTTP request" do
|
153
|
-
subject { Foo::User.from_default(:
|
154
|
-
|
181
|
+
subject { Foo::User.from_default(name: "Tobias Fünke") }
|
182
|
+
|
183
|
+
describe "#id" do
|
184
|
+
subject { super().id }
|
185
|
+
it { is_expected.to eq(4) }
|
186
|
+
end
|
155
187
|
end
|
156
188
|
end
|
157
189
|
end
|
@@ -4,15 +4,15 @@ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
|
4
4
|
describe Her::Model::Introspection do
|
5
5
|
context "introspecting a resource" do
|
6
6
|
before do
|
7
|
-
Her::API.setup :
|
7
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
8
8
|
builder.use Her::Middleware::FirstLevelParseJSON
|
9
9
|
builder.use Faraday::Request::UrlEncoded
|
10
10
|
builder.adapter :test do |stub|
|
11
|
-
stub.post("/users") {
|
12
|
-
stub.get("/users/1") {
|
13
|
-
stub.put("/users/1") {
|
14
|
-
stub.delete("/users/1") {
|
15
|
-
stub.get("/projects/1/comments") {
|
11
|
+
stub.post("/users") { [200, {}, { id: 1, name: "Tobias Funke" }.to_json] }
|
12
|
+
stub.get("/users/1") { [200, {}, { id: 1, name: "Tobias Funke" }.to_json] }
|
13
|
+
stub.put("/users/1") { [200, {}, { id: 1, name: "Tobias Funke" }.to_json] }
|
14
|
+
stub.delete("/users/1") { [200, {}, { id: 1, name: "Tobias Funke" }.to_json] }
|
15
|
+
stub.get("/projects/1/comments") { [200, {}, [{ id: 1, body: "Hello!" }].to_json] }
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -25,33 +25,37 @@ describe Her::Model::Introspection do
|
|
25
25
|
describe "#inspect" do
|
26
26
|
it "outputs resource attributes for an existing resource" do
|
27
27
|
@user = Foo::User.find(1)
|
28
|
-
["#<Foo::User(users/1) name=\"Tobias Funke\" id=1>", "#<Foo::User(users/1) id=1 name=\"Tobias Funke\">"].
|
28
|
+
expect(["#<Foo::User(users/1) name=\"Tobias Funke\" id=1>", "#<Foo::User(users/1) id=1 name=\"Tobias Funke\">"]).to include(@user.inspect)
|
29
29
|
end
|
30
30
|
|
31
31
|
it "outputs resource attributes for an not-saved-yet resource" do
|
32
|
-
@user = Foo::User.new(:
|
33
|
-
@user.inspect.
|
32
|
+
@user = Foo::User.new(name: "Tobias Funke")
|
33
|
+
expect(@user.inspect).to eq("#<Foo::User(users) name=\"Tobias Funke\">")
|
34
34
|
end
|
35
35
|
|
36
36
|
it "outputs resource attributes using getters" do
|
37
|
-
@user = Foo::User.new(:
|
38
|
-
@user.instance_eval
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
@user = Foo::User.new(name: "Tobias Funke", password: "Funke")
|
38
|
+
@user.instance_eval do
|
39
|
+
def password
|
40
|
+
"filtered"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
expect(@user.inspect).to include("name=\"Tobias Funke\"")
|
44
|
+
expect(@user.inspect).to include("password=\"filtered\"")
|
45
|
+
expect(@user.inspect).not_to include("password=\"Funke\"")
|
42
46
|
end
|
43
47
|
|
44
48
|
it "support dash on attribute" do
|
45
49
|
@user = Foo::User.new(:'life-span' => "3 years")
|
46
|
-
@user.inspect.
|
50
|
+
expect(@user.inspect).to include("life-span=\"3 years\"")
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
50
54
|
describe "#inspect with errors in resource path" do
|
51
55
|
it "prints the resource path as “unknown”" do
|
52
|
-
@comment = Foo::Comment.where(:
|
53
|
-
path =
|
54
|
-
["#<Foo::Comment(#{path}) body=\"Hello!\" id=1>", "#<Foo::Comment(#{path}) id=1 body=\"Hello!\">"].
|
56
|
+
@comment = Foo::Comment.where(project_id: 1).first
|
57
|
+
path = "<unknown path, missing `project_id`>"
|
58
|
+
expect(["#<Foo::Comment(#{path}) body=\"Hello!\" id=1>", "#<Foo::Comment(#{path}) id=1 body=\"Hello!\">"]).to include(@comment.inspect)
|
55
59
|
end
|
56
60
|
end
|
57
61
|
end
|
@@ -66,10 +70,10 @@ describe Her::Model::Introspection do
|
|
66
70
|
end
|
67
71
|
|
68
72
|
it "returns a sibling class, if found" do
|
69
|
-
Foo::User.her_nearby_class("AccessRecord").
|
70
|
-
AccessRecord.her_nearby_class("Log").
|
71
|
-
Foo::User.her_nearby_class("Log").
|
72
|
-
Foo::User.her_nearby_class("X").
|
73
|
+
expect(Foo::User.her_nearby_class("AccessRecord")).to eq(Foo::AccessRecord)
|
74
|
+
expect(AccessRecord.her_nearby_class("Log")).to eq(Log)
|
75
|
+
expect(Foo::User.her_nearby_class("Log")).to eq(Log)
|
76
|
+
expect(Foo::User.her_nearby_class("X")).to be_nil
|
73
77
|
end
|
74
78
|
end
|
75
79
|
end
|
@@ -4,40 +4,40 @@ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
|
4
4
|
describe Her::Model::NestedAttributes do
|
5
5
|
context "with a belongs_to association" do
|
6
6
|
before do
|
7
|
-
Her::API.setup :
|
7
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
8
8
|
builder.use Her::Middleware::FirstLevelParseJSON
|
9
9
|
builder.use Faraday::Request::UrlEncoded
|
10
10
|
end
|
11
11
|
|
12
12
|
spawn_model "Foo::User" do
|
13
|
-
belongs_to :company, :
|
13
|
+
belongs_to :company, path: "/organizations/:id", foreign_key: :organization_id
|
14
14
|
accepts_nested_attributes_for :company
|
15
15
|
end
|
16
16
|
|
17
17
|
spawn_model "Foo::Company"
|
18
18
|
|
19
|
-
@user_with_data_through_nested_attributes = Foo::User.new :
|
19
|
+
@user_with_data_through_nested_attributes = Foo::User.new name: "Test", company_attributes: { name: "Example Company" }
|
20
20
|
end
|
21
21
|
|
22
22
|
context "when child does not yet exist" do
|
23
23
|
it "creates an instance of the associated class" do
|
24
|
-
@user_with_data_through_nested_attributes.company.
|
25
|
-
@user_with_data_through_nested_attributes.company.name.
|
24
|
+
expect(@user_with_data_through_nested_attributes.company).to be_a(Foo::Company)
|
25
|
+
expect(@user_with_data_through_nested_attributes.company.name).to eq("Example Company")
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
context "when child does exist" do
|
30
30
|
it "updates the attributes of the associated object" do
|
31
|
-
@user_with_data_through_nested_attributes.company_attributes = { :
|
32
|
-
@user_with_data_through_nested_attributes.company.
|
33
|
-
@user_with_data_through_nested_attributes.company.name.
|
31
|
+
@user_with_data_through_nested_attributes.company_attributes = { name: "Fünke's Company" }
|
32
|
+
expect(@user_with_data_through_nested_attributes.company).to be_a(Foo::Company)
|
33
|
+
expect(@user_with_data_through_nested_attributes.company.name).to eq("Fünke's Company")
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
context "with a has_one association" do
|
39
39
|
before do
|
40
|
-
Her::API.setup :
|
40
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
41
41
|
builder.use Her::Middleware::FirstLevelParseJSON
|
42
42
|
builder.use Faraday::Request::UrlEncoded
|
43
43
|
end
|
@@ -49,28 +49,28 @@ describe Her::Model::NestedAttributes do
|
|
49
49
|
|
50
50
|
spawn_model "Foo::Pet"
|
51
51
|
|
52
|
-
@user_with_data_through_nested_attributes = Foo::User.new :
|
52
|
+
@user_with_data_through_nested_attributes = Foo::User.new name: "Test", pet_attributes: { name: "Hasi" }
|
53
53
|
end
|
54
54
|
|
55
55
|
context "when child does not yet exist" do
|
56
56
|
it "creates an instance of the associated class" do
|
57
|
-
@user_with_data_through_nested_attributes.pet.
|
58
|
-
@user_with_data_through_nested_attributes.pet.name.
|
57
|
+
expect(@user_with_data_through_nested_attributes.pet).to be_a(Foo::Pet)
|
58
|
+
expect(@user_with_data_through_nested_attributes.pet.name).to eq("Hasi")
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
62
|
context "when child does exist" do
|
63
63
|
it "updates the attributes of the associated object" do
|
64
|
-
@user_with_data_through_nested_attributes.pet_attributes = { :
|
65
|
-
@user_with_data_through_nested_attributes.pet.
|
66
|
-
@user_with_data_through_nested_attributes.pet.name.
|
64
|
+
@user_with_data_through_nested_attributes.pet_attributes = { name: "Rodriguez" }
|
65
|
+
expect(@user_with_data_through_nested_attributes.pet).to be_a(Foo::Pet)
|
66
|
+
expect(@user_with_data_through_nested_attributes.pet.name).to eq("Rodriguez")
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
context "with a has_many association" do
|
72
72
|
before do
|
73
|
-
Her::API.setup :
|
73
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
74
74
|
builder.use Her::Middleware::FirstLevelParseJSON
|
75
75
|
builder.use Faraday::Request::UrlEncoded
|
76
76
|
end
|
@@ -82,23 +82,23 @@ describe Her::Model::NestedAttributes do
|
|
82
82
|
|
83
83
|
spawn_model "Foo::Pet"
|
84
84
|
|
85
|
-
@user_with_data_through_nested_attributes = Foo::User.new :
|
85
|
+
@user_with_data_through_nested_attributes = Foo::User.new name: "Test", pets_attributes: [{ name: "Hasi" }, { name: "Rodriguez" }]
|
86
86
|
end
|
87
87
|
|
88
88
|
context "when children do not yet exist" do
|
89
89
|
it "creates an instance of the associated class" do
|
90
|
-
@user_with_data_through_nested_attributes.pets.length.
|
91
|
-
@user_with_data_through_nested_attributes.pets[0].
|
92
|
-
@user_with_data_through_nested_attributes.pets[1].
|
93
|
-
@user_with_data_through_nested_attributes.pets[0].name.
|
94
|
-
@user_with_data_through_nested_attributes.pets[1].name.
|
90
|
+
expect(@user_with_data_through_nested_attributes.pets.length).to eq(2)
|
91
|
+
expect(@user_with_data_through_nested_attributes.pets[0]).to be_a(Foo::Pet)
|
92
|
+
expect(@user_with_data_through_nested_attributes.pets[1]).to be_a(Foo::Pet)
|
93
|
+
expect(@user_with_data_through_nested_attributes.pets[0].name).to eq("Hasi")
|
94
|
+
expect(@user_with_data_through_nested_attributes.pets[1].name).to eq("Rodriguez")
|
95
95
|
end
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
99
|
context "with a has_many association as a Hash" do
|
100
100
|
before do
|
101
|
-
Her::API.setup :
|
101
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
102
102
|
builder.use Her::Middleware::FirstLevelParseJSON
|
103
103
|
builder.use Faraday::Request::UrlEncoded
|
104
104
|
end
|
@@ -110,25 +110,25 @@ describe Her::Model::NestedAttributes do
|
|
110
110
|
|
111
111
|
spawn_model "Foo::Pet"
|
112
112
|
|
113
|
-
@user_with_data_through_nested_attributes_as_hash = Foo::User.new :
|
113
|
+
@user_with_data_through_nested_attributes_as_hash = Foo::User.new name: "Test", pets_attributes: { "0" => { name: "Hasi" }, "1" => { name: "Rodriguez" } }
|
114
114
|
end
|
115
115
|
|
116
116
|
context "when children do not yet exist" do
|
117
117
|
it "creates an instance of the associated class" do
|
118
|
-
@user_with_data_through_nested_attributes_as_hash.pets.length.
|
119
|
-
@user_with_data_through_nested_attributes_as_hash.pets[0].
|
120
|
-
@user_with_data_through_nested_attributes_as_hash.pets[1].
|
121
|
-
@user_with_data_through_nested_attributes_as_hash.pets[0].name.
|
122
|
-
@user_with_data_through_nested_attributes_as_hash.pets[1].name.
|
118
|
+
expect(@user_with_data_through_nested_attributes_as_hash.pets.length).to eq(2)
|
119
|
+
expect(@user_with_data_through_nested_attributes_as_hash.pets[0]).to be_a(Foo::Pet)
|
120
|
+
expect(@user_with_data_through_nested_attributes_as_hash.pets[1]).to be_a(Foo::Pet)
|
121
|
+
expect(@user_with_data_through_nested_attributes_as_hash.pets[0].name).to eq("Hasi")
|
122
|
+
expect(@user_with_data_through_nested_attributes_as_hash.pets[1].name).to eq("Rodriguez")
|
123
123
|
end
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
127
|
context "with an unknown association" do
|
128
128
|
it "raises an error" do
|
129
|
-
expect
|
129
|
+
expect do
|
130
130
|
spawn_model("Foo::User") { accepts_nested_attributes_for :company }
|
131
|
-
|
131
|
+
end.to raise_error(Her::Errors::AssociationUnknownError, "Unknown association name :company")
|
132
132
|
end
|
133
133
|
end
|
134
134
|
end
|