praxis-blueprints 3.2 → 3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,39 +1,49 @@
1
+ # frozen_string_literal: true
1
2
  lib = File.expand_path('../lib', __FILE__)
2
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
4
  require 'praxis-blueprints/version'
4
5
 
5
6
  Gem::Specification.new do |spec|
6
- spec.name = "praxis-blueprints"
7
+ spec.name = 'praxis-blueprints'
7
8
  spec.version = Praxis::BLUEPRINTS_VERSION
8
- spec.authors = ["Josep M. Blanquer","Dane Jensen"]
9
- spec.summary = %q{Attributes, views, rendering and example generation for common Blueprint Structures.}
10
- spec.description = "Praxis Blueprints is a library that allows for defining a reusable class structures that has a set of typed attributes and a set of views with which to render them. Instantiations of Blueprints resemble ruby Structs which respond to methods of the attribute names. Rendering is format-agnostic in that
11
- it results in a structured hash instead of an encoded string. Blueprints can automatically generate object structures that follow the attribute definitions."
12
- spec.email = ["blanquer@gmail.com","dane.jensen@gmail.com"]
9
+ spec.authors = ['Josep M. Blanquer', 'Dane Jensen']
10
+ spec.summary = 'Attributes, views, rendering and example generation for common Blueprint Structures.'
11
+ spec.description = <<-EOF
12
+ Praxis Blueprints is a library that allows for defining a reusable class
13
+ structures that has a set of typed attributes and a set of views with which
14
+ to render them. Instantiations of Blueprints resemble ruby Structs which
15
+ respond to methods of the attribute names. Rendering is format-agnostic in
16
+ that it results in a structured hash instead of an encoded string.
17
+ Blueprints can automatically generate object structures that follow the
18
+ attribute definitions.
19
+ EOF
20
+ spec.email = ['blanquer@gmail.com', 'dane.jensen@gmail.com']
13
21
 
14
- spec.homepage = "https://github.com/rightscale/praxis-blueprints"
15
- spec.license = "MIT"
16
- spec.required_ruby_version = ">=2.1"
22
+ spec.homepage = 'https://github.com/rightscale/praxis-blueprints'
23
+ spec.license = 'MIT'
24
+ spec.required_ruby_version = '>=2.1'
17
25
 
18
26
  spec.files = `git ls-files -z`.split("\x0")
19
27
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ["lib"]
28
+ spec.require_paths = ['lib']
21
29
 
22
- spec.add_runtime_dependency(%q<randexp>, ["~> 0"])
23
- spec.add_runtime_dependency(%q<attributor>, [">= 5.0.2"])
24
- spec.add_runtime_dependency(%q<activesupport>, [">= 3"])
30
+ spec.add_runtime_dependency('randexp', ['~> 0'])
31
+ spec.add_runtime_dependency('attributor', ['>= 5.1'])
32
+ spec.add_runtime_dependency('activesupport', ['>= 3'])
25
33
 
26
- spec.add_development_dependency "bundler", "~> 1.6"
27
- spec.add_development_dependency "rake", "~> 0"
34
+ spec.add_development_dependency 'bundler', '~> 1.6'
35
+ spec.add_development_dependency 'rake', '~> 0'
28
36
 
29
- spec.add_development_dependency(%q<redcarpet>, ["< 3.0"])
30
- spec.add_development_dependency(%q<yard>, ["~> 0.8.7"])
31
- spec.add_development_dependency(%q<guard>, ["~> 2"])
32
- spec.add_development_dependency(%q<guard-rspec>, [">= 0"])
33
- spec.add_development_dependency(%q<rspec>, ["< 2.99"])
34
- spec.add_development_dependency(%q<pry>, ["~> 0"])
35
- spec.add_development_dependency(%q<pry-byebug>, ["~> 1"])
36
- spec.add_development_dependency(%q<pry-stack_explorer>, ["~> 0"])
37
- spec.add_development_dependency(%q<fuubar>, ["~> 1"])
38
- spec.add_development_dependency(%q<coveralls>)
37
+ spec.add_development_dependency('redcarpet', ['< 3.0'])
38
+ spec.add_development_dependency('yard', ['~> 0.8.7'])
39
+ spec.add_development_dependency('guard', ['~> 2'])
40
+ spec.add_development_dependency('guard-rspec', ['>= 0'])
41
+ spec.add_development_dependency('rspec', ['< 2.99'])
42
+ spec.add_development_dependency('pry', ['~> 0'])
43
+ spec.add_development_dependency('pry-byebug', ['~> 1'])
44
+ spec.add_development_dependency('pry-stack_explorer', ['~> 0'])
45
+ spec.add_development_dependency('fuubar', ['~> 1'])
46
+ spec.add_development_dependency('coveralls')
47
+ spec.add_development_dependency 'rubocop'
48
+ spec.add_development_dependency 'guard-rubocop'
39
49
  end
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
3
 
3
4
  describe Praxis::Blueprint do
4
-
5
5
  subject(:blueprint_class) { Person }
6
6
 
7
- its(:family){ should eq('hash') }
7
+ its(:family) { should eq('hash') }
8
8
 
9
9
  context 'deterministic examples' do
10
10
  it 'works' do
@@ -52,7 +52,6 @@ describe Praxis::Blueprint do
52
52
  its(:finalized?) { should be(true) }
53
53
  end
54
54
 
55
-
56
55
  context '.finalize on that subclass' do
57
56
  before do
58
57
  blueprint_class.should_receive(:_finalize!).and_call_original
@@ -60,9 +59,7 @@ describe Praxis::Blueprint do
60
59
  end
61
60
 
62
61
  its(:finalized?) { should be(true) }
63
-
64
62
  end
65
-
66
63
  end
67
64
 
68
65
  context 'creating a base abstract Blueprint class without attributes' do
@@ -76,7 +73,6 @@ describe Praxis::Blueprint do
76
73
  blueprint_class.finalize!
77
74
  blueprint_class.finalized?.should be(true)
78
75
  end
79
-
80
76
  end
81
77
 
82
78
  it 'has an inner Struct class for the attributes' do
@@ -88,7 +84,6 @@ describe Praxis::Blueprint do
88
84
  it 'sorta has view objects' do
89
85
  blueprint_class.views.should have_key(:default)
90
86
  end
91
-
92
87
  end
93
88
 
94
89
  context 'an instance' do
@@ -113,24 +108,22 @@ describe Praxis::Blueprint do
113
108
  end
114
109
  end
115
110
 
116
-
117
111
  context 'from Blueprint.example' do
118
112
  subject(:blueprint_instance) { blueprint_class.example }
119
113
  it_behaves_like 'a blueprint instance'
120
114
  end
121
115
 
122
116
  context 'wrapping an object' do
123
-
124
117
  let(:data) do
125
118
  {
126
119
  name: 'Bob',
127
120
  full_name: FullName.example,
128
121
  address: Address.example,
129
- email: "bob@example.com",
122
+ email: 'bob@example.com',
130
123
  aliases: [],
131
124
  prior_addresses: [],
132
- parents: { father: Randgen.first_name, mother: Randgen.first_name},
133
- href: "www.example.com",
125
+ parents: { father: Randgen.first_name, mother: Randgen.first_name },
126
+ href: 'www.example.com',
134
127
  alive: true
135
128
  }
136
129
  end
@@ -139,7 +132,6 @@ describe Praxis::Blueprint do
139
132
 
140
133
  subject(:blueprint_instance) { blueprint_class.new(resource) }
141
134
 
142
-
143
135
  it_behaves_like 'a blueprint instance'
144
136
 
145
137
  context 'creating additional blueprint instances from that object' do
@@ -148,7 +140,7 @@ describe Praxis::Blueprint do
148
140
  context 'with caching enabled' do
149
141
  around do |example|
150
142
  Praxis::Blueprint.caching_enabled = true
151
- Praxis::Blueprint.cache = Hash.new { |h,k| h[k] = Hash.new }
143
+ Praxis::Blueprint.cache = Hash.new { |h, k| h[k] = {} }
152
144
  example.run
153
145
 
154
146
  Praxis::Blueprint.caching_enabled = false
@@ -165,15 +157,12 @@ describe Praxis::Blueprint do
165
157
  context 'with caching disabled' do
166
158
  it { should_not be blueprint_instance }
167
159
  end
168
-
169
160
  end
170
-
171
161
  end
172
-
173
162
  end
174
163
 
175
164
  context '.describe' do
176
- let(:shallow ) { false }
165
+ let(:shallow) { false }
177
166
  let(:example_object) { nil }
178
167
 
179
168
  before do
@@ -187,18 +176,17 @@ describe Praxis::Blueprint do
187
176
  expect(blueprint_class.attribute.type).to receive(:describe).with(true, example: example_object).twice.and_call_original
188
177
  end
189
178
 
190
- subject(:output){ blueprint_class.describe }
179
+ subject(:output) { blueprint_class.describe }
191
180
 
192
- its([:name]){ should eq(blueprint_class.name)}
193
- its([:id]){ should eq(blueprint_class.id)}
194
- its([:views]){ should be_kind_of(Hash)}
195
- its(:keys){ should_not include(:anonymous) }
181
+ its([:name]) { should eq(blueprint_class.name) }
182
+ its([:id]) { should eq(blueprint_class.id) }
183
+ its([:views]) { should be_kind_of(Hash) }
184
+ its(:keys) { should_not include(:anonymous) }
196
185
  it 'should contain the an entry for each view' do
197
186
  subject[:views].keys.should include(:default, :current, :extended, :master)
198
187
  end
199
188
  end
200
189
 
201
-
202
190
  context 'for shallow descriptions' do
203
191
  let(:shallow) { true }
204
192
 
@@ -218,8 +206,8 @@ describe Praxis::Blueprint do
218
206
  end
219
207
  it 'reports their anonymous-ness' do
220
208
  description = blueprint_class.describe(true)
221
- expect( description ).to have_key(:anonymous)
222
- expect( description[:anonymous] ).to be(true)
209
+ expect(description).to have_key(:anonymous)
210
+ expect(description[:anonymous]).to be(true)
223
211
  end
224
212
  end
225
213
  end
@@ -241,8 +229,10 @@ describe Praxis::Blueprint do
241
229
  output[:attributes][:name][:example].should eq example.name
242
230
  output[:attributes][:age][:example].should eq example.age
243
231
 
232
+ output[:attributes][:aliases].should have_key(:example)
233
+ output[:attributes][:aliases][:example].should eq example.aliases.dump
234
+
244
235
  output[:attributes][:full_name].should_not have_key(:example)
245
- output[:attributes][:aliases].should_not have_key(:example)
246
236
 
247
237
  parents_attributes = output[:attributes][:parents][:type][:attributes]
248
238
  parents_attributes[:father][:example].should eq example.parents.father
@@ -252,7 +242,7 @@ describe Praxis::Blueprint do
252
242
  end
253
243
 
254
244
  context '.validate' do
255
- let(:hash) { {name: 'bob'} }
245
+ let(:hash) { { name: 'bob' } }
256
246
  let(:person) { Person.load(hash) }
257
247
  subject(:errors) { person.validate }
258
248
 
@@ -261,7 +251,7 @@ describe Praxis::Blueprint do
261
251
  end
262
252
 
263
253
  context 'with invalid sub-attribute' do
264
- let(:hash) { {name: 'bob', address: {state: "ME"}} }
254
+ let(:hash) { { name: 'bob', address: { state: 'ME' } } }
265
255
 
266
256
  it { should have(1).item }
267
257
  its(:first) { should =~ /Attribute \$.address.state/ }
@@ -269,9 +259,9 @@ describe Praxis::Blueprint do
269
259
 
270
260
  context 'for objects of the wrong type' do
271
261
  it 'raises an error' do
272
- expect {
262
+ expect do
273
263
  Person.validate(Object.new)
274
- }.to raise_error(ArgumentError, /Error validating .* as Person for an object of type Object/)
264
+ end.to raise_error(ArgumentError, /Error validating .* as Person for an object of type Object/)
275
265
  end
276
266
  end
277
267
  end
@@ -279,9 +269,9 @@ describe Praxis::Blueprint do
279
269
  context '.load' do
280
270
  let(:hash) do
281
271
  {
282
- :name => 'Bob',
283
- :full_name => {:first => 'Robert', :last => 'Robertson'},
284
- :address => {:street => 'main', :state => 'OR'}
272
+ name: 'Bob',
273
+ full_name: { first: 'Robert', last: 'Robertson' },
274
+ address: { street: 'main', state: 'OR' }
285
275
  }
286
276
  end
287
277
  subject(:person) { Person.load(hash) }
@@ -298,19 +288,16 @@ describe Praxis::Blueprint do
298
288
  it { should be_kind_of(FullName) }
299
289
  end
300
290
  end
301
-
302
291
  end
303
292
 
304
-
305
293
  context 'decorators' do
306
294
  let(:name) { 'Soren II' }
307
295
 
308
296
  let(:object) { Person.example.object }
309
297
  subject(:person) { Person.new(object, decorators) }
310
298
 
311
-
312
299
  context 'as a hash' do
313
- let(:decorators) { {name: name} }
300
+ let(:decorators) { { name: name } }
314
301
  it do
315
302
  person.name.should eq('Soren II')
316
303
  end
@@ -318,7 +305,7 @@ describe Praxis::Blueprint do
318
305
  its(:name) { should be(name) }
319
306
 
320
307
  context 'an additional instance with the equivalent hash' do
321
- subject(:additional_person) { Person.new(object, {name: name}) }
308
+ subject(:additional_person) { Person.new(object, name: name) }
322
309
  it { should_not be person }
323
310
  end
324
311
 
@@ -334,7 +321,7 @@ describe Praxis::Blueprint do
334
321
  end
335
322
 
336
323
  context 'as an object' do
337
- let(:decorators) { double("decorators", name: name) }
324
+ let(:decorators) { double('decorators', name: name) }
338
325
  its(:name) { should be(name) }
339
326
 
340
327
  context 'an additional instance with the same object' do
@@ -342,13 +329,10 @@ describe Praxis::Blueprint do
342
329
  it { should_not be person }
343
330
  end
344
331
  end
345
-
346
332
  end
347
333
 
348
-
349
334
  context 'with a provided :reference option on attributes' do
350
335
  context 'that does not match the value set on the class' do
351
-
352
336
  subject(:mismatched_reference) do
353
337
  Class.new(Praxis::Blueprint) do
354
338
  self.reference = Class.new(Praxis::Blueprint)
@@ -357,15 +341,13 @@ describe Praxis::Blueprint do
357
341
  end
358
342
 
359
343
  it 'should raise an error' do
360
- expect {
344
+ expect do
361
345
  mismatched_reference.attributes
362
- }.to raise_error
346
+ end.to raise_error
363
347
  end
364
-
365
348
  end
366
349
  end
367
350
 
368
-
369
351
  context '.example' do
370
352
  context 'with some attribute values provided' do
371
353
  let(:name) { 'Sir Bobbert' }
@@ -377,7 +359,6 @@ describe Praxis::Blueprint do
377
359
  context '.render' do
378
360
  let(:person) { Person.example('1') }
379
361
  it 'is an alias to dump' do
380
-
381
362
  person.object.contents
382
363
  rendered = Person.render(person, view: :default)
383
364
  dumped = Person.dump(person, view: :default)
@@ -391,10 +372,7 @@ describe Praxis::Blueprint do
391
372
  let(:render_opts) { {} }
392
373
  subject(:output) { person.render(view: view_name, **render_opts) }
393
374
 
394
-
395
-
396
375
  context 'with a sub-attribute that is a blueprint' do
397
-
398
376
  it { should have_key(:name) }
399
377
  it { should have_key(:address) }
400
378
  it 'renders the sub-attribute correctly' do
@@ -403,14 +381,13 @@ describe Praxis::Blueprint do
403
381
  end
404
382
 
405
383
  it 'reports a dump error with the appropriate context' do
406
- person.address.should_receive(:state).and_raise("Kaboom")
407
- expect {
384
+ person.address.should_receive(:state).and_raise('Kaboom')
385
+ expect do
408
386
  person.render(view: view_name, context: ['special_root'])
409
- }.to raise_error(/Error while dumping attribute state of type Address for context special_root.address. Reason: .*Kaboom/)
387
+ end.to raise_error(/Error while dumping attribute state of type Address for context special_root.address. Reason: .*Kaboom/)
410
388
  end
411
389
  end
412
390
 
413
-
414
391
  context 'with sub-attribute that is an Attributor::Model' do
415
392
  it { should have_key(:full_name) }
416
393
  it 'renders the model correctly' do
@@ -422,7 +399,7 @@ describe Praxis::Blueprint do
422
399
 
423
400
  context 'using the `fields` option' do
424
401
  context 'as a hash' do
425
- subject(:output) { person.render(fields: {address: {state: true}}) }
402
+ subject(:output) { person.render(fields: { address: { state: true } }) }
426
403
  it 'should only have the address rendered' do
427
404
  output.keys.should eq [:address]
428
405
  end
@@ -438,5 +415,4 @@ describe Praxis::Blueprint do
438
415
  end
439
416
  end
440
417
  end
441
-
442
418
  end
@@ -1,17 +1,16 @@
1
+ # frozen_string_literal: true
1
2
  require_relative '../spec_helper'
2
3
 
3
4
  describe Praxis::CollectionView do
4
-
5
5
  let(:root_context) { ['people'] }
6
6
 
7
7
  let(:people) do
8
- 3.times.collect do |i|
9
- context = ["people", "at(#{i})"]
8
+ Array.new(3) do |i|
9
+ context = ['people', "at(#{i})"]
10
10
  Person.example(context)
11
11
  end
12
12
  end
13
13
 
14
-
15
14
  let(:contents_definition) do
16
15
  proc do
17
16
  attribute :name
@@ -28,16 +27,14 @@ describe Praxis::CollectionView do
28
27
  end
29
28
 
30
29
  context 'creating from a member view' do
31
-
32
30
  it 'gets the proper contents' do
33
31
  collection_view.contents.should eq member_view.contents
34
32
  end
35
33
 
36
34
  context 'lazy initializes its contents' do
37
-
38
35
  it 'so it will not call contents until it is first needed' do
39
- member_view.stub(:contents){ raise 'No!' }
40
- expect{ collection_view.name }.to_not raise_error
36
+ member_view.stub(:contents) { raise 'No!' }
37
+ expect { collection_view.name }.to_not raise_error
41
38
  end
42
39
  it 'when contents is needed, it will clone it from the member_view' do
43
40
  # Twice is because we're callong member_view.contents for the right side of the equality
@@ -61,7 +58,7 @@ describe Praxis::CollectionView do
61
58
  subject(:output) { collection_view.render(people, context: root_context) }
62
59
 
63
60
  it { should be_kind_of(Array) }
64
- it { should eq people.collect {|person| member_view.render(person)} }
61
+ it { should eq people.collect { |person| member_view.render(person) } }
65
62
  end
66
63
 
67
64
  context '#example' do
@@ -82,5 +79,4 @@ describe Praxis::CollectionView do
82
79
  its([:attributes]) { should eq(member_view.describe[:attributes]) }
83
80
  its([:type]) { should eq(:collection) }
84
81
  end
85
-
86
82
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
+
4
+ describe Praxis::ConfigHash do
5
+ subject(:instance) { Praxis::ConfigHash.new(hash, &block) }
6
+ let(:hash) { { one: ['existing'], two: 'dos' } }
7
+ let(:block) do
8
+ proc { 'abc' }
9
+ end
10
+
11
+ context 'initialization' do
12
+ it 'saves the passed hash' do
13
+ expect(subject.hash).to be(hash)
14
+ end
15
+ end
16
+
17
+ context '.from' do
18
+ subject(:instance) { Praxis::ConfigHash.from(hash, &block) }
19
+ it 'returns an instance' do
20
+ expect(subject).to be_kind_of(Praxis::ConfigHash)
21
+ expect(subject.hash).to be(hash)
22
+ end
23
+ end
24
+
25
+ context '#to_hash' do
26
+ let(:block) do
27
+ proc { hash['i_was'] = 'here' }
28
+ end
29
+ it 'evaluates the block and returns the resulting hash' do
30
+ expect(subject.to_hash).to eq(subject.hash)
31
+ expect(subject.hash['i_was']).to eq('here')
32
+ end
33
+ end
34
+
35
+ context '#method_missing' do
36
+ context 'when keys do not exist in the hash key' do
37
+ it 'sets a single value to the hash' do
38
+ subject.some_name 'someval'
39
+ expect(subject.hash[:some_name]).to eq('someval')
40
+ end
41
+ it 'sets a multiple values to the hash key' do
42
+ subject.some_name 'someval', 'other1', 'other2'
43
+ expect(subject.hash[:some_name]).to include('someval', 'other1', 'other2')
44
+ end
45
+ end
46
+ context 'when keys already exist in the hash key' do
47
+ it 'adds one value to the hash' do
48
+ subject.one'newval'
49
+ expect(subject.hash[:one]).to match_array(%w(existing newval))
50
+ end
51
+ it 'adds multiple values to the hash key' do
52
+ subject.one 'newval', 'other1', 'other2'
53
+ expect(subject.hash[:one]).to match_array(%w(existing newval other1 other2))
54
+ end
55
+ context 'when passing a value and a block' do
56
+ let(:my_block) { proc {} }
57
+ it 'adds the tuple to the hash key' do
58
+ subject.one 'val', &my_block
59
+ expect(subject.hash[:one]).to include(['val', my_block])
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end