cfoundry 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -190,11 +190,7 @@ module CFoundry::V2
190
190
  def to_one(name, opts = {})
191
191
  to_one_relations[name] = opts
192
192
 
193
- obj = opts[:as] || name
194
- kls = obj.to_s.capitalize.gsub(/(.)_(.)/) do
195
- $1 + $2.upcase
196
- end
197
-
193
+ association_name = opts[:as] || name
198
194
  default = opts[:default]
199
195
 
200
196
  if has_default = opts.key?(:default)
@@ -207,40 +203,53 @@ module CFoundry::V2
207
203
 
208
204
  @cache[name] =
209
205
  if @manifest && @manifest[:entity].key?(name)
210
- @client.send(:"make_#{obj}", @manifest[:entity][name])
206
+ @client.send(:"make_#{association_name}", @manifest[:entity][name])
211
207
  elsif url = send("#{name}_url")
212
- @client.send(:"#{obj}_from", url)
208
+ @client.send(:"#{association_name}_from", url)
213
209
  else
214
210
  default
215
211
  end
216
212
  end
217
213
 
214
+ define_method("create_#{name}") do |*args|
215
+ associated_instance = @client.send(:"#{association_name}")
216
+ args.first.each do |name, value|
217
+ associated_instance.send("#{name}=", value)
218
+ end if args.first.is_a? Hash
219
+
220
+ associated_instance.create!
221
+ self.send("#{name}=", associated_instance)
222
+ end
223
+
218
224
  define_method(:"#{name}_url") do
219
225
  manifest[:entity][:"#{name}_url"]
220
226
  end
221
227
 
222
- define_method(:"#{name}=") do |val|
223
- klass = self.class.objects[obj]
228
+ define_method(:"#{name}=") do |assigned_value|
229
+ klass = self.class.objects[association_name]
224
230
 
225
- unless has_default && val == default
226
- CFoundry::Validator.validate_type(val, klass)
231
+ unless has_default && assigned_value == default
232
+ CFoundry::Validator.validate_type(assigned_value, klass)
227
233
  end
228
234
 
229
235
  @manifest ||= {}
230
236
  @manifest[:entity] ||= {}
231
237
 
232
- old = @manifest[:entity][:"#{name}_guid"]
233
- if old != (val && val.guid)
238
+ old_guid = @manifest[:entity][:"#{name}_guid"]
239
+ association_guid = assigned_value ? assigned_value.guid : nil
240
+
241
+ if old_guid != (association_guid)
234
242
  old_obj =
235
- @cache[name] || klass.new(@client, old, @manifest[:entity][name])
243
+ @cache[name] || klass.new(@client, old_guid, @manifest[:entity][name])
236
244
 
237
- @changes[name] = [old_obj, val]
245
+ @changes[name] = [old_obj, assigned_value]
238
246
  end
239
247
 
240
- @cache[name] = val
248
+ @cache[name] = assigned_value
241
249
 
242
- @manifest[:entity][:"#{name}_guid"] =
243
- @diff[:"#{name}_guid"] = val && val.guid
250
+ @manifest[:entity][:"#{name}_guid"] = association_guid
251
+ @diff[:"#{name}_guid"] = association_guid
252
+ assigned_value
244
253
  end
245
254
  end
246
255
 
@@ -253,9 +262,7 @@ module CFoundry::V2
253
262
 
254
263
  object = opts[:as] || singular
255
264
 
256
- kls = object.to_s.capitalize.gsub(/(.)_(.)/) do
257
- $1 + $2.upcase
258
- end
265
+ kls = object.to_s.camelcase
259
266
 
260
267
  define_method(plural) do |*args|
261
268
  klass = CFoundry::V2.const_get(kls)
@@ -1,4 +1,4 @@
1
1
  module CFoundry # :nodoc:
2
2
  # CFoundry library version number.
3
- VERSION = "1.3.0".freeze
3
+ VERSION = "1.4.0".freeze
4
4
  end
@@ -1,172 +1,217 @@
1
1
  require "spec_helper"
2
2
 
3
- describe CFoundry::V2::ModelMagic do
4
- let(:client) { fake_client }
5
- let(:mymodel) { fake_model }
6
- let(:guid) { random_string("my-object-guid") }
7
- let(:myobject) { mymodel.new(guid, client) }
3
+ module CFoundry::V2
4
+ class Associated < FakeModel
5
+ attribute :attribute, String
6
+ end
7
+
8
+ describe ModelMagic do
9
+ let(:client) { fake_client }
10
+ let(:mymodel) { fake_model }
11
+ let(:guid) { random_string("my-object-guid") }
12
+ let(:myobject) { mymodel.new(guid, client) }
8
13
 
9
- describe 'attributes' do
10
- describe 'reading' do
11
- let(:mymodel) { fake_model { attribute :foo, :object } }
14
+ describe 'attributes' do
15
+ describe 'reading' do
16
+ let(:mymodel) { fake_model { attribute :foo, :object } }
12
17
 
13
- context 'when it exists in the manifest' do
14
- subject { myobject.fake(:foo => "bar") }
18
+ context 'when it exists in the manifest' do
19
+ subject { myobject.fake(:foo => "bar") }
20
+
21
+ it 'returns the value from the manifest' do
22
+ expect(subject.foo).to eq "bar"
23
+ end
15
24
 
16
- it 'returns the value from the manifest' do
17
- expect(subject.foo).to eq "bar"
25
+ context 'and the default is nil but the value is false' do
26
+ let(:mymodel) {
27
+ fake_model { attribute :foo, :object, :default => nil }
28
+ }
29
+
30
+ subject { myobject.fake(:foo => false) }
31
+
32
+ it 'returns false' do
33
+ expect(subject.foo).to eq false
34
+ end
35
+ end
36
+
37
+ context 'and the default is false but the value is nil' do
38
+ let(:mymodel) {
39
+ fake_model { attribute :foo, :object, :default => false }
40
+ }
41
+
42
+ subject { myobject.fake(:foo => nil) }
43
+
44
+ it 'returns nil' do
45
+ expect(subject.foo).to eq nil
46
+ end
47
+ end
18
48
  end
19
49
 
20
- context 'and the default is nil but the value is false' do
21
- let(:mymodel) {
22
- fake_model { attribute :foo, :object, :default => nil }
23
- }
50
+ context 'when the manifest has not been acquired' do
51
+ it 'retrieves the manifest the first time' do
52
+ mock(client.base).my_fake_model(guid) {
53
+ {:entity => {:foo => "fizz"}}
54
+ }.ordered
24
55
 
25
- subject { myobject.fake(:foo => false) }
56
+ expect(myobject.foo).to eq "fizz"
26
57
 
27
- it 'returns false' do
28
- expect(subject.foo).to eq false
58
+ dont_allow(client.base).my_fake_model.ordered
59
+
60
+ expect(myobject.foo).to eq "fizz"
29
61
  end
30
62
  end
31
63
 
32
- context 'and the default is false but the value is nil' do
64
+ context 'when it does not exist in the manifest' do
33
65
  let(:mymodel) {
34
- fake_model { attribute :foo, :object, :default => false }
66
+ fake_model { attribute :foo, :object, :default => "foo" }
35
67
  }
36
68
 
37
- subject { myobject.fake(:foo => nil) }
69
+ subject { myobject.fake }
38
70
 
39
- it 'returns nil' do
40
- expect(subject.foo).to eq nil
71
+ it 'returns the default value' do
72
+ expect(subject.foo).to eq "foo"
41
73
  end
42
74
  end
43
- end
44
75
 
45
- context 'when the manifest has not been acquired' do
46
- it 'retrieves the manifest the first time' do
47
- mock(client.base).my_fake_model(guid) {
48
- { :entity => { :foo => "fizz" } }
49
- }.ordered
76
+ context 'when the attribute has a custom json key' do
77
+ let(:mymodel) {
78
+ fake_model { attribute :foo, :object, :at => :not_foo }
79
+ }
50
80
 
51
- expect(myobject.foo).to eq "fizz"
81
+ subject { myobject.fake }
52
82
 
53
- dont_allow(client.base).my_fake_model.ordered
83
+ it 'retrieves the attribute using the custom key' do
84
+ stub(client.base).my_fake_model(guid) {
85
+ {:entity => {:not_foo => "fizz"}}
86
+ }
54
87
 
55
- expect(myobject.foo).to eq "fizz"
88
+ expect(myobject.foo).to eq "fizz"
89
+ end
56
90
  end
57
91
  end
58
92
 
59
- context 'when it does not exist in the manifest' do
60
- let(:mymodel) {
61
- fake_model { attribute :foo, :object, :default => "foo" }
62
- }
93
+ describe 'writing' do
94
+ context 'when the attribute has a custom json key' do
95
+ let(:mymodel) {
96
+ fake_model { attribute :foo, :object, :at => :not_foo }
97
+ }
63
98
 
64
- subject { myobject.fake }
99
+ subject { myobject }
65
100
 
66
- it 'returns the default value' do
67
- expect(subject.foo).to eq "foo"
68
- end
69
- end
101
+ it "uses the 'at' value in the update payload" do
102
+ mock(client.base).put("v2", :my_fake_models, subject.guid, hash_including(:payload => {:not_foo => 123}))
103
+ subject.foo = 123
104
+ subject.update!
105
+ end
70
106
 
71
- context 'when the attribute has a custom json key' do
72
- let(:mymodel) {
73
- fake_model { attribute :foo, :object, :at => :not_foo }
74
- }
107
+ it "uses the 'at' value in the create payload" do
108
+ subject.foo = 123
75
109
 
76
- subject { myobject.fake }
110
+ mock(client.base).post(
111
+ "v2", :my_fake_models,
112
+ hash_including(:payload => {:not_foo => 123})
113
+ ) { {:metadata => {}} }
77
114
 
78
- it 'retrieves the attribute using the custom key' do
79
- stub(client.base).my_fake_model(guid) {
80
- { :entity => { :not_foo => "fizz" } }
81
- }
115
+ subject.create!
116
+ end
82
117
 
83
- expect(myobject.foo).to eq "fizz"
118
+ it "is then readable via the attribute name" do
119
+ subject.foo = 123
120
+ expect(subject.foo).to eq 123
121
+ end
84
122
  end
85
123
  end
86
124
  end
87
125
 
88
- describe 'writing' do
89
- context 'when the attribute has a custom json key' do
90
- let(:mymodel) {
91
- fake_model { attribute :foo, :object, :at => :not_foo }
92
- }
126
+ describe 'to_one relationships' do
127
+ describe 'writing' do
128
+ let!(:mymodel) { fake_model { to_one :foo } }
129
+ let!(:othermodel) { fake_model :foo }
93
130
 
94
- subject { myobject }
131
+ let(:myobject) { mymodel.new(nil, client).fake }
132
+ let(:otherobject) { othermodel.new(nil, client).fake }
95
133
 
96
- it "uses the 'at' value in the update payload" do
97
- mock(client.base).put("v2", :my_fake_models, subject.guid, hash_including(:payload => {:not_foo => 123}))
98
- subject.foo = 123
99
- subject.update!
100
- end
134
+ subject { myobject.foo = otherobject }
101
135
 
102
- it "uses the 'at' value in the create payload" do
103
- subject.foo = 123
136
+ it "sets the GUID in the manifest to the object's GUID" do
137
+ expect { subject }.to change {
138
+ myobject.manifest[:entity][:foo_guid]
139
+ }.to(otherobject.guid)
140
+ end
104
141
 
105
- mock(client.base).post(
106
- "v2", :my_fake_models,
107
- hash_including(:payload => {:not_foo => 123})
108
- ) { {:metadata => {}} }
142
+ it "tracks internal changes in the diff" do
143
+ expect { subject }.to change { myobject.diff }.to(
144
+ :foo_guid => otherobject.guid)
145
+ end
109
146
 
110
- subject.create!
147
+ it "tracks high-level changes in .changes" do
148
+ before = myobject.foo
149
+ expect { subject }.to change { myobject.changes }.to(
150
+ :foo => [before, otherobject])
111
151
  end
112
152
 
113
- it "is then readable via the attribute name" do
114
- subject.foo = 123
115
- expect(subject.foo).to eq 123
153
+ it "returns the assigned value" do
154
+ myobject.send(:foo=, otherobject).should == otherobject
116
155
  end
117
- end
118
- end
119
- end
120
156
 
121
- describe 'to_one relationships' do
122
- describe 'writing' do
123
- let!(:mymodel) { fake_model { to_one :foo } }
124
- let!(:othermodel) { fake_model :foo }
157
+ context "when there is a default" do
158
+ let(:mymodel) { fake_model { to_one :foo, :default => nil } }
125
159
 
126
- let(:myobject) { mymodel.new(nil, client).fake }
127
- let(:otherobject) { othermodel.new(nil, client).fake }
160
+ subject { myobject.foo = nil }
128
161
 
129
- subject { myobject.foo = otherobject }
162
+ it "allows setting to the default" do
163
+ myobject.foo = otherobject
130
164
 
131
- it "sets the GUID in the manifest to the object's GUID" do
132
- expect { subject }.to change {
133
- myobject.manifest[:entity][:foo_guid]
134
- }.to(otherobject.guid)
165
+ expect { subject }.to change {
166
+ myobject.manifest[:entity][:foo_guid]
167
+ }.from(otherobject.guid).to(nil)
168
+ end
169
+ end
135
170
  end
136
171
 
137
- it "tracks internal changes in the diff" do
138
- expect { subject }.to change { myobject.diff }.to(
139
- :foo_guid => otherobject.guid)
140
- end
172
+ describe 'associated create' do
173
+ let!(:model) { fake_model { to_one :associated } }
174
+ let(:instance) { model.new(nil, client).fake }
175
+ let!(:request) { WebMock.stub_request(:post, /v2\/associated/).to_return(:body => {:metadata => {:guid => "thing"}}.to_json) }
141
176
 
142
- it "tracks high-level changes in .changes" do
143
- before = myobject.foo
144
- expect { subject }.to change { myobject.changes }.to(
145
- :foo => [before, otherobject])
146
- end
177
+ it 'returns a new associated object' do
178
+ instance.create_associated.should be_a(Associated)
179
+ end
180
+
181
+ it 'sets the relation' do
182
+ created = instance.create_associated
183
+ instance.associated.should == created
184
+ end
147
185
 
148
- context "when there is a default" do
149
- let(:mymodel) { fake_model { to_one :foo, :default => nil } }
186
+ context 'with attributes for the association' do
187
+ it 'sets these attributes on the association' do
188
+ created = instance.create_associated(:attribute => 'value')
189
+ created.attribute.should == 'value'
190
+ end
191
+ end
150
192
 
151
- subject { myobject.foo = nil }
193
+ it 'calls out to cloud_controller' do
194
+ instance.create_associated
195
+ request.should have_been_requested
196
+ end
152
197
 
153
- it "allows setting to the default" do
154
- myobject.foo = otherobject
198
+ context 'when creation fails' do
199
+ let!(:request) { WebMock.stub_request(:post, /v2\/associated/).to_raise(:not_authorized) }
155
200
 
156
- expect { subject }.to change {
157
- myobject.manifest[:entity][:foo_guid]
158
- }.from(otherobject.guid).to(nil)
201
+ it 'raises an exception' do
202
+ expect { instance.create_associated }.to raise_error(StandardError)
203
+ end
159
204
  end
160
205
  end
161
206
  end
162
- end
163
207
 
164
- describe 'summarization for an arbitrary model' do
165
- let(:mymodel) { fake_model { attribute :foo, :string } }
166
- let(:summary_attributes) { { :foo => "abcd" } }
208
+ describe 'summarization for an arbitrary model' do
209
+ let(:mymodel) { fake_model { attribute :foo, :string } }
210
+ let(:summary_attributes) { {:foo => "abcd"} }
167
211
 
168
- subject { myobject }
212
+ subject { myobject }
169
213
 
170
- it_behaves_like 'a summarizeable model'
214
+ it_behaves_like 'a summarizeable model'
215
+ end
171
216
  end
172
217
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfoundry
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-05-24 00:00:00.000000000 Z
13
+ date: 2013-05-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: multipart-post
@@ -376,7 +376,7 @@ files:
376
376
  - spec/support/shared_examples/cc_api_stub_request_examples.rb
377
377
  - spec/support/shared_examples/client_login_examples.rb
378
378
  - spec/support/shared_examples/model_summary_examples.rb
379
- homepage: http://github.com/cloudfoundry/vmc-lib
379
+ homepage: http://github.com/cloudfoundry/cfoundry
380
380
  licenses: []
381
381
  post_install_message:
382
382
  rdoc_options: []
@@ -390,7 +390,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
390
390
  version: '0'
391
391
  segments:
392
392
  - 0
393
- hash: -667619740033887048
393
+ hash: 731683098158861932
394
394
  required_rubygems_version: !ruby/object:Gem::Requirement
395
395
  none: false
396
396
  requirements: