virtus2 2.0.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 +39 -0
- data/.rspec +2 -0
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +18 -0
- data/Changelog.md +258 -0
- data/Gemfile +10 -0
- data/Guardfile +19 -0
- data/LICENSE +20 -0
- data/README.md +630 -0
- data/Rakefile +15 -0
- data/TODO.md +6 -0
- data/lib/virtus/attribute/accessor.rb +103 -0
- data/lib/virtus/attribute/boolean.rb +55 -0
- data/lib/virtus/attribute/builder.rb +182 -0
- data/lib/virtus/attribute/coercer.rb +45 -0
- data/lib/virtus/attribute/coercible.rb +20 -0
- data/lib/virtus/attribute/collection.rb +103 -0
- data/lib/virtus/attribute/default_value/from_callable.rb +35 -0
- data/lib/virtus/attribute/default_value/from_clonable.rb +35 -0
- data/lib/virtus/attribute/default_value/from_symbol.rb +35 -0
- data/lib/virtus/attribute/default_value.rb +51 -0
- data/lib/virtus/attribute/embedded_value.rb +67 -0
- data/lib/virtus/attribute/enum.rb +45 -0
- data/lib/virtus/attribute/hash.rb +130 -0
- data/lib/virtus/attribute/lazy_default.rb +18 -0
- data/lib/virtus/attribute/nullify_blank.rb +24 -0
- data/lib/virtus/attribute/strict.rb +26 -0
- data/lib/virtus/attribute.rb +245 -0
- data/lib/virtus/attribute_set.rb +240 -0
- data/lib/virtus/builder/hook_context.rb +51 -0
- data/lib/virtus/builder.rb +133 -0
- data/lib/virtus/class_inclusions.rb +48 -0
- data/lib/virtus/class_methods.rb +90 -0
- data/lib/virtus/coercer.rb +41 -0
- data/lib/virtus/configuration.rb +72 -0
- data/lib/virtus/const_missing_extensions.rb +18 -0
- data/lib/virtus/extensions.rb +105 -0
- data/lib/virtus/instance_methods.rb +218 -0
- data/lib/virtus/model.rb +68 -0
- data/lib/virtus/module_extensions.rb +88 -0
- data/lib/virtus/support/equalizer.rb +128 -0
- data/lib/virtus/support/options.rb +113 -0
- data/lib/virtus/support/type_lookup.rb +109 -0
- data/lib/virtus/value_object.rb +150 -0
- data/lib/virtus/version.rb +3 -0
- data/lib/virtus.rb +310 -0
- data/spec/integration/attributes_attribute_spec.rb +28 -0
- data/spec/integration/building_module_spec.rb +90 -0
- data/spec/integration/collection_member_coercion_spec.rb +96 -0
- data/spec/integration/custom_attributes_spec.rb +42 -0
- data/spec/integration/custom_collection_attributes_spec.rb +101 -0
- data/spec/integration/default_values_spec.rb +87 -0
- data/spec/integration/defining_attributes_spec.rb +86 -0
- data/spec/integration/embedded_value_spec.rb +50 -0
- data/spec/integration/extending_objects_spec.rb +35 -0
- data/spec/integration/hash_attributes_coercion_spec.rb +54 -0
- data/spec/integration/inheritance_spec.rb +42 -0
- data/spec/integration/injectible_coercers_spec.rb +48 -0
- data/spec/integration/mass_assignment_with_accessors_spec.rb +44 -0
- data/spec/integration/overriding_virtus_spec.rb +46 -0
- data/spec/integration/required_attributes_spec.rb +25 -0
- data/spec/integration/struct_as_embedded_value_spec.rb +28 -0
- data/spec/integration/using_modules_spec.rb +55 -0
- data/spec/integration/value_object_with_custom_constructor_spec.rb +42 -0
- data/spec/integration/virtus/instance_level_attributes_spec.rb +23 -0
- data/spec/integration/virtus/value_object_spec.rb +99 -0
- data/spec/shared/constants_helpers.rb +9 -0
- data/spec/shared/freeze_method_behavior.rb +40 -0
- data/spec/shared/idempotent_method_behaviour.rb +5 -0
- data/spec/shared/options_class_method.rb +19 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/unit/virtus/attribute/boolean/coerce_spec.rb +43 -0
- data/spec/unit/virtus/attribute/boolean/value_coerced_predicate_spec.rb +25 -0
- data/spec/unit/virtus/attribute/class_methods/build_spec.rb +180 -0
- data/spec/unit/virtus/attribute/class_methods/coerce_spec.rb +32 -0
- data/spec/unit/virtus/attribute/coerce_spec.rb +129 -0
- data/spec/unit/virtus/attribute/coercible_predicate_spec.rb +20 -0
- data/spec/unit/virtus/attribute/collection/class_methods/build_spec.rb +105 -0
- data/spec/unit/virtus/attribute/collection/coerce_spec.rb +74 -0
- data/spec/unit/virtus/attribute/collection/value_coerced_predicate_spec.rb +31 -0
- data/spec/unit/virtus/attribute/comparison_spec.rb +20 -0
- data/spec/unit/virtus/attribute/custom_collection_spec.rb +29 -0
- data/spec/unit/virtus/attribute/defined_spec.rb +20 -0
- data/spec/unit/virtus/attribute/embedded_value/class_methods/build_spec.rb +70 -0
- data/spec/unit/virtus/attribute/embedded_value/coerce_spec.rb +91 -0
- data/spec/unit/virtus/attribute/get_spec.rb +32 -0
- data/spec/unit/virtus/attribute/hash/class_methods/build_spec.rb +106 -0
- data/spec/unit/virtus/attribute/hash/coerce_spec.rb +92 -0
- data/spec/unit/virtus/attribute/lazy_predicate_spec.rb +20 -0
- data/spec/unit/virtus/attribute/rename_spec.rb +16 -0
- data/spec/unit/virtus/attribute/required_predicate_spec.rb +19 -0
- data/spec/unit/virtus/attribute/set_default_value_spec.rb +107 -0
- data/spec/unit/virtus/attribute/set_spec.rb +29 -0
- data/spec/unit/virtus/attribute/value_coerced_predicate_spec.rb +19 -0
- data/spec/unit/virtus/attribute_set/append_spec.rb +47 -0
- data/spec/unit/virtus/attribute_set/define_reader_method_spec.rb +36 -0
- data/spec/unit/virtus/attribute_set/define_writer_method_spec.rb +36 -0
- data/spec/unit/virtus/attribute_set/each_spec.rb +65 -0
- data/spec/unit/virtus/attribute_set/element_reference_spec.rb +17 -0
- data/spec/unit/virtus/attribute_set/element_set_spec.rb +64 -0
- data/spec/unit/virtus/attribute_set/merge_spec.rb +34 -0
- data/spec/unit/virtus/attribute_set/reset_spec.rb +71 -0
- data/spec/unit/virtus/attribute_spec.rb +229 -0
- data/spec/unit/virtus/attributes_reader_spec.rb +41 -0
- data/spec/unit/virtus/attributes_writer_spec.rb +51 -0
- data/spec/unit/virtus/class_methods/finalize_spec.rb +67 -0
- data/spec/unit/virtus/class_methods/new_spec.rb +39 -0
- data/spec/unit/virtus/config_spec.rb +13 -0
- data/spec/unit/virtus/element_reader_spec.rb +21 -0
- data/spec/unit/virtus/element_writer_spec.rb +19 -0
- data/spec/unit/virtus/freeze_spec.rb +41 -0
- data/spec/unit/virtus/model_spec.rb +197 -0
- data/spec/unit/virtus/module_spec.rb +174 -0
- data/spec/unit/virtus/set_default_attributes_spec.rb +32 -0
- data/spec/unit/virtus/value_object_spec.rb +138 -0
- data/virtus2.gemspec +26 -0
- metadata +225 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'custom attributes' do
|
4
|
+
|
5
|
+
before do
|
6
|
+
module Examples
|
7
|
+
class NoisyString < Virtus::Attribute
|
8
|
+
lazy true
|
9
|
+
|
10
|
+
def coerce(input)
|
11
|
+
input.to_s.upcase
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class RegularExpression < Virtus::Attribute
|
16
|
+
primitive Regexp
|
17
|
+
end
|
18
|
+
|
19
|
+
class User
|
20
|
+
include Virtus
|
21
|
+
|
22
|
+
attribute :name, String
|
23
|
+
attribute :scream, NoisyString
|
24
|
+
attribute :expression, RegularExpression
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
subject { Examples::User.new }
|
30
|
+
|
31
|
+
specify 'allows you to define custom attributes' do
|
32
|
+
regexp = /awesome/
|
33
|
+
subject.expression = regexp
|
34
|
+
expect(subject.expression).to eq(regexp)
|
35
|
+
end
|
36
|
+
|
37
|
+
specify 'allows you to define coercion methods' do
|
38
|
+
subject.scream = 'welcome'
|
39
|
+
expect(subject.scream).to eq('WELCOME')
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'custom collection attributes' do
|
4
|
+
let(:library) { Examples::Library.new }
|
5
|
+
let(:books) { library.books }
|
6
|
+
|
7
|
+
before do
|
8
|
+
module Examples end
|
9
|
+
Examples.const_set 'BookCollection', book_collection_class
|
10
|
+
|
11
|
+
module Examples
|
12
|
+
class Book
|
13
|
+
include Virtus
|
14
|
+
|
15
|
+
attribute :title, String
|
16
|
+
end
|
17
|
+
|
18
|
+
class BookCollectionAttribute < Virtus::Attribute::Collection
|
19
|
+
primitive BookCollection
|
20
|
+
end
|
21
|
+
|
22
|
+
class Library
|
23
|
+
include Virtus
|
24
|
+
|
25
|
+
attribute :books, BookCollection[Book]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
after do
|
31
|
+
[:BookCollectionAttribute, :BookCollection, :Book, :Library].each do |const|
|
32
|
+
Examples.send(:remove_const, const)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
shared_examples_for 'a collection' do
|
37
|
+
it 'can be used as Virtus attributes' do
|
38
|
+
attribute = Examples::Library.attribute_set[:books]
|
39
|
+
expect(attribute).to be_kind_of(Examples::BookCollectionAttribute)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'defaults to an empty collection' do
|
43
|
+
books_should_be_an_empty_collection
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'coerces nil' do
|
47
|
+
library.books = nil
|
48
|
+
books_should_be_an_empty_collection
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'coerces an empty array' do
|
52
|
+
library.books = []
|
53
|
+
books_should_be_an_empty_collection
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'coerces an array of attribute hashes' do
|
57
|
+
library.books = [{ :title => 'Foo' }]
|
58
|
+
expect(books).to be_kind_of(Examples::BookCollection)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'coerces its members' do
|
62
|
+
library.books = [{ :title => 'Foo' }]
|
63
|
+
expect(books.count).to eq(1)
|
64
|
+
expect(books.first).to be_kind_of(Examples::Book)
|
65
|
+
end
|
66
|
+
|
67
|
+
def books_should_be_an_empty_collection
|
68
|
+
expect(books).to be_kind_of(Examples::BookCollection)
|
69
|
+
expect(books.count).to eq(0)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'with an array subclass' do
|
74
|
+
let(:book_collection_class) { Class.new(Array) }
|
75
|
+
|
76
|
+
it_behaves_like 'a collection'
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with an enumerable' do
|
80
|
+
require 'forwardable'
|
81
|
+
|
82
|
+
let(:book_collection_class) {
|
83
|
+
Class.new do
|
84
|
+
extend Forwardable
|
85
|
+
include Enumerable
|
86
|
+
|
87
|
+
def_delegators :@array, :each, :<<
|
88
|
+
|
89
|
+
def initialize(*args)
|
90
|
+
@array = Array[*args]
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.[](*args)
|
94
|
+
new(*args)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
}
|
98
|
+
|
99
|
+
it_behaves_like 'a collection'
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "default values" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
module Examples
|
7
|
+
|
8
|
+
class Reference
|
9
|
+
include Virtus::ValueObject
|
10
|
+
|
11
|
+
attribute :ref, String
|
12
|
+
end
|
13
|
+
|
14
|
+
class Page
|
15
|
+
include Virtus
|
16
|
+
|
17
|
+
attribute :title, String
|
18
|
+
attribute :slug, String, :default => lambda { |post, attribute| post.title.downcase.gsub(' ', '-') }, :lazy => true
|
19
|
+
attribute :view_count, Integer, :default => 0
|
20
|
+
attribute :published, Boolean, :default => false, :accessor => :private
|
21
|
+
attribute :editor_title, String, :default => :default_editor_title, :lazy => true
|
22
|
+
attribute :reference, String, :default => Reference.new
|
23
|
+
attribute :revisions, Array
|
24
|
+
attribute :index, Hash
|
25
|
+
attribute :authors, Set
|
26
|
+
|
27
|
+
def default_editor_title
|
28
|
+
published? ? title : "UNPUBLISHED: #{title}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
subject { Examples::Page.new }
|
36
|
+
|
37
|
+
specify 'without a default the value is nil' do
|
38
|
+
expect(subject.title).to be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
specify 'can be supplied with the :default option' do
|
42
|
+
expect(subject.view_count).to eq(0)
|
43
|
+
end
|
44
|
+
|
45
|
+
specify "you can pass a 'callable-object' to the :default option" do
|
46
|
+
subject.title = 'Example Blog Post'
|
47
|
+
expect(subject.slug).to eq('example-blog-post')
|
48
|
+
end
|
49
|
+
|
50
|
+
specify 'you can set defaults for private attributes' do
|
51
|
+
subject.title = 'Top Secret'
|
52
|
+
expect(subject.editor_title).to eq('UNPUBLISHED: Top Secret')
|
53
|
+
end
|
54
|
+
|
55
|
+
specify 'you can reset attribute to its default' do
|
56
|
+
subject.view_count = 10
|
57
|
+
expect do
|
58
|
+
subject.reset_attribute(:view_count)
|
59
|
+
end.to change { subject.view_count }.to(0)
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'a ValueObject' do
|
63
|
+
it 'does not duplicate the ValueObject' do
|
64
|
+
page1 = Examples::Page.new
|
65
|
+
page2 = Examples::Page.new
|
66
|
+
expect(page1.reference).to equal(page2.reference)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'an Array' do
|
71
|
+
specify 'without a default the value is an empty Array' do
|
72
|
+
expect(subject.revisions).to eql([])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'a Hash' do
|
77
|
+
specify 'without a default the value is an empty Hash' do
|
78
|
+
expect(subject.index).to eql({})
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'a Set' do
|
83
|
+
specify 'without a default the value is an empty Set' do
|
84
|
+
expect(subject.authors).to eql(Set.new)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "virtus attribute definitions" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
module Examples
|
7
|
+
class Person
|
8
|
+
include Virtus
|
9
|
+
|
10
|
+
attribute :name, String
|
11
|
+
attribute :age, Integer
|
12
|
+
attribute :doctor, Boolean
|
13
|
+
attribute :salary, Decimal
|
14
|
+
end
|
15
|
+
|
16
|
+
class Manager < Person
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
subject(:person) { Examples::Person.new(attributes) }
|
23
|
+
|
24
|
+
let(:attributes) { {} }
|
25
|
+
|
26
|
+
specify 'virtus creates accessor methods' do
|
27
|
+
person.name = 'Peter'
|
28
|
+
expect(person.name).to eq('Peter')
|
29
|
+
end
|
30
|
+
|
31
|
+
specify 'the constructor accepts a hash for mass-assignment' do
|
32
|
+
john = Examples::Person.new(:name => 'John', :age => 13)
|
33
|
+
expect(john.name).to eq('John')
|
34
|
+
expect(john.age).to eq(13)
|
35
|
+
end
|
36
|
+
|
37
|
+
specify 'Boolean attributes have a predicate method' do
|
38
|
+
expect(person).not_to be_doctor
|
39
|
+
person.doctor = true
|
40
|
+
expect(person).to be_doctor
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'with attributes' do
|
44
|
+
let(:attributes) { {:name => 'Jane', :age => 45, :doctor => true, :salary => 4500} }
|
45
|
+
|
46
|
+
specify "#attributes returns the object's attributes as a hash" do
|
47
|
+
expect(person.attributes).to eq(attributes)
|
48
|
+
end
|
49
|
+
|
50
|
+
specify "#to_hash returns the object's attributes as a hash" do
|
51
|
+
expect(person.to_hash).to eq(attributes)
|
52
|
+
end
|
53
|
+
|
54
|
+
specify "#to_h returns the object's attributes as a hash" do
|
55
|
+
expect(person.to_h).to eql(attributes)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'inheritance' do
|
60
|
+
specify 'inherits all the attributes from the base class' do
|
61
|
+
fred = Examples::Manager.new(:name => 'Fred', :age => 29)
|
62
|
+
expect(fred.name).to eq('Fred')
|
63
|
+
expect(fred.age).to eq(29)
|
64
|
+
end
|
65
|
+
|
66
|
+
specify 'lets you add attributes to the base class at runtime' do
|
67
|
+
frank = Examples::Manager.new(:name => 'Frank')
|
68
|
+
Examples::Person.attribute :just_added, String
|
69
|
+
frank.just_added = 'it works!'
|
70
|
+
expect(frank.just_added).to eq('it works!')
|
71
|
+
end
|
72
|
+
|
73
|
+
specify 'lets you add attributes to the subclass at runtime' do
|
74
|
+
person_jack = Examples::Person.new(:name => 'Jack')
|
75
|
+
manager_frank = Examples::Manager.new(:name => 'Frank')
|
76
|
+
|
77
|
+
Examples::Manager.attribute :just_added, String
|
78
|
+
|
79
|
+
manager_frank.just_added = 'awesome!'
|
80
|
+
|
81
|
+
expect(manager_frank.just_added).to eq('awesome!')
|
82
|
+
expect(person_jack).not_to respond_to(:just_added)
|
83
|
+
expect(person_jack).not_to respond_to(:just_added=)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'embedded values' do
|
4
|
+
before do
|
5
|
+
module Examples
|
6
|
+
class City
|
7
|
+
include Virtus.model
|
8
|
+
|
9
|
+
attribute :name, String
|
10
|
+
end
|
11
|
+
|
12
|
+
class Address
|
13
|
+
include Virtus.model
|
14
|
+
|
15
|
+
attribute :street, String
|
16
|
+
attribute :zipcode, String
|
17
|
+
attribute :city, City
|
18
|
+
end
|
19
|
+
|
20
|
+
class User
|
21
|
+
include Virtus.model
|
22
|
+
|
23
|
+
attribute :name, String
|
24
|
+
attribute :address, Address
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
subject { Examples::User.new(:name => 'the guy',
|
30
|
+
:address => address_attributes) }
|
31
|
+
let(:address_attributes) do
|
32
|
+
{ :street => 'Street 1/2', :zipcode => '12345', :city => { :name => 'NYC' } }
|
33
|
+
end
|
34
|
+
|
35
|
+
specify '#attributes returns instances of the embedded values' do
|
36
|
+
expect(subject.attributes).to eq({
|
37
|
+
:name => 'the guy',
|
38
|
+
:address => subject.address
|
39
|
+
})
|
40
|
+
end
|
41
|
+
|
42
|
+
specify 'allows you to pass a hash for the embedded value' do
|
43
|
+
user = Examples::User.new
|
44
|
+
user.address = address_attributes
|
45
|
+
expect(user.address.street).to eq('Street 1/2')
|
46
|
+
expect(user.address.zipcode).to eq('12345')
|
47
|
+
expect(user.address.city.name).to eq('NYC')
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'I can extend objects' do
|
4
|
+
before do
|
5
|
+
module Examples
|
6
|
+
class User; end
|
7
|
+
|
8
|
+
class Admin; end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
specify 'defining attributes on an object' do
|
13
|
+
attributes = { :name => 'John', :age => 29 }
|
14
|
+
|
15
|
+
admin = Examples::Admin.new
|
16
|
+
admin.extend(Virtus)
|
17
|
+
|
18
|
+
admin.attribute :name, String
|
19
|
+
admin.attribute :age, Integer
|
20
|
+
|
21
|
+
admin.name = 'John'
|
22
|
+
admin.age = 29
|
23
|
+
|
24
|
+
expect(admin.name).to eql('John')
|
25
|
+
expect(admin.age).to eql(29)
|
26
|
+
|
27
|
+
expect(admin.attributes).to eql(attributes)
|
28
|
+
|
29
|
+
new_attributes = { :name => 'Jane', :age => 28 }
|
30
|
+
admin.attributes = new_attributes
|
31
|
+
|
32
|
+
expect(admin.name).to eql('Jane')
|
33
|
+
expect(admin.age).to eql(28)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
class Package
|
5
|
+
include Virtus
|
6
|
+
|
7
|
+
attribute :dimensions, Hash[Symbol => Float]
|
8
|
+
attribute :meta_info , Hash[String => String]
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
describe Package do
|
13
|
+
let(:instance) do
|
14
|
+
described_class.new(
|
15
|
+
:dimensions => { 'width' => "2.2", :height => 2, "length" => 4.5 },
|
16
|
+
:meta_info => { 'from' => :Me , :to => 'You' }
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:dimensions) { instance.dimensions }
|
21
|
+
let(:meta_info) { instance.meta_info }
|
22
|
+
|
23
|
+
describe '#dimensions' do
|
24
|
+
subject { dimensions }
|
25
|
+
|
26
|
+
it 'has 3 keys' do
|
27
|
+
expect(subject.keys.size).to eq(3)
|
28
|
+
end
|
29
|
+
it { is_expected.to have_key :width }
|
30
|
+
it { is_expected.to have_key :height }
|
31
|
+
it { is_expected.to have_key :length }
|
32
|
+
|
33
|
+
it 'should be coerced to [Symbol => Float] format' do
|
34
|
+
expect(dimensions[:width]).to be_eql(2.2)
|
35
|
+
expect(dimensions[:height]).to be_eql(2.0)
|
36
|
+
expect(dimensions[:length]).to be_eql(4.5)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#meta_info' do
|
41
|
+
subject { meta_info }
|
42
|
+
|
43
|
+
it 'has 2 keys' do
|
44
|
+
expect(subject.keys.size).to eq(2)
|
45
|
+
end
|
46
|
+
it { is_expected.to have_key 'from' }
|
47
|
+
it { is_expected.to have_key 'to' }
|
48
|
+
|
49
|
+
it 'should be coerced to [String => String] format' do
|
50
|
+
expect(meta_info['from']).to eq('Me')
|
51
|
+
expect(meta_info['to']).to eq('You')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|