cfoundry 1.3.0 → 1.4.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.
@@ -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: