her5 0.8.1
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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +17 -0
- data/.yardopts +2 -0
- data/CONTRIBUTING.md +26 -0
- data/Gemfile +10 -0
- data/LICENSE +7 -0
- data/README.md +1017 -0
- data/Rakefile +11 -0
- data/UPGRADE.md +101 -0
- data/gemfiles/Gemfile.activemodel-3.2.x +7 -0
- data/gemfiles/Gemfile.activemodel-4.0 +7 -0
- data/gemfiles/Gemfile.activemodel-4.1 +7 -0
- data/gemfiles/Gemfile.activemodel-4.2 +7 -0
- data/gemfiles/Gemfile.activemodel-5.0.x +7 -0
- data/her5.gemspec +30 -0
- data/lib/her.rb +19 -0
- data/lib/her/api.rb +120 -0
- data/lib/her/collection.rb +12 -0
- data/lib/her/errors.rb +104 -0
- data/lib/her/json_api/model.rb +57 -0
- data/lib/her/middleware.rb +12 -0
- data/lib/her/middleware/accept_json.rb +17 -0
- data/lib/her/middleware/first_level_parse_json.rb +36 -0
- data/lib/her/middleware/json_api_parser.rb +68 -0
- data/lib/her/middleware/parse_json.rb +28 -0
- data/lib/her/middleware/second_level_parse_json.rb +36 -0
- data/lib/her/model.rb +75 -0
- data/lib/her/model/associations.rb +141 -0
- data/lib/her/model/associations/association.rb +107 -0
- data/lib/her/model/associations/association_proxy.rb +45 -0
- data/lib/her/model/associations/belongs_to_association.rb +101 -0
- data/lib/her/model/associations/has_many_association.rb +101 -0
- data/lib/her/model/associations/has_one_association.rb +80 -0
- data/lib/her/model/attributes.rb +297 -0
- data/lib/her/model/base.rb +33 -0
- data/lib/her/model/deprecated_methods.rb +61 -0
- data/lib/her/model/http.rb +113 -0
- data/lib/her/model/introspection.rb +65 -0
- data/lib/her/model/nested_attributes.rb +84 -0
- data/lib/her/model/orm.rb +207 -0
- data/lib/her/model/parse.rb +221 -0
- data/lib/her/model/paths.rb +126 -0
- data/lib/her/model/relation.rb +164 -0
- data/lib/her/version.rb +3 -0
- data/spec/api_spec.rb +114 -0
- data/spec/collection_spec.rb +26 -0
- data/spec/json_api/model_spec.rb +305 -0
- data/spec/middleware/accept_json_spec.rb +10 -0
- data/spec/middleware/first_level_parse_json_spec.rb +62 -0
- data/spec/middleware/json_api_parser_spec.rb +32 -0
- data/spec/middleware/second_level_parse_json_spec.rb +35 -0
- data/spec/model/associations/association_proxy_spec.rb +31 -0
- data/spec/model/associations_spec.rb +504 -0
- data/spec/model/attributes_spec.rb +389 -0
- data/spec/model/callbacks_spec.rb +145 -0
- data/spec/model/dirty_spec.rb +91 -0
- data/spec/model/http_spec.rb +158 -0
- data/spec/model/introspection_spec.rb +76 -0
- data/spec/model/nested_attributes_spec.rb +134 -0
- data/spec/model/orm_spec.rb +506 -0
- data/spec/model/parse_spec.rb +345 -0
- data/spec/model/paths_spec.rb +347 -0
- data/spec/model/relation_spec.rb +226 -0
- data/spec/model/validations_spec.rb +42 -0
- data/spec/model_spec.rb +44 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/extensions/array.rb +5 -0
- data/spec/support/extensions/hash.rb +5 -0
- data/spec/support/macros/her_macros.rb +17 -0
- data/spec/support/macros/model_macros.rb +36 -0
- data/spec/support/macros/request_macros.rb +27 -0
- metadata +289 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
3
|
+
|
4
|
+
describe "Her::Model and ActiveModel::Dirty" do
|
5
|
+
context "checking dirty attributes" do
|
6
|
+
before do
|
7
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
8
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
9
|
+
builder.use Faraday::Request::UrlEncoded
|
10
|
+
builder.adapter :test do |stub|
|
11
|
+
stub.get("/users/1") { |env| [200, {}, { :id => 1, :fullname => "Lindsay Fünke" }.to_json] }
|
12
|
+
stub.get("/users/2") { |env| [200, {}, { :id => 2, :fullname => "Maeby Fünke" }.to_json] }
|
13
|
+
stub.get("/users/3") { |env| [200, {}, { :user_id => 3, :fullname => "Maeby Fünke" }.to_json] }
|
14
|
+
stub.put("/users/1") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke" }.to_json] }
|
15
|
+
stub.put("/users/2") { |env| [400, {}, { :errors => ["Email cannot be blank"] }.to_json] }
|
16
|
+
stub.post("/users") { |env| [200, {}, { :id => 1, :fullname => "Tobias Fünke" }.to_json] }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
spawn_model "Foo::User" do
|
21
|
+
attributes :fullname, :email
|
22
|
+
end
|
23
|
+
spawn_model "Dynamic::User" do
|
24
|
+
primary_key :user_id
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "for existing resource" do
|
29
|
+
let(:user) { Foo::User.find(1) }
|
30
|
+
it "has no changes" do
|
31
|
+
user.changes.should be_empty
|
32
|
+
user.should_not be_changed
|
33
|
+
end
|
34
|
+
context "with successful save" do
|
35
|
+
it "tracks dirty attributes" do
|
36
|
+
user.fullname = "Tobias Fünke"
|
37
|
+
user.fullname_changed?.should be_truthy
|
38
|
+
user.email_changed?.should be_falsey
|
39
|
+
user.should be_changed
|
40
|
+
user.save
|
41
|
+
user.should_not be_changed
|
42
|
+
end
|
43
|
+
|
44
|
+
it "tracks only changed dirty attributes" do
|
45
|
+
user.fullname = user.fullname
|
46
|
+
user.fullname_changed?.should be_falsey
|
47
|
+
end
|
48
|
+
|
49
|
+
it "tracks previous changes" do
|
50
|
+
user.fullname = "Tobias Fünke"
|
51
|
+
user.save
|
52
|
+
user.previous_changes.should eq({"fullname"=>"Lindsay Fünke"})
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'tracks dirty attribute for mass assign for dynamic created attributes' do
|
56
|
+
user = Dynamic::User.find(3)
|
57
|
+
user.assign_attributes(:fullname => 'New Fullname')
|
58
|
+
user.fullname_changed?.should be_truthy
|
59
|
+
user.should be_changed
|
60
|
+
user.changes.length.should eq(1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "with erroneous save" do
|
65
|
+
it "tracks dirty attributes" do
|
66
|
+
user = Foo::User.find(2)
|
67
|
+
user.fullname = "Tobias Fünke"
|
68
|
+
user.fullname_changed?.should be_truthy
|
69
|
+
user.email_changed?.should be_falsey
|
70
|
+
user.should be_changed
|
71
|
+
user.save
|
72
|
+
user.should be_changed
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "for new resource" do
|
78
|
+
let(:user) { Foo::User.new(:fullname => "Lindsay Fünke") }
|
79
|
+
it "has changes" do
|
80
|
+
user.should be_changed
|
81
|
+
end
|
82
|
+
it "tracks dirty attributes" do
|
83
|
+
user.fullname = "Tobias Fünke"
|
84
|
+
user.fullname_changed?.should be_truthy
|
85
|
+
user.should be_changed
|
86
|
+
user.save
|
87
|
+
user.should_not be_changed
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
3
|
+
|
4
|
+
describe Her::Model::HTTP do
|
5
|
+
context "binding a model with an API" do
|
6
|
+
let(:api1) { Her::API.new :url => "https://api1.example.com" }
|
7
|
+
let(:api2) { Her::API.new :url => "https://api2.example.com" }
|
8
|
+
|
9
|
+
before do
|
10
|
+
spawn_model("Foo::User")
|
11
|
+
spawn_model("Foo::Comment")
|
12
|
+
Her::API.setup :url => "https://api.example.com"
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when binding a model to its superclass' her_api" do
|
16
|
+
before do
|
17
|
+
spawn_model "Foo::Superclass"
|
18
|
+
Foo::Superclass.uses_api api1
|
19
|
+
Foo::Subclass = Class.new(Foo::Superclass)
|
20
|
+
end
|
21
|
+
|
22
|
+
specify { Foo::Subclass.her_api.should == Foo::Superclass.her_api }
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when changing her_api without changing the parent class' her_api" do
|
26
|
+
before do
|
27
|
+
spawn_model "Foo::Superclass"
|
28
|
+
Foo::Subclass = Class.new(Foo::Superclass)
|
29
|
+
Foo::Superclass.uses_api api1
|
30
|
+
Foo::Subclass.uses_api api2
|
31
|
+
end
|
32
|
+
|
33
|
+
specify { Foo::Subclass.her_api.should_not == Foo::Superclass.her_api }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "making HTTP requests" do
|
38
|
+
before do
|
39
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
40
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
41
|
+
builder.use Faraday::Request::UrlEncoded
|
42
|
+
builder.adapter :test do |stub|
|
43
|
+
stub.get("/users") { |env| [200, {}, [{ :id => 1 }].to_json] }
|
44
|
+
stub.get("/users/1") { |env| [200, {}, { :id => 1 }.to_json] }
|
45
|
+
stub.get("/users/popular") do |env|
|
46
|
+
if env[:params]["page"] == "2"
|
47
|
+
[200, {}, [{ :id => 3 }, { :id => 4 }].to_json]
|
48
|
+
else
|
49
|
+
[200, {}, [{ :id => 1 }, { :id => 2 }].to_json]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
spawn_model "Foo::User"
|
56
|
+
end
|
57
|
+
|
58
|
+
describe :get do
|
59
|
+
subject { Foo::User.get(:popular) }
|
60
|
+
its(:length) { should == 2 }
|
61
|
+
specify { subject.first.id.should == 1 }
|
62
|
+
end
|
63
|
+
|
64
|
+
describe :get_raw do
|
65
|
+
context "with a block" do
|
66
|
+
specify do
|
67
|
+
Foo::User.get_raw("/users") do |parsed_data, response|
|
68
|
+
parsed_data[:data].should == [{ :id => 1 }]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with a return value" do
|
74
|
+
subject { Foo::User.get_raw("/users") }
|
75
|
+
specify { subject[:parsed_data][:data].should == [{ :id => 1 }] }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe :get_collection do
|
80
|
+
context "with a String path" do
|
81
|
+
subject { Foo::User.get_collection("/users/popular") }
|
82
|
+
its(:length) { should == 2 }
|
83
|
+
specify { subject.first.id.should == 1 }
|
84
|
+
end
|
85
|
+
|
86
|
+
context "with a Symbol" do
|
87
|
+
subject { Foo::User.get_collection(:popular) }
|
88
|
+
its(:length) { should == 2 }
|
89
|
+
specify { subject.first.id.should == 1 }
|
90
|
+
end
|
91
|
+
|
92
|
+
context "with extra parameters" do
|
93
|
+
subject { Foo::User.get_collection(:popular, :page => 2) }
|
94
|
+
its(:length) { should == 2 }
|
95
|
+
specify { subject.first.id.should == 3 }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe :get_resource do
|
100
|
+
context "with a String path" do
|
101
|
+
subject { Foo::User.get_resource("/users/1") }
|
102
|
+
its(:id) { should == 1 }
|
103
|
+
end
|
104
|
+
|
105
|
+
context "with a Symbol" do
|
106
|
+
subject { Foo::User.get_resource(:"1") }
|
107
|
+
its(:id) { should == 1 }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe :get_raw do
|
112
|
+
specify do
|
113
|
+
Foo::User.get_raw(:popular) do |parsed_data, response|
|
114
|
+
parsed_data[:data].should == [{ :id => 1 }, { :id => 2 }]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "setting custom HTTP requests" do
|
121
|
+
before do
|
122
|
+
Her::API.setup :url => "https://api.example.com" do |connection|
|
123
|
+
connection.use Her::Middleware::FirstLevelParseJSON
|
124
|
+
connection.adapter :test do |stub|
|
125
|
+
stub.get("/users/popular") { |env| [200, {}, [{ :id => 1 }, { :id => 2 }].to_json] }
|
126
|
+
stub.post("/users/from_default") { |env| [200, {}, { :id => 4 }.to_json] }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
spawn_model "Foo::User"
|
131
|
+
end
|
132
|
+
|
133
|
+
subject { Foo::User }
|
134
|
+
|
135
|
+
describe :custom_get do
|
136
|
+
context "without cache" do
|
137
|
+
before { Foo::User.custom_get :popular, :recent }
|
138
|
+
it { should respond_to(:popular) }
|
139
|
+
it { should respond_to(:recent) }
|
140
|
+
|
141
|
+
context "making the HTTP request" do
|
142
|
+
subject { Foo::User.popular }
|
143
|
+
its(:length) { should == 2 }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe :custom_post do
|
149
|
+
before { Foo::User.custom_post :from_default }
|
150
|
+
it { should respond_to(:from_default) }
|
151
|
+
|
152
|
+
context "making the HTTP request" do
|
153
|
+
subject { Foo::User.from_default(:name => "Tobias Fünke") }
|
154
|
+
its(:id) { should == 4 }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
3
|
+
|
4
|
+
describe Her::Model::Introspection do
|
5
|
+
context "introspecting a resource" do
|
6
|
+
before do
|
7
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
8
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
9
|
+
builder.use Faraday::Request::UrlEncoded
|
10
|
+
builder.adapter :test do |stub|
|
11
|
+
stub.post("/users") { |env| [200, {}, { :id => 1, :name => "Tobias Funke" }.to_json] }
|
12
|
+
stub.get("/users/1") { |env| [200, {}, { :id => 1, :name => "Tobias Funke" }.to_json] }
|
13
|
+
stub.put("/users/1") { |env| [200, {}, { :id => 1, :name => "Tobias Funke" }.to_json] }
|
14
|
+
stub.delete("/users/1") { |env| [200, {}, { :id => 1, :name => "Tobias Funke" }.to_json] }
|
15
|
+
stub.get("/projects/1/comments") { |env| [200, {}, [{ :id => 1, :body => "Hello!" }].to_json] }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
spawn_model "Foo::User"
|
20
|
+
spawn_model "Foo::Comment" do
|
21
|
+
collection_path "projects/:project_id/comments"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#inspect" do
|
26
|
+
it "outputs resource attributes for an existing resource" do
|
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\">"].should include(@user.inspect)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "outputs resource attributes for an not-saved-yet resource" do
|
32
|
+
@user = Foo::User.new(:name => "Tobias Funke")
|
33
|
+
@user.inspect.should == "#<Foo::User(users) name=\"Tobias Funke\">"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "outputs resource attributes using getters" do
|
37
|
+
@user = Foo::User.new(:name => "Tobias Funke", :password => "Funke")
|
38
|
+
@user.instance_eval {def password; 'filtered'; end}
|
39
|
+
@user.inspect.should include("name=\"Tobias Funke\"")
|
40
|
+
@user.inspect.should include("password=\"filtered\"")
|
41
|
+
@user.inspect.should_not include("password=\"Funke\"")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "support dash on attribute" do
|
45
|
+
@user = Foo::User.new(:'life-span' => "3 years")
|
46
|
+
@user.inspect.should include("life-span=\"3 years\"")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#inspect with errors in resource path" do
|
51
|
+
it "prints the resource path as “unknown”" do
|
52
|
+
@comment = Foo::Comment.where(:project_id => 1).first
|
53
|
+
path = '<unknown path, missing `project_id`>'
|
54
|
+
["#<Foo::Comment(#{path}) body=\"Hello!\" id=1>", "#<Foo::Comment(#{path}) id=1 body=\"Hello!\">"].should include(@comment.inspect)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#her_nearby_class" do
|
60
|
+
context "for a class inside of a module" do
|
61
|
+
before do
|
62
|
+
spawn_model "Foo::User"
|
63
|
+
spawn_model "Foo::AccessRecord"
|
64
|
+
spawn_model "AccessRecord"
|
65
|
+
spawn_model "Log"
|
66
|
+
end
|
67
|
+
|
68
|
+
it "returns a sibling class, if found" do
|
69
|
+
Foo::User.her_nearby_class("AccessRecord").should == Foo::AccessRecord
|
70
|
+
AccessRecord.her_nearby_class("Log").should == Log
|
71
|
+
Foo::User.her_nearby_class("Log").should == Log
|
72
|
+
Foo::User.her_nearby_class("X").should be_nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
3
|
+
|
4
|
+
describe Her::Model::NestedAttributes do
|
5
|
+
context "with a belongs_to association" do
|
6
|
+
before do
|
7
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
8
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
9
|
+
builder.use Faraday::Request::UrlEncoded
|
10
|
+
end
|
11
|
+
|
12
|
+
spawn_model "Foo::User" do
|
13
|
+
belongs_to :company, :path => "/organizations/:id", :foreign_key => :organization_id
|
14
|
+
accepts_nested_attributes_for :company
|
15
|
+
end
|
16
|
+
|
17
|
+
spawn_model "Foo::Company"
|
18
|
+
|
19
|
+
@user_with_data_through_nested_attributes = Foo::User.new :name => "Test", :company_attributes => { :name => "Example Company" }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when child does not yet exist" do
|
23
|
+
it "creates an instance of the associated class" do
|
24
|
+
@user_with_data_through_nested_attributes.company.should be_a(Foo::Company)
|
25
|
+
@user_with_data_through_nested_attributes.company.name.should == "Example Company"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when child does exist" do
|
30
|
+
it "updates the attributes of the associated object" do
|
31
|
+
@user_with_data_through_nested_attributes.company_attributes = { :name => "Fünke's Company" }
|
32
|
+
@user_with_data_through_nested_attributes.company.should be_a(Foo::Company)
|
33
|
+
@user_with_data_through_nested_attributes.company.name.should == "Fünke's Company"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with a has_one association" do
|
39
|
+
before do
|
40
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
41
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
42
|
+
builder.use Faraday::Request::UrlEncoded
|
43
|
+
end
|
44
|
+
|
45
|
+
spawn_model "Foo::User" do
|
46
|
+
has_one :pet
|
47
|
+
accepts_nested_attributes_for :pet
|
48
|
+
end
|
49
|
+
|
50
|
+
spawn_model "Foo::Pet"
|
51
|
+
|
52
|
+
@user_with_data_through_nested_attributes = Foo::User.new :name => "Test", :pet_attributes => { :name => "Hasi" }
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when child does not yet exist" do
|
56
|
+
it "creates an instance of the associated class" do
|
57
|
+
@user_with_data_through_nested_attributes.pet.should be_a(Foo::Pet)
|
58
|
+
@user_with_data_through_nested_attributes.pet.name.should == "Hasi"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when child does exist" do
|
63
|
+
it "updates the attributes of the associated object" do
|
64
|
+
@user_with_data_through_nested_attributes.pet_attributes = { :name => "Rodriguez" }
|
65
|
+
@user_with_data_through_nested_attributes.pet.should be_a(Foo::Pet)
|
66
|
+
@user_with_data_through_nested_attributes.pet.name.should == "Rodriguez"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with a has_many association" do
|
72
|
+
before do
|
73
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
74
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
75
|
+
builder.use Faraday::Request::UrlEncoded
|
76
|
+
end
|
77
|
+
|
78
|
+
spawn_model "Foo::User" do
|
79
|
+
has_many :pets
|
80
|
+
accepts_nested_attributes_for :pets
|
81
|
+
end
|
82
|
+
|
83
|
+
spawn_model "Foo::Pet"
|
84
|
+
|
85
|
+
@user_with_data_through_nested_attributes = Foo::User.new :name => "Test", :pets_attributes => [{ :name => "Hasi" }, { :name => "Rodriguez" }]
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when children do not yet exist" do
|
89
|
+
it "creates an instance of the associated class" do
|
90
|
+
@user_with_data_through_nested_attributes.pets.length.should == 2
|
91
|
+
@user_with_data_through_nested_attributes.pets[0].should be_a(Foo::Pet)
|
92
|
+
@user_with_data_through_nested_attributes.pets[1].should be_a(Foo::Pet)
|
93
|
+
@user_with_data_through_nested_attributes.pets[0].name.should == "Hasi"
|
94
|
+
@user_with_data_through_nested_attributes.pets[1].name.should == "Rodriguez"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "with a has_many association as a Hash" do
|
100
|
+
before do
|
101
|
+
Her::API.setup :url => "https://api.example.com" do |builder|
|
102
|
+
builder.use Her::Middleware::FirstLevelParseJSON
|
103
|
+
builder.use Faraday::Request::UrlEncoded
|
104
|
+
end
|
105
|
+
|
106
|
+
spawn_model "Foo::User" do
|
107
|
+
has_many :pets
|
108
|
+
accepts_nested_attributes_for :pets
|
109
|
+
end
|
110
|
+
|
111
|
+
spawn_model "Foo::Pet"
|
112
|
+
|
113
|
+
@user_with_data_through_nested_attributes_as_hash = Foo::User.new :name => "Test", :pets_attributes => { '0' => { :name => "Hasi" }, '1' => { :name => "Rodriguez" }}
|
114
|
+
end
|
115
|
+
|
116
|
+
context "when children do not yet exist" do
|
117
|
+
it "creates an instance of the associated class" do
|
118
|
+
@user_with_data_through_nested_attributes_as_hash.pets.length.should == 2
|
119
|
+
@user_with_data_through_nested_attributes_as_hash.pets[0].should be_a(Foo::Pet)
|
120
|
+
@user_with_data_through_nested_attributes_as_hash.pets[1].should be_a(Foo::Pet)
|
121
|
+
@user_with_data_through_nested_attributes_as_hash.pets[0].name.should == "Hasi"
|
122
|
+
@user_with_data_through_nested_attributes_as_hash.pets[1].name.should == "Rodriguez"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "with an unknown association" do
|
128
|
+
it "raises an error" do
|
129
|
+
expect {
|
130
|
+
spawn_model("Foo::User") { accepts_nested_attributes_for :company }
|
131
|
+
}.to raise_error(Her::Errors::AssociationUnknownError, 'Unknown association name :company')
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|