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
@@ -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
|
data/spec/model/orm_spec.rb
CHANGED
@@ -5,14 +5,14 @@ describe Her::Model::ORM do
|
|
5
5
|
context "mapping data to Ruby objects" do
|
6
6
|
before do
|
7
7
|
api = Her::API.new
|
8
|
-
api.setup :
|
8
|
+
api.setup url: "https://api.example.com" do |builder|
|
9
9
|
builder.use Her::Middleware::FirstLevelParseJSON
|
10
10
|
builder.use Faraday::Request::UrlEncoded
|
11
11
|
builder.adapter :test do |stub|
|
12
|
-
stub.get("/users/1") {
|
13
|
-
stub.get("/users") {
|
14
|
-
stub.get("/admin_users") {
|
15
|
-
stub.get("/admin_users/1") {
|
12
|
+
stub.get("/users/1") { [200, {}, { id: 1, name: "Tobias Fünke" }.to_json] }
|
13
|
+
stub.get("/users") { [200, {}, [{ id: 1, name: "Tobias Fünke" }, { id: 2, name: "Lindsay Fünke" }].to_json] }
|
14
|
+
stub.get("/admin_users") { [200, {}, [{ admin_id: 1, name: "Tobias Fünke" }, { admin_id: 2, name: "Lindsay Fünke" }].to_json] }
|
15
|
+
stub.get("/admin_users/1") { [200, {}, { admin_id: 1, name: "Tobias Fünke" }.to_json] }
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -28,53 +28,55 @@ describe Her::Model::ORM do
|
|
28
28
|
|
29
29
|
it "maps a single resource to a Ruby object" do
|
30
30
|
@user = Foo::User.find(1)
|
31
|
-
@user.id.
|
32
|
-
@user.name.
|
31
|
+
expect(@user.id).to eq(1)
|
32
|
+
expect(@user.name).to eq("Tobias Fünke")
|
33
33
|
|
34
34
|
@admin = Foo::AdminUser.find(1)
|
35
|
-
@admin.id.
|
36
|
-
@admin.name.
|
35
|
+
expect(@admin.id).to eq(1)
|
36
|
+
expect(@admin.name).to eq("Tobias Fünke")
|
37
37
|
end
|
38
38
|
|
39
39
|
it "maps a collection of resources to an array of Ruby objects" do
|
40
40
|
@users = Foo::User.all
|
41
|
-
@users.length.
|
42
|
-
@users.first.name.
|
41
|
+
expect(@users.length).to eq(2)
|
42
|
+
expect(@users.first.name).to eq("Tobias Fünke")
|
43
43
|
|
44
44
|
@users = Foo::AdminUser.all
|
45
|
-
@users.length.
|
46
|
-
@users.first.name.
|
45
|
+
expect(@users.length).to eq(2)
|
46
|
+
expect(@users.first.name).to eq("Tobias Fünke")
|
47
47
|
end
|
48
48
|
|
49
49
|
it "handles new resource" do
|
50
|
-
@new_user = Foo::User.new(:
|
51
|
-
@new_user.new
|
52
|
-
@new_user.new_record
|
53
|
-
@new_user.fullname.
|
50
|
+
@new_user = Foo::User.new(fullname: "Tobias Fünke")
|
51
|
+
expect(@new_user.new?).to be_truthy
|
52
|
+
expect(@new_user.new_record?).to be_truthy
|
53
|
+
expect(@new_user.fullname).to eq("Tobias Fünke")
|
54
54
|
|
55
55
|
@existing_user = Foo::User.find(1)
|
56
|
-
@existing_user.new
|
57
|
-
@existing_user.new_record
|
56
|
+
expect(@existing_user.new?).to be_falsey
|
57
|
+
expect(@existing_user.new_record?).to be_falsey
|
58
58
|
end
|
59
59
|
|
60
|
-
it
|
61
|
-
@new_user = Foo::AdminUser.new(:
|
62
|
-
@new_user.
|
60
|
+
it "handles new resource with custom primary key" do
|
61
|
+
@new_user = Foo::AdminUser.new(fullname: "Lindsay Fünke", id: -1)
|
62
|
+
expect(@new_user).to be_new
|
63
63
|
|
64
64
|
@existing_user = Foo::AdminUser.find(1)
|
65
|
-
@existing_user.
|
65
|
+
expect(@existing_user).not_to be_new
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
context "mapping data, metadata and error data to Ruby objects" do
|
70
70
|
before do
|
71
71
|
api = Her::API.new
|
72
|
-
api.setup :
|
72
|
+
api.setup url: "https://api.example.com" do |builder|
|
73
73
|
builder.use Her::Middleware::SecondLevelParseJSON
|
74
74
|
builder.use Faraday::Request::UrlEncoded
|
75
75
|
builder.adapter :test do |stub|
|
76
|
+
stub.get("/users") { [200, {}, { data: [{ id: 1, name: "Tobias Fünke" }, { id: 2, name: "Lindsay Fünke" }], metadata: { total_pages: 10, next_page: 2 }, errors: %w(Oh My God) }.to_json] }
|
76
77
|
stub.get("/users") { |env| [200, {}, { :data => [{ :id => 1, :name => "Tobias Fünke" }, { :id => 2, :name => "Lindsay Fünke" }], :metadata => { :total_pages => 10, :next_page => 2 }, :errors => ["Oh", "My", "God"] }.to_json] }
|
77
78
|
stub.post("/users") { |env| [200, {}, { :data => { :name => "George Michael Bluth" }, :metadata => { :foo => "bar" }, :errors => ["Yes", "Sir"] }.to_json] }
|
79
|
+
stub.delete("/users/1") { |env| [200, {}, { :data => { :id => 1 }, :metadata => { :foo => "bar" }, :errors => ["Yes", "Sir"] }.to_json] }
|
78
80
|
end
|
79
81
|
end
|
80
82
|
|
@@ -85,21 +87,31 @@ describe Her::Model::ORM do
|
|
85
87
|
|
86
88
|
it "handles metadata on a collection" do
|
87
89
|
@users = User.all
|
88
|
-
@users.metadata[:total_pages].
|
90
|
+
expect(@users.metadata[:total_pages]).to eq(10)
|
89
91
|
end
|
90
92
|
|
91
93
|
it "handles error data on a collection" do
|
92
94
|
@users = User.all
|
93
|
-
@users.errors.length.
|
95
|
+
expect(@users.errors.length).to eq(3)
|
94
96
|
end
|
95
97
|
|
96
98
|
it "handles metadata on a resource" do
|
97
|
-
@user = User.create(:
|
98
|
-
@user.metadata[:foo].
|
99
|
+
@user = User.create(name: "George Michael Bluth")
|
100
|
+
expect(@user.metadata[:foo]).to eq("bar")
|
99
101
|
end
|
100
102
|
|
101
103
|
it "handles error data on a resource" do
|
102
|
-
@user = User.create(:
|
104
|
+
@user = User.create(name: "George Michael Bluth")
|
105
|
+
expect(@user.response_errors).to eq(%w(Yes Sir))
|
106
|
+
end
|
107
|
+
|
108
|
+
it "handles metadata on a destroyed resource" do
|
109
|
+
@user = User.destroy_existing(1)
|
110
|
+
@user.metadata[:foo].should == "bar"
|
111
|
+
end
|
112
|
+
|
113
|
+
it "handles error data on a destroyed resource" do
|
114
|
+
@user = User.destroy_existing(1)
|
103
115
|
@user.response_errors.should == ["Yes", "Sir"]
|
104
116
|
end
|
105
117
|
end
|
@@ -107,12 +119,12 @@ describe Her::Model::ORM do
|
|
107
119
|
context "mapping data, metadata and error data in string keys to Ruby objects" do
|
108
120
|
before do
|
109
121
|
api = Her::API.new
|
110
|
-
api.setup :
|
122
|
+
api.setup url: "https://api.example.com" do |builder|
|
111
123
|
builder.use Her::Middleware::SecondLevelParseJSON
|
112
124
|
builder.use Faraday::Request::UrlEncoded
|
113
125
|
builder.adapter :test do |stub|
|
114
|
-
stub.get("/users") {
|
115
|
-
stub.post("/users") {
|
126
|
+
stub.get("/users") { [200, {}, { data: [{ id: 1, name: "Tobias Fünke" }, { id: 2, name: "Lindsay Fünke" }], metadata: { total_pages: 10, next_page: 2 }, errors: %w(Oh My God) }.to_json] }
|
127
|
+
stub.post("/users") { [200, {}, { data: { name: "George Michael Bluth" }, metadata: { foo: "bar" }, errors: %w(Yes Sir) }.to_json] }
|
116
128
|
end
|
117
129
|
end
|
118
130
|
|
@@ -123,34 +135,34 @@ describe Her::Model::ORM do
|
|
123
135
|
|
124
136
|
it "handles metadata on a collection" do
|
125
137
|
@users = User.all
|
126
|
-
@users.metadata[:total_pages].
|
138
|
+
expect(@users.metadata[:total_pages]).to eq(10)
|
127
139
|
end
|
128
140
|
|
129
141
|
it "handles error data on a collection" do
|
130
142
|
@users = User.all
|
131
|
-
@users.errors.length.
|
143
|
+
expect(@users.errors.length).to eq(3)
|
132
144
|
end
|
133
145
|
|
134
146
|
it "handles metadata on a resource" do
|
135
|
-
@user = User.create(:
|
136
|
-
@user.metadata[:foo].
|
147
|
+
@user = User.create(name: "George Michael Bluth")
|
148
|
+
expect(@user.metadata[:foo]).to eq("bar")
|
137
149
|
end
|
138
150
|
|
139
151
|
it "handles error data on a resource" do
|
140
|
-
@user = User.create(:
|
141
|
-
@user.response_errors.
|
152
|
+
@user = User.create(name: "George Michael Bluth")
|
153
|
+
expect(@user.response_errors).to eq(%w(Yes Sir))
|
142
154
|
end
|
143
155
|
end
|
144
156
|
|
145
157
|
context "defining custom getters and setters" do
|
146
158
|
before do
|
147
159
|
api = Her::API.new
|
148
|
-
api.setup :
|
160
|
+
api.setup url: "https://api.example.com" do |builder|
|
149
161
|
builder.use Her::Middleware::FirstLevelParseJSON
|
150
162
|
builder.use Faraday::Request::UrlEncoded
|
151
163
|
builder.adapter :test do |stub|
|
152
|
-
stub.get("/users/1") {
|
153
|
-
stub.get("/users/2") {
|
164
|
+
stub.get("/users/1") { [200, {}, { id: 1, friends: %w(Maeby GOB Anne) }.to_json] }
|
165
|
+
stub.get("/users/2") { [200, {}, { id: 1 }.to_json] }
|
154
166
|
end
|
155
167
|
end
|
156
168
|
|
@@ -159,7 +171,7 @@ describe Her::Model::ORM do
|
|
159
171
|
belongs_to :organization
|
160
172
|
|
161
173
|
def friends=(val)
|
162
|
-
val = val.
|
174
|
+
val = val.delete("\r").split("\n").map { |friend| friend.gsub(/^\s*\*\s*/, "") } if val && val.is_a?(String)
|
163
175
|
@attributes[:friends] = val
|
164
176
|
end
|
165
177
|
|
@@ -171,18 +183,18 @@ describe Her::Model::ORM do
|
|
171
183
|
|
172
184
|
it "handles custom setters" do
|
173
185
|
@user = User.find(1)
|
174
|
-
@user.friends.
|
186
|
+
expect(@user.friends).to eq("* Maeby\n* GOB\n* Anne")
|
175
187
|
@user.instance_eval do
|
176
|
-
@attributes[:friends] =
|
188
|
+
@attributes[:friends] = %w(Maeby GOB Anne)
|
177
189
|
end
|
178
190
|
end
|
179
191
|
|
180
192
|
it "handles custom getters" do
|
181
193
|
@user = User.new
|
182
194
|
@user.friends = "* George\n* Oscar\n* Lucille"
|
183
|
-
@user.friends.
|
195
|
+
expect(@user.friends).to eq("* George\n* Oscar\n* Lucille")
|
184
196
|
@user.instance_eval do
|
185
|
-
@attributes[:friends] =
|
197
|
+
@attributes[:friends] = %w(George Oscar Lucille)
|
186
198
|
end
|
187
199
|
end
|
188
200
|
end
|
@@ -190,16 +202,16 @@ describe Her::Model::ORM do
|
|
190
202
|
context "finding resources" do
|
191
203
|
before do
|
192
204
|
api = Her::API.new
|
193
|
-
api.setup :
|
205
|
+
api.setup url: "https://api.example.com" do |builder|
|
194
206
|
builder.use Her::Middleware::FirstLevelParseJSON
|
195
207
|
builder.use Faraday::Request::UrlEncoded
|
196
208
|
builder.adapter :test do |stub|
|
197
|
-
stub.get("/users/1") {
|
198
|
-
stub.get("/users/2") {
|
199
|
-
stub.get("/users?id[]=1&id[]=2") {
|
200
|
-
stub.get("/users?age=42&foo=bar") {
|
201
|
-
stub.get("/users?age=42") {
|
202
|
-
stub.get("/users?age=40") {
|
209
|
+
stub.get("/users/1") { [200, {}, { id: 1, age: 42 }.to_json] }
|
210
|
+
stub.get("/users/2") { [200, {}, { id: 2, age: 34 }.to_json] }
|
211
|
+
stub.get("/users?id[]=1&id[]=2") { [200, {}, [{ id: 1, age: 42 }, { id: 2, age: 34 }].to_json] }
|
212
|
+
stub.get("/users?age=42&foo=bar") { [200, {}, [{ id: 3, age: 42 }].to_json] }
|
213
|
+
stub.get("/users?age=42") { [200, {}, [{ id: 1, age: 42 }].to_json] }
|
214
|
+
stub.get("/users?age=40") { [200, {}, [{ id: 1, age: 40 }].to_json] }
|
203
215
|
end
|
204
216
|
end
|
205
217
|
|
@@ -210,58 +222,58 @@ describe Her::Model::ORM do
|
|
210
222
|
|
211
223
|
it "handles finding by a single id" do
|
212
224
|
@user = User.find(1)
|
213
|
-
@user.id.
|
225
|
+
expect(@user.id).to eq(1)
|
214
226
|
end
|
215
227
|
|
216
228
|
it "handles finding by multiple ids" do
|
217
229
|
@users = User.find(1, 2)
|
218
|
-
@users.
|
219
|
-
@users.length.
|
220
|
-
@users[0].id.
|
221
|
-
@users[1].id.
|
230
|
+
expect(@users).to be_kind_of(Array)
|
231
|
+
expect(@users.length).to eq(2)
|
232
|
+
expect(@users[0].id).to eq(1)
|
233
|
+
expect(@users[1].id).to eq(2)
|
222
234
|
end
|
223
235
|
|
224
236
|
it "handles finding by an array of ids" do
|
225
237
|
@users = User.find([1, 2])
|
226
|
-
@users.
|
227
|
-
@users.length.
|
228
|
-
@users[0].id.
|
229
|
-
@users[1].id.
|
238
|
+
expect(@users).to be_kind_of(Array)
|
239
|
+
expect(@users.length).to eq(2)
|
240
|
+
expect(@users[0].id).to eq(1)
|
241
|
+
expect(@users[1].id).to eq(2)
|
230
242
|
end
|
231
243
|
|
232
244
|
it "handles finding by an array of ids of length 1" do
|
233
245
|
@users = User.find([1])
|
234
|
-
@users.
|
235
|
-
@users.length.
|
236
|
-
@users[0].id.
|
246
|
+
expect(@users).to be_kind_of(Array)
|
247
|
+
expect(@users.length).to eq(1)
|
248
|
+
expect(@users[0].id).to eq(1)
|
237
249
|
end
|
238
250
|
|
239
251
|
it "handles finding by an array id param of length 2" do
|
240
252
|
@users = User.find(id: [1, 2])
|
241
|
-
@users.
|
242
|
-
@users.length.
|
243
|
-
@users[0].id.
|
244
|
-
@users[1].id.
|
253
|
+
expect(@users).to be_kind_of(Array)
|
254
|
+
expect(@users.length).to eq(2)
|
255
|
+
expect(@users[0].id).to eq(1)
|
256
|
+
expect(@users[1].id).to eq(2)
|
245
257
|
end
|
246
258
|
|
247
|
-
it
|
259
|
+
it "handles finding with id parameter as an array" do
|
248
260
|
@users = User.where(id: [1, 2])
|
249
|
-
@users.
|
250
|
-
@users.length.
|
251
|
-
@users[0].id.
|
252
|
-
@users[1].id.
|
261
|
+
expect(@users).to be_kind_of(Array)
|
262
|
+
expect(@users.length).to eq(2)
|
263
|
+
expect(@users[0].id).to eq(1)
|
264
|
+
expect(@users[1].id).to eq(2)
|
253
265
|
end
|
254
266
|
|
255
267
|
it "handles finding with other parameters" do
|
256
|
-
@users = User.where(:
|
257
|
-
@users.
|
258
|
-
@users.first.id.
|
268
|
+
@users = User.where(age: 42, foo: "bar").all
|
269
|
+
expect(@users).to be_kind_of(Array)
|
270
|
+
expect(@users.first.id).to eq(3)
|
259
271
|
end
|
260
272
|
|
261
273
|
it "handles finding with other parameters and scoped" do
|
262
274
|
@users = User.scoped
|
263
|
-
@users.where(:
|
264
|
-
@users.where(:
|
275
|
+
expect(@users.where(age: 42)).to be_all { |u| u.age == 42 }
|
276
|
+
expect(@users.where(age: 40)).to be_all { |u| u.age == 40 }
|
265
277
|
end
|
266
278
|
end
|
267
279
|
|
@@ -272,20 +284,20 @@ describe Her::Model::ORM do
|
|
272
284
|
end
|
273
285
|
|
274
286
|
it "builds a new resource without requesting it" do
|
275
|
-
Foo::User.
|
276
|
-
@new_user = Foo::User.build(:
|
277
|
-
@new_user.new
|
278
|
-
@new_user.fullname.
|
287
|
+
expect(Foo::User).not_to receive(:request)
|
288
|
+
@new_user = Foo::User.build(fullname: "Tobias Fünke")
|
289
|
+
expect(@new_user.new?).to be_truthy
|
290
|
+
expect(@new_user.fullname).to eq("Tobias Fünke")
|
279
291
|
end
|
280
292
|
end
|
281
293
|
|
282
294
|
context "when request_new_object_on_build is set" do
|
283
295
|
before do
|
284
|
-
Her::API.setup :
|
296
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
285
297
|
builder.use Her::Middleware::FirstLevelParseJSON
|
286
298
|
builder.use Faraday::Request::UrlEncoded
|
287
299
|
builder.adapter :test do |stub|
|
288
|
-
stub.get("/users/new") { |env| ok! :
|
300
|
+
stub.get("/users/new") { |env| ok! id: nil, fullname: params(env)[:fullname], email: "tobias@bluthcompany.com" }
|
289
301
|
end
|
290
302
|
end
|
291
303
|
|
@@ -293,23 +305,23 @@ describe Her::Model::ORM do
|
|
293
305
|
end
|
294
306
|
|
295
307
|
it "requests a new resource" do
|
296
|
-
Foo::User.
|
297
|
-
@new_user = Foo::User.build(:
|
298
|
-
@new_user.new
|
299
|
-
@new_user.fullname.
|
300
|
-
@new_user.email.
|
308
|
+
expect(Foo::User).to receive(:request).once.and_call_original
|
309
|
+
@new_user = Foo::User.build(fullname: "Tobias Fünke")
|
310
|
+
expect(@new_user.new?).to be_truthy
|
311
|
+
expect(@new_user.fullname).to eq("Tobias Fünke")
|
312
|
+
expect(@new_user.email).to eq("tobias@bluthcompany.com")
|
301
313
|
end
|
302
314
|
end
|
303
315
|
end
|
304
316
|
|
305
317
|
context "creating resources" do
|
306
318
|
before do
|
307
|
-
Her::API.setup :
|
319
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
308
320
|
builder.use Her::Middleware::FirstLevelParseJSON
|
309
321
|
builder.use Faraday::Request::UrlEncoded
|
310
322
|
builder.adapter :test do |stub|
|
311
|
-
stub.post("/users") { |env| [200, {}, { :
|
312
|
-
stub.post("/companies") {
|
323
|
+
stub.post("/users") { |env| [200, {}, { id: 1, fullname: Faraday::Utils.parse_query(env[:body])["fullname"], email: Faraday::Utils.parse_query(env[:body])["email"] }.to_json] }
|
324
|
+
stub.post("/companies") { [200, {}, { errors: ["name is required"] }.to_json] }
|
313
325
|
end
|
314
326
|
end
|
315
327
|
|
@@ -318,27 +330,27 @@ describe Her::Model::ORM do
|
|
318
330
|
end
|
319
331
|
|
320
332
|
it "handle one-line resource creation" do
|
321
|
-
@user = Foo::User.create(:
|
322
|
-
@user.id.
|
323
|
-
@user.fullname.
|
324
|
-
@user.email.
|
333
|
+
@user = Foo::User.create(fullname: "Tobias Fünke", email: "tobias@bluth.com")
|
334
|
+
expect(@user.id).to eq(1)
|
335
|
+
expect(@user.fullname).to eq("Tobias Fünke")
|
336
|
+
expect(@user.email).to eq("tobias@bluth.com")
|
325
337
|
end
|
326
338
|
|
327
339
|
it "handle resource creation through Model.new + #save" do
|
328
|
-
@user = Foo::User.new(:
|
329
|
-
@user.save.
|
330
|
-
@user.fullname.
|
340
|
+
@user = Foo::User.new(fullname: "Tobias Fünke")
|
341
|
+
expect(@user.save).to be_truthy
|
342
|
+
expect(@user.fullname).to eq("Tobias Fünke")
|
331
343
|
end
|
332
344
|
|
333
345
|
it "handle resource creation through Model.new + #save!" do
|
334
|
-
@user = Foo::User.new(:
|
335
|
-
@user.save
|
336
|
-
@user.fullname.
|
346
|
+
@user = Foo::User.new(fullname: "Tobias Fünke")
|
347
|
+
expect(@user.save!).to be_truthy
|
348
|
+
expect(@user.fullname).to eq("Tobias Fünke")
|
337
349
|
end
|
338
350
|
|
339
351
|
it "returns false when #save gets errors" do
|
340
352
|
@company = Foo::Company.new
|
341
|
-
@company.save.
|
353
|
+
expect(@company.save).to be_falsey
|
342
354
|
end
|
343
355
|
|
344
356
|
it "raises ResourceInvalid when #save! gets errors" do
|
@@ -347,20 +359,20 @@ describe Her::Model::ORM do
|
|
347
359
|
end
|
348
360
|
|
349
361
|
it "don't overwrite data if response is empty" do
|
350
|
-
@company = Foo::Company.new(:
|
351
|
-
@company.save.
|
352
|
-
@company.name.
|
362
|
+
@company = Foo::Company.new(name: "Company Inc.")
|
363
|
+
expect(@company.save).to be_falsey
|
364
|
+
expect(@company.name).to eq("Company Inc.")
|
353
365
|
end
|
354
366
|
end
|
355
367
|
|
356
368
|
context "updating resources" do
|
357
369
|
before do
|
358
|
-
Her::API.setup :
|
370
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
359
371
|
builder.use Her::Middleware::FirstLevelParseJSON
|
360
372
|
builder.use Faraday::Request::UrlEncoded
|
361
373
|
builder.adapter :test do |stub|
|
362
|
-
stub.get("/users/1") {
|
363
|
-
stub.put("/users/1") {
|
374
|
+
stub.get("/users/1") { [200, {}, { id: 1, fullname: "Tobias Fünke" }.to_json] }
|
375
|
+
stub.put("/users/1") { [200, {}, { id: 1, fullname: "Lindsay Fünke" }.to_json] }
|
364
376
|
end
|
365
377
|
end
|
366
378
|
|
@@ -369,32 +381,32 @@ describe Her::Model::ORM do
|
|
369
381
|
|
370
382
|
it "handle resource data update without saving it" do
|
371
383
|
@user = Foo::User.find(1)
|
372
|
-
@user.fullname.
|
384
|
+
expect(@user.fullname).to eq("Tobias Fünke")
|
373
385
|
@user.fullname = "Kittie Sanchez"
|
374
|
-
@user.fullname.
|
386
|
+
expect(@user.fullname).to eq("Kittie Sanchez")
|
375
387
|
end
|
376
388
|
|
377
389
|
it "handle resource update through the .update class method" do
|
378
|
-
@user = Foo::User.save_existing(1,
|
379
|
-
@user.fullname.
|
390
|
+
@user = Foo::User.save_existing(1, fullname: "Lindsay Fünke")
|
391
|
+
expect(@user.fullname).to eq("Lindsay Fünke")
|
380
392
|
end
|
381
393
|
|
382
394
|
it "handle resource update through #save on an existing resource" do
|
383
395
|
@user = Foo::User.find(1)
|
384
396
|
@user.fullname = "Lindsay Fünke"
|
385
397
|
@user.save
|
386
|
-
@user.fullname.
|
398
|
+
expect(@user.fullname).to eq("Lindsay Fünke")
|
387
399
|
end
|
388
400
|
end
|
389
401
|
|
390
402
|
context "deleting resources" do
|
391
403
|
before do
|
392
|
-
Her::API.setup :
|
404
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
393
405
|
builder.use Her::Middleware::FirstLevelParseJSON
|
394
406
|
builder.use Faraday::Request::UrlEncoded
|
395
407
|
builder.adapter :test do |stub|
|
396
|
-
stub.get("/users/1") {
|
397
|
-
stub.delete("/users/1") {
|
408
|
+
stub.get("/users/1") { [200, {}, { id: 1, fullname: "Tobias Fünke", active: true }.to_json] }
|
409
|
+
stub.delete("/users/1") { [200, {}, { id: 1, fullname: "Lindsay Fünke", active: false }.to_json] }
|
398
410
|
end
|
399
411
|
end
|
400
412
|
|
@@ -403,103 +415,103 @@ describe Her::Model::ORM do
|
|
403
415
|
|
404
416
|
it "handle resource deletion through the .destroy class method" do
|
405
417
|
@user = Foo::User.destroy_existing(1)
|
406
|
-
@user.active.
|
407
|
-
@user.
|
418
|
+
expect(@user.active).to be_falsey
|
419
|
+
expect(@user).to be_destroyed
|
408
420
|
end
|
409
421
|
|
410
422
|
it "handle resource deletion through #destroy on an existing resource" do
|
411
423
|
@user = Foo::User.find(1)
|
412
424
|
@user.destroy
|
413
|
-
@user.active.
|
414
|
-
@user.
|
425
|
+
expect(@user.active).to be_falsey
|
426
|
+
expect(@user).to be_destroyed
|
415
427
|
end
|
416
428
|
|
417
429
|
context "with params" do
|
418
430
|
before do
|
419
|
-
Her::API.setup :
|
431
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
420
432
|
builder.use Her::Middleware::FirstLevelParseJSON
|
421
433
|
builder.use Faraday::Request::UrlEncoded
|
422
434
|
builder.adapter :test do |stub|
|
423
|
-
stub.delete("/users/1?delete_type=soft") {
|
435
|
+
stub.delete("/users/1?delete_type=soft") { [200, {}, { id: 1, fullname: "Lindsay Fünke", active: false }.to_json] }
|
424
436
|
end
|
425
437
|
end
|
426
438
|
end
|
427
439
|
|
428
440
|
it "handle resource deletion through the .destroy class method" do
|
429
|
-
@user = Foo::User.destroy_existing(1, delete_type:
|
430
|
-
@user.active.
|
431
|
-
@user.
|
441
|
+
@user = Foo::User.destroy_existing(1, delete_type: "soft")
|
442
|
+
expect(@user.active).to be_falsey
|
443
|
+
expect(@user).to be_destroyed
|
432
444
|
end
|
433
445
|
|
434
446
|
it "handle resource deletion through #destroy on an existing resource" do
|
435
447
|
@user = Foo::User.find(1)
|
436
|
-
@user.destroy(delete_type:
|
437
|
-
@user.active.
|
438
|
-
@user.
|
448
|
+
@user.destroy(delete_type: "soft")
|
449
|
+
expect(@user.active).to be_falsey
|
450
|
+
expect(@user).to be_destroyed
|
439
451
|
end
|
440
452
|
end
|
441
453
|
end
|
442
454
|
|
443
|
-
context
|
455
|
+
context "customizing HTTP methods" do
|
444
456
|
before do
|
445
|
-
Her::API.setup :
|
457
|
+
Her::API.setup url: "https://api.example.com" do |builder|
|
446
458
|
builder.use Her::Middleware::FirstLevelParseJSON
|
447
459
|
builder.use Faraday::Request::UrlEncoded
|
448
460
|
end
|
449
461
|
end
|
450
462
|
|
451
|
-
context
|
463
|
+
context "create" do
|
452
464
|
before do
|
453
465
|
Her::API.default_api.connection.adapter :test do |stub|
|
454
|
-
stub.put(
|
466
|
+
stub.put("/users") { [200, {}, { id: 1, fullname: "Tobias Fünke" }.to_json] }
|
455
467
|
end
|
456
|
-
spawn_model
|
468
|
+
spawn_model "Foo::User" do
|
457
469
|
attributes :fullname, :email
|
458
|
-
method_for :create,
|
470
|
+
method_for :create, "PUT"
|
459
471
|
end
|
460
472
|
end
|
461
473
|
|
462
|
-
context
|
463
|
-
it
|
464
|
-
user = Foo::User.new(:
|
465
|
-
user.
|
466
|
-
user.save.
|
474
|
+
context "for top-level class" do
|
475
|
+
it "uses the custom method (PUT) instead of default method (POST)" do
|
476
|
+
user = Foo::User.new(fullname: "Tobias Fünke")
|
477
|
+
expect(user).to be_new
|
478
|
+
expect(user.save).to be_truthy
|
467
479
|
end
|
468
480
|
end
|
469
481
|
|
470
|
-
context
|
482
|
+
context "for children class" do
|
471
483
|
before do
|
472
484
|
class User < Foo::User; end
|
473
485
|
@spawned_models << :User
|
474
486
|
end
|
475
487
|
|
476
|
-
it
|
477
|
-
user = User.new(:
|
478
|
-
user.
|
479
|
-
user.save.
|
488
|
+
it "uses the custom method (PUT) instead of default method (POST)" do
|
489
|
+
user = User.new(fullname: "Tobias Fünke")
|
490
|
+
expect(user).to be_new
|
491
|
+
expect(user.save).to be_truthy
|
480
492
|
end
|
481
493
|
end
|
482
494
|
end
|
483
495
|
|
484
|
-
context
|
496
|
+
context "update" do
|
485
497
|
before do
|
486
498
|
Her::API.default_api.connection.adapter :test do |stub|
|
487
|
-
stub.get(
|
488
|
-
stub.post(
|
499
|
+
stub.get("/users/1") { [200, {}, { id: 1, fullname: "Lindsay Fünke" }.to_json] }
|
500
|
+
stub.post("/users/1") { [200, {}, { id: 1, fullname: "Tobias Fünke" }.to_json] }
|
489
501
|
end
|
490
502
|
|
491
|
-
spawn_model
|
503
|
+
spawn_model "Foo::User" do
|
492
504
|
attributes :fullname, :email
|
493
505
|
method_for :update, :post
|
494
506
|
end
|
495
507
|
end
|
496
508
|
|
497
|
-
it
|
509
|
+
it "uses the custom method (POST) instead of default method (PUT)" do
|
498
510
|
user = Foo::User.find(1)
|
499
|
-
user.fullname.
|
500
|
-
user.fullname =
|
511
|
+
expect(user.fullname).to eq "Lindsay Fünke"
|
512
|
+
user.fullname = "Toby Fünke"
|
501
513
|
user.save
|
502
|
-
user.fullname.
|
514
|
+
expect(user.fullname).to eq "Tobias Fünke"
|
503
515
|
end
|
504
516
|
end
|
505
517
|
end
|