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
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
|
3
3
|
|
4
4
|
describe "Her::Model and ActiveModel::Callbacks" do
|
5
5
|
before do
|
6
|
-
Her::API.setup :
|
6
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
7
7
|
builder.use Her::Middleware::FirstLevelParseJSON
|
8
8
|
end
|
9
9
|
|
@@ -11,11 +11,11 @@ describe "Her::Model and ActiveModel::Callbacks" do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
context :before_save do
|
14
|
-
subject { Foo::User.create(:
|
14
|
+
subject { Foo::User.create(name: "Tobias Funke") }
|
15
15
|
before do
|
16
16
|
Her::API.default_api.connection.adapter :test do |stub|
|
17
|
-
stub.post("/users") { |env| [200, {}, { :
|
18
|
-
stub.put("/users/1") { |env| [200, {}, { :
|
17
|
+
stub.post("/users") { |env| [200, {}, { id: 1, name: env[:body][:name] }.to_json] }
|
18
|
+
stub.put("/users/1") { |env| [200, {}, { id: 1, name: env[:body][:name] }.to_json] }
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -23,21 +23,29 @@ describe "Her::Model and ActiveModel::Callbacks" do
|
|
23
23
|
before do
|
24
24
|
class Foo::User
|
25
25
|
before_save :alter_name
|
26
|
-
def alter_name
|
26
|
+
def alter_name
|
27
|
+
name.upcase!
|
28
|
+
end
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
|
32
|
+
describe "#name" do
|
33
|
+
subject { super().name }
|
34
|
+
it { is_expected.to eq("TOBIAS FUNKE") }
|
35
|
+
end
|
31
36
|
end
|
32
37
|
|
33
38
|
context "when using a block callback" do
|
34
39
|
before do
|
35
40
|
class Foo::User
|
36
|
-
before_save
|
41
|
+
before_save -> { name.upcase! }
|
37
42
|
end
|
38
43
|
end
|
39
44
|
|
40
|
-
|
45
|
+
describe "#name" do
|
46
|
+
subject { super().name }
|
47
|
+
it { is_expected.to eq("TOBIAS FUNKE") }
|
48
|
+
end
|
41
49
|
end
|
42
50
|
|
43
51
|
context "when changing a value of an existing resource in a callback" do
|
@@ -51,18 +59,18 @@ describe "Her::Model and ActiveModel::Callbacks" do
|
|
51
59
|
end
|
52
60
|
|
53
61
|
it "should call the server with the canged value" do
|
54
|
-
subject.name.
|
62
|
+
expect(subject.name).to eq("Tobias Funke")
|
55
63
|
subject.save
|
56
|
-
subject.name.
|
64
|
+
expect(subject.name).to eq("Lumberjack")
|
57
65
|
end
|
58
66
|
end
|
59
67
|
end
|
60
68
|
|
61
69
|
context :before_create do
|
62
|
-
subject { Foo::User.create(:
|
70
|
+
subject { Foo::User.create(name: "Tobias Funke") }
|
63
71
|
before do
|
64
72
|
Her::API.default_api.connection.adapter :test do |stub|
|
65
|
-
stub.post("/users") { |env| [200, {}, { :
|
73
|
+
stub.post("/users") { |env| [200, {}, { id: 1, name: env[:body][:name] }.to_json] }
|
66
74
|
end
|
67
75
|
end
|
68
76
|
|
@@ -70,21 +78,29 @@ describe "Her::Model and ActiveModel::Callbacks" do
|
|
70
78
|
before do
|
71
79
|
class Foo::User
|
72
80
|
before_create :alter_name
|
73
|
-
def alter_name
|
81
|
+
def alter_name
|
82
|
+
name.upcase!
|
83
|
+
end
|
74
84
|
end
|
75
85
|
end
|
76
86
|
|
77
|
-
|
87
|
+
describe "#name" do
|
88
|
+
subject { super().name }
|
89
|
+
it { is_expected.to eq("TOBIAS FUNKE") }
|
90
|
+
end
|
78
91
|
end
|
79
92
|
|
80
93
|
context "when using a block callback" do
|
81
94
|
before do
|
82
95
|
class Foo::User
|
83
|
-
before_create
|
96
|
+
before_create -> { name.upcase! }
|
84
97
|
end
|
85
98
|
end
|
86
99
|
|
87
|
-
|
100
|
+
describe "#name" do
|
101
|
+
subject { super().name }
|
102
|
+
it { is_expected.to eq("TOBIAS FUNKE") }
|
103
|
+
end
|
88
104
|
end
|
89
105
|
end
|
90
106
|
|
@@ -92,7 +108,7 @@ describe "Her::Model and ActiveModel::Callbacks" do
|
|
92
108
|
subject { Foo::User.find(1) }
|
93
109
|
before do
|
94
110
|
Her::API.default_api.connection.adapter :test do |stub|
|
95
|
-
stub.get("/users/1") {
|
111
|
+
stub.get("/users/1") { [200, {}, { id: 1, name: "Tobias Funke" }.to_json] }
|
96
112
|
end
|
97
113
|
end
|
98
114
|
|
@@ -100,46 +116,62 @@ describe "Her::Model and ActiveModel::Callbacks" do
|
|
100
116
|
before do
|
101
117
|
class Foo::User
|
102
118
|
after_find :alter_name
|
103
|
-
def alter_name
|
119
|
+
def alter_name
|
120
|
+
name.upcase!
|
121
|
+
end
|
104
122
|
end
|
105
123
|
end
|
106
124
|
|
107
|
-
|
125
|
+
describe "#name" do
|
126
|
+
subject { super().name }
|
127
|
+
it { is_expected.to eq("TOBIAS FUNKE") }
|
128
|
+
end
|
108
129
|
end
|
109
130
|
|
110
131
|
context "when using a block callback" do
|
111
132
|
before do
|
112
133
|
class Foo::User
|
113
|
-
after_find
|
134
|
+
after_find -> { name.upcase! }
|
114
135
|
end
|
115
136
|
end
|
116
137
|
|
117
|
-
|
138
|
+
describe "#name" do
|
139
|
+
subject { super().name }
|
140
|
+
it { is_expected.to eq("TOBIAS FUNKE") }
|
141
|
+
end
|
118
142
|
end
|
119
143
|
end
|
120
144
|
|
121
145
|
context :after_initialize do
|
122
|
-
subject { Foo::User.new(:
|
146
|
+
subject { Foo::User.new(name: "Tobias Funke") }
|
123
147
|
|
124
148
|
context "when using a symbol callback" do
|
125
149
|
before do
|
126
150
|
class Foo::User
|
127
151
|
after_initialize :alter_name
|
128
|
-
def alter_name
|
152
|
+
def alter_name
|
153
|
+
name.upcase!
|
154
|
+
end
|
129
155
|
end
|
130
156
|
end
|
131
157
|
|
132
|
-
|
158
|
+
describe "#name" do
|
159
|
+
subject { super().name }
|
160
|
+
it { is_expected.to eq("TOBIAS FUNKE") }
|
161
|
+
end
|
133
162
|
end
|
134
163
|
|
135
164
|
context "when using a block callback" do
|
136
165
|
before do
|
137
166
|
class Foo::User
|
138
|
-
after_initialize
|
167
|
+
after_initialize -> { name.upcase! }
|
139
168
|
end
|
140
169
|
end
|
141
170
|
|
142
|
-
|
171
|
+
describe "#name" do
|
172
|
+
subject { super().name }
|
173
|
+
it { is_expected.to eq("TOBIAS FUNKE") }
|
174
|
+
end
|
143
175
|
end
|
144
176
|
end
|
145
177
|
end
|
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")
|
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
|