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.
- data/lib/cfoundry/v2/model_magic.rb +28 -21
- data/lib/cfoundry/version.rb +1 -1
- data/spec/cfoundry/v2/model_magic_spec.rb +155 -110
- metadata +4 -4
@@ -190,11 +190,7 @@ module CFoundry::V2
|
|
190
190
|
def to_one(name, opts = {})
|
191
191
|
to_one_relations[name] = opts
|
192
192
|
|
193
|
-
|
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_#{
|
206
|
+
@client.send(:"make_#{association_name}", @manifest[:entity][name])
|
211
207
|
elsif url = send("#{name}_url")
|
212
|
-
@client.send(:"#{
|
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 |
|
223
|
-
klass = self.class.objects[
|
228
|
+
define_method(:"#{name}=") do |assigned_value|
|
229
|
+
klass = self.class.objects[association_name]
|
224
230
|
|
225
|
-
unless has_default &&
|
226
|
-
CFoundry::Validator.validate_type(
|
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
|
-
|
233
|
-
|
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,
|
243
|
+
@cache[name] || klass.new(@client, old_guid, @manifest[:entity][name])
|
236
244
|
|
237
|
-
@changes[name] = [old_obj,
|
245
|
+
@changes[name] = [old_obj, assigned_value]
|
238
246
|
end
|
239
247
|
|
240
|
-
@cache[name] =
|
248
|
+
@cache[name] = assigned_value
|
241
249
|
|
242
|
-
@manifest[:entity][:"#{name}_guid"] =
|
243
|
-
|
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.
|
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)
|
data/lib/cfoundry/version.rb
CHANGED
@@ -1,172 +1,217 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
14
|
+
describe 'attributes' do
|
15
|
+
describe 'reading' do
|
16
|
+
let(:mymodel) { fake_model { attribute :foo, :object } }
|
12
17
|
|
13
|
-
|
14
|
-
|
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
|
-
|
17
|
-
|
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 '
|
21
|
-
|
22
|
-
|
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
|
-
|
56
|
+
expect(myobject.foo).to eq "fizz"
|
26
57
|
|
27
|
-
|
28
|
-
|
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 '
|
64
|
+
context 'when it does not exist in the manifest' do
|
33
65
|
let(:mymodel) {
|
34
|
-
fake_model { attribute :foo, :object, :default =>
|
66
|
+
fake_model { attribute :foo, :object, :default => "foo" }
|
35
67
|
}
|
36
68
|
|
37
|
-
subject { myobject.fake
|
69
|
+
subject { myobject.fake }
|
38
70
|
|
39
|
-
it 'returns
|
40
|
-
expect(subject.foo).to eq
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
81
|
+
subject { myobject.fake }
|
52
82
|
|
53
|
-
|
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
|
-
|
88
|
+
expect(myobject.foo).to eq "fizz"
|
89
|
+
end
|
56
90
|
end
|
57
91
|
end
|
58
92
|
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
99
|
+
subject { myobject }
|
65
100
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
72
|
-
|
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
|
-
|
110
|
+
mock(client.base).post(
|
111
|
+
"v2", :my_fake_models,
|
112
|
+
hash_including(:payload => {:not_foo => 123})
|
113
|
+
) { {:metadata => {}} }
|
77
114
|
|
78
|
-
|
79
|
-
|
80
|
-
{ :entity => { :not_foo => "fizz" } }
|
81
|
-
}
|
115
|
+
subject.create!
|
116
|
+
end
|
82
117
|
|
83
|
-
|
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 '
|
89
|
-
|
90
|
-
let(:mymodel) {
|
91
|
-
|
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
|
-
|
131
|
+
let(:myobject) { mymodel.new(nil, client).fake }
|
132
|
+
let(:otherobject) { othermodel.new(nil, client).fake }
|
95
133
|
|
96
|
-
|
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 "
|
103
|
-
subject.
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
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 "
|
114
|
-
|
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
|
-
|
122
|
-
|
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
|
-
|
127
|
-
let(:otherobject) { othermodel.new(nil, client).fake }
|
160
|
+
subject { myobject.foo = nil }
|
128
161
|
|
129
|
-
|
162
|
+
it "allows setting to the default" do
|
163
|
+
myobject.foo = otherobject
|
130
164
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
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
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
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
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
-
|
149
|
-
|
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
|
-
|
193
|
+
it 'calls out to cloud_controller' do
|
194
|
+
instance.create_associated
|
195
|
+
request.should have_been_requested
|
196
|
+
end
|
152
197
|
|
153
|
-
|
154
|
-
|
198
|
+
context 'when creation fails' do
|
199
|
+
let!(:request) { WebMock.stub_request(:post, /v2\/associated/).to_raise(:not_authorized) }
|
155
200
|
|
156
|
-
|
157
|
-
|
158
|
-
|
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
|
-
|
165
|
-
|
166
|
-
|
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
|
-
|
212
|
+
subject { myobject }
|
169
213
|
|
170
|
-
|
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.
|
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-
|
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/
|
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:
|
393
|
+
hash: 731683098158861932
|
394
394
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
395
395
|
none: false
|
396
396
|
requirements:
|