virtus 1.0.1 → 2.0.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.
Files changed (99) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +19 -15
  3. data/Changelog.md +43 -2
  4. data/Gemfile +5 -5
  5. data/README.md +113 -78
  6. data/Rakefile +13 -3
  7. data/lib/virtus.rb +46 -6
  8. data/lib/virtus/attribute.rb +21 -3
  9. data/lib/virtus/attribute/accessor.rb +11 -0
  10. data/lib/virtus/attribute/builder.rb +8 -13
  11. data/lib/virtus/attribute/collection.rb +12 -3
  12. data/lib/virtus/attribute/default_value.rb +2 -0
  13. data/lib/virtus/attribute/hash.rb +3 -3
  14. data/lib/virtus/attribute/nullify_blank.rb +24 -0
  15. data/lib/virtus/attribute/strict.rb +1 -1
  16. data/lib/virtus/attribute_set.rb +2 -2
  17. data/lib/virtus/builder.rb +2 -6
  18. data/lib/virtus/class_inclusions.rb +0 -1
  19. data/lib/virtus/coercer.rb +1 -0
  20. data/lib/virtus/configuration.rb +17 -36
  21. data/lib/virtus/extensions.rb +13 -21
  22. data/lib/virtus/instance_methods.rb +3 -2
  23. data/lib/virtus/model.rb +1 -3
  24. data/lib/virtus/module_extensions.rb +8 -2
  25. data/lib/virtus/support/equalizer.rb +1 -1
  26. data/lib/virtus/support/options.rb +2 -1
  27. data/lib/virtus/support/type_lookup.rb +1 -1
  28. data/lib/virtus/version.rb +1 -1
  29. data/spec/integration/attributes_attribute_spec.rb +28 -0
  30. data/spec/integration/building_module_spec.rb +22 -0
  31. data/spec/integration/collection_member_coercion_spec.rb +34 -13
  32. data/spec/integration/custom_attributes_spec.rb +2 -2
  33. data/spec/integration/custom_collection_attributes_spec.rb +6 -6
  34. data/spec/integration/default_values_spec.rb +8 -8
  35. data/spec/integration/defining_attributes_spec.rb +25 -18
  36. data/spec/integration/embedded_value_spec.rb +5 -5
  37. data/spec/integration/extending_objects_spec.rb +5 -5
  38. data/spec/integration/hash_attributes_coercion_spec.rb +16 -12
  39. data/spec/integration/mass_assignment_with_accessors_spec.rb +5 -5
  40. data/spec/integration/overriding_virtus_spec.rb +4 -4
  41. data/spec/integration/required_attributes_spec.rb +1 -1
  42. data/spec/integration/struct_as_embedded_value_spec.rb +4 -4
  43. data/spec/integration/using_modules_spec.rb +8 -8
  44. data/spec/integration/value_object_with_custom_constructor_spec.rb +4 -4
  45. data/spec/integration/virtus/instance_level_attributes_spec.rb +1 -1
  46. data/spec/integration/virtus/value_object_spec.rb +14 -14
  47. data/spec/shared/freeze_method_behavior.rb +6 -3
  48. data/spec/shared/idempotent_method_behaviour.rb +1 -1
  49. data/spec/shared/options_class_method.rb +3 -3
  50. data/spec/spec_helper.rb +2 -18
  51. data/spec/unit/virtus/attribute/boolean/coerce_spec.rb +3 -3
  52. data/spec/unit/virtus/attribute/boolean/value_coerced_predicate_spec.rb +3 -3
  53. data/spec/unit/virtus/attribute/class_methods/build_spec.rb +64 -24
  54. data/spec/unit/virtus/attribute/class_methods/coerce_spec.rb +2 -2
  55. data/spec/unit/virtus/attribute/coerce_spec.rb +58 -10
  56. data/spec/unit/virtus/attribute/coercible_predicate_spec.rb +2 -2
  57. data/spec/unit/virtus/attribute/collection/class_methods/build_spec.rb +15 -4
  58. data/spec/unit/virtus/attribute/collection/coerce_spec.rb +25 -4
  59. data/spec/unit/virtus/attribute/collection/value_coerced_predicate_spec.rb +31 -0
  60. data/spec/unit/virtus/attribute/comparison_spec.rb +20 -0
  61. data/spec/unit/virtus/attribute/custom_collection_spec.rb +8 -2
  62. data/spec/unit/virtus/attribute/defined_spec.rb +20 -0
  63. data/spec/unit/virtus/attribute/embedded_value/class_methods/build_spec.rb +30 -15
  64. data/spec/unit/virtus/attribute/embedded_value/coerce_spec.rb +25 -11
  65. data/spec/unit/virtus/attribute/get_spec.rb +2 -2
  66. data/spec/unit/virtus/attribute/hash/class_methods/build_spec.rb +21 -9
  67. data/spec/unit/virtus/attribute/hash/coerce_spec.rb +9 -9
  68. data/spec/unit/virtus/attribute/lazy_predicate_spec.rb +2 -2
  69. data/spec/unit/virtus/attribute/rename_spec.rb +6 -3
  70. data/spec/unit/virtus/attribute/required_predicate_spec.rb +2 -2
  71. data/spec/unit/virtus/attribute/set_default_value_spec.rb +43 -10
  72. data/spec/unit/virtus/attribute/set_spec.rb +1 -1
  73. data/spec/unit/virtus/attribute/value_coerced_predicate_spec.rb +2 -2
  74. data/spec/unit/virtus/attribute_set/append_spec.rb +6 -6
  75. data/spec/unit/virtus/attribute_set/define_reader_method_spec.rb +12 -11
  76. data/spec/unit/virtus/attribute_set/define_writer_method_spec.rb +13 -12
  77. data/spec/unit/virtus/attribute_set/each_spec.rb +21 -16
  78. data/spec/unit/virtus/attribute_set/element_reference_spec.rb +2 -2
  79. data/spec/unit/virtus/attribute_set/element_set_spec.rb +17 -9
  80. data/spec/unit/virtus/attribute_set/merge_spec.rb +7 -5
  81. data/spec/unit/virtus/attribute_set/reset_spec.rb +22 -11
  82. data/spec/unit/virtus/attribute_spec.rb +8 -7
  83. data/spec/unit/virtus/attributes_reader_spec.rb +1 -1
  84. data/spec/unit/virtus/attributes_writer_spec.rb +1 -1
  85. data/spec/unit/virtus/element_reader_spec.rb +1 -1
  86. data/spec/unit/virtus/freeze_spec.rb +23 -3
  87. data/spec/unit/virtus/model_spec.rb +38 -7
  88. data/spec/unit/virtus/module_spec.rb +59 -2
  89. data/spec/unit/virtus/set_default_attributes_spec.rb +10 -3
  90. data/spec/unit/virtus/value_object_spec.rb +15 -5
  91. data/virtus.gemspec +7 -5
  92. metadata +46 -44
  93. data/.ruby-version +0 -1
  94. data/Gemfile.devtools +0 -54
  95. data/config/flay.yml +0 -3
  96. data/config/flog.yml +0 -2
  97. data/config/mutant.yml +0 -15
  98. data/config/reek.yml +0 -146
  99. data/config/yardstick.yml +0 -2
@@ -23,28 +23,32 @@ describe Package do
23
23
  describe '#dimensions' do
24
24
  subject { dimensions }
25
25
 
26
- it { should have(3).keys }
27
- it { should have_key :width }
28
- it { should have_key :height }
29
- it { should have_key :length }
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 }
30
32
 
31
33
  it 'should be coerced to [Symbol => Float] format' do
32
- dimensions[:width].should be_eql(2.2)
33
- dimensions[:height].should be_eql(2.0)
34
- dimensions[:length].should be_eql(4.5)
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)
35
37
  end
36
38
  end
37
39
 
38
40
  describe '#meta_info' do
39
41
  subject { meta_info }
40
42
 
41
- it { should have(2).keys }
42
- it { should have_key 'from' }
43
- it { should have_key 'to' }
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' }
44
48
 
45
49
  it 'should be coerced to [String => String] format' do
46
- meta_info['from'].should == 'Me'
47
- meta_info['to'].should == 'You'
50
+ expect(meta_info['from']).to eq('Me')
51
+ expect(meta_info['to']).to eq('You')
48
52
  end
49
53
  end
50
54
  end
@@ -28,17 +28,17 @@ describe "mass assignment with accessors" do
28
28
  subject { Examples::Product.new(:categories => ['Office', 'Printers'], :_id => 100) }
29
29
 
30
30
  specify 'works uppon instantiation' do
31
- subject.category.should == 'Office'
32
- subject.subcategory.should == 'Printers'
31
+ expect(subject.category).to eq('Office')
32
+ expect(subject.subcategory).to eq('Printers')
33
33
  end
34
34
 
35
35
  specify 'can be set with #attributes=' do
36
36
  subject.attributes = {:categories => ['Home', 'Furniture']}
37
- subject.category.should == 'Home'
38
- subject.subcategory.should == 'Furniture'
37
+ expect(subject.category).to eq('Home')
38
+ expect(subject.subcategory).to eq('Furniture')
39
39
  end
40
40
 
41
41
  specify 'respects accessor visibility' do
42
- subject.id.should_not == 100
42
+ expect(subject.id).not_to eq(100)
43
43
  end
44
44
  end
@@ -22,11 +22,11 @@ describe 'overriding virtus behavior' do
22
22
 
23
23
  describe 'overriding an attribute getter' do
24
24
  specify 'calls the defined getter' do
25
- Examples::Article.new.title.should == '<unknown>'
25
+ expect(Examples::Article.new.title).to eq('<unknown>')
26
26
  end
27
27
 
28
28
  specify 'super can be used to access the getter defined by virtus' do
29
- Examples::Article.new(:title => 'example article').title.should == 'example article'
29
+ expect(Examples::Article.new(:title => 'example article').title).to eq('example article')
30
30
  end
31
31
  end
32
32
 
@@ -34,13 +34,13 @@ describe 'overriding virtus behavior' do
34
34
  specify 'calls the defined setter' do
35
35
  article = Examples::Article.new(:title => "can't be changed")
36
36
  article.title = 'this will never be assigned'
37
- article.title.should == "can't be changed"
37
+ expect(article.title).to eq("can't be changed")
38
38
  end
39
39
 
40
40
  specify 'super can be used to access the setter defined by virtus' do
41
41
  article = Examples::Article.new(:title => 'example article')
42
42
  article.title = 'my new title'
43
- article.title.should == 'my new title'
43
+ expect(article.title).to eq('my new title')
44
44
  end
45
45
  end
46
46
  end
@@ -13,7 +13,7 @@ describe 'Using required attributes' do
13
13
  end
14
14
 
15
15
  it 'raises coercion error when required attribute is nil' do
16
- expect { Examples::User.new(:name => nil) }.to raise_error(Virtus::CoercionError)
16
+ expect { Examples::User.new(:name => nil) }.to raise_error(Virtus::CoercionError, "Failed to coerce attribute `name' from nil into String")
17
17
  end
18
18
 
19
19
  it 'does not raise coercion error when not required attribute is nil' do
@@ -19,10 +19,10 @@ describe 'Using Struct as an embedded value attribute' do
19
19
  end
20
20
 
21
21
  specify 'initialize a struct object with correct attributes' do
22
- subject.top_left.x.should be(3)
23
- subject.top_left.y.should be(5)
22
+ expect(subject.top_left.x).to be(3)
23
+ expect(subject.top_left.y).to be(5)
24
24
 
25
- subject.bottom_right.x.should be(8)
26
- subject.bottom_right.y.should be(7)
25
+ expect(subject.bottom_right.x).to be(8)
26
+ expect(subject.bottom_right.y).to be(7)
27
27
  end
28
28
  end
@@ -33,15 +33,15 @@ describe 'I can define attributes within a module' do
33
33
  end
34
34
 
35
35
  specify 'including a module with attributes into a class' do
36
- Examples::User.attribute_set[:name].should be_instance_of(Virtus::Attribute)
37
- Examples::User.attribute_set[:gamer].should be_instance_of(Virtus::Attribute::Boolean)
36
+ expect(Examples::User.attribute_set[:name]).to be_instance_of(Virtus::Attribute)
37
+ expect(Examples::User.attribute_set[:gamer]).to be_instance_of(Virtus::Attribute::Boolean)
38
38
 
39
- Examples::Admin.attribute_set[:name].should be_instance_of(Virtus::Attribute)
40
- Examples::Admin.attribute_set[:age].should be_instance_of(Virtus::Attribute)
39
+ expect(Examples::Admin.attribute_set[:name]).to be_instance_of(Virtus::Attribute)
40
+ expect(Examples::Admin.attribute_set[:age]).to be_instance_of(Virtus::Attribute)
41
41
 
42
42
  user = Examples::Admin.new(:name => 'Piotr', :age => 29)
43
- user.name.should eql('Piotr')
44
- user.age.should eql(29)
43
+ expect(user.name).to eql('Piotr')
44
+ expect(user.age).to eql(29)
45
45
  end
46
46
 
47
47
  specify 'including a module with attributes into an instance' do
@@ -49,7 +49,7 @@ describe 'I can define attributes within a module' do
49
49
  moderator.extend(Examples::Name, Examples::Age)
50
50
 
51
51
  moderator.attributes = { :name => 'John', :age => 21 }
52
- moderator.name.should eql('John')
53
- moderator.age.should eql(21)
52
+ expect(moderator.name).to eql('John')
53
+ expect(moderator.age).to eql(21)
54
54
  end
55
55
  end
@@ -33,10 +33,10 @@ describe "Defining a ValueObject with a custom constructor" do
33
33
  end
34
34
 
35
35
  specify "initialize a value object attribute with correct attributes" do
36
- subject.top_left.x.should be(3)
37
- subject.top_left.y.should be(4)
36
+ expect(subject.top_left.x).to be(3)
37
+ expect(subject.top_left.y).to be(4)
38
38
 
39
- subject.bottom_right.x.should be(5)
40
- subject.bottom_right.y.should be(8)
39
+ expect(subject.bottom_right.x).to be(5)
40
+ expect(subject.bottom_right.y).to be(8)
41
41
  end
42
42
  end
@@ -17,7 +17,7 @@ describe Virtus, 'instance level attributes' do
17
17
  it 'allows setting the attribute value on the instance' do
18
18
  attribute
19
19
  subject.name = 'foo'
20
- subject.name.should eql('foo')
20
+ expect(subject.name).to eql('foo')
21
21
  end
22
22
  end
23
23
  end
@@ -26,21 +26,21 @@ describe Virtus::ValueObject do
26
26
 
27
27
  describe 'initialization' do
28
28
  it 'sets the attribute values provided to Class.new' do
29
- class_under_test.new(:latitude => 10000.001).latitude.should == 10000.001
30
- subject.latitude.should eql(attribute_values[:latitude])
29
+ expect(class_under_test.new(:latitude => 10000.001).latitude).to eq(10000.001)
30
+ expect(subject.latitude).to eql(attribute_values[:latitude])
31
31
  end
32
32
  end
33
33
 
34
34
  describe 'writer visibility' do
35
35
  it 'attributes are configured for private writers' do
36
- class_under_test.attribute_set[:latitude].public_reader?.should be(true)
37
- class_under_test.attribute_set[:longitude].public_writer?.should be(false)
36
+ expect(class_under_test.attribute_set[:latitude].public_reader?).to be(true)
37
+ expect(class_under_test.attribute_set[:longitude].public_writer?).to be(false)
38
38
  end
39
39
 
40
40
  it 'writer methods are set to private' do
41
41
  private_methods = class_under_test.private_instance_methods
42
42
  private_methods.map! { |m| m.to_s }
43
- private_methods.should include('latitude=', 'longitude=', 'attributes=')
43
+ expect(private_methods).to include('latitude=', 'longitude=', 'attributes=')
44
44
  end
45
45
 
46
46
  it 'attempts to call attribute writer methods raises NameError' do
@@ -52,48 +52,48 @@ describe Virtus::ValueObject do
52
52
  describe 'equality' do
53
53
  describe '#==' do
54
54
  it 'returns true for different objects with the same state' do
55
- subject.should == instance_with_equal_state
55
+ expect(subject).to eq(instance_with_equal_state)
56
56
  end
57
57
 
58
58
  it 'returns false for different objects with different state' do
59
- subject.should_not == instance_with_different_state
59
+ expect(subject).not_to eq(instance_with_different_state)
60
60
  end
61
61
  end
62
62
 
63
63
  describe '#eql?' do
64
64
  it 'returns true for different objects with the same state' do
65
- subject.should eql(instance_with_equal_state)
65
+ expect(subject).to eql(instance_with_equal_state)
66
66
  end
67
67
 
68
68
  it 'returns false for different objects with different state' do
69
- subject.should_not eql(instance_with_different_state)
69
+ expect(subject).not_to eql(instance_with_different_state)
70
70
  end
71
71
  end
72
72
 
73
73
  describe '#equal?' do
74
74
  it 'returns false for different objects with the same state' do
75
- subject.should_not equal(instance_with_equal_state)
75
+ expect(subject).not_to equal(instance_with_equal_state)
76
76
  end
77
77
 
78
78
  it 'returns false for different objects with different state' do
79
- subject.should_not equal(instance_with_different_state)
79
+ expect(subject).not_to equal(instance_with_different_state)
80
80
  end
81
81
  end
82
82
 
83
83
  describe '#hash' do
84
84
  it 'returns the same value for different objects with the same state' do
85
- subject.hash.should eql(instance_with_equal_state.hash)
85
+ expect(subject.hash).to eql(instance_with_equal_state.hash)
86
86
  end
87
87
 
88
88
  it 'returns different values for different objects with different state' do
89
- subject.hash.should_not eql(instance_with_different_state.hash)
89
+ expect(subject.hash).not_to eql(instance_with_different_state.hash)
90
90
  end
91
91
  end
92
92
  end
93
93
 
94
94
  describe '#inspect' do
95
95
  it 'includes the class name and attribute values' do
96
- subject.inspect.should == '#<GeoLocation latitude=10.0 longitude=20.0>'
96
+ expect(subject.inspect).to eq('#<GeoLocation latitude=10.0 longitude=20.0>')
97
97
  end
98
98
  end
99
99
  end
@@ -20,7 +20,7 @@ shared_examples_for 'a #freeze method' do
20
20
  it_should_behave_like 'an idempotent method'
21
21
 
22
22
  it 'returns object' do
23
- should be(object)
23
+ is_expected.to be(object)
24
24
  end
25
25
 
26
26
  it 'prevents future modifications' do
@@ -29,9 +29,12 @@ shared_examples_for 'a #freeze method' do
29
29
  expect { object.instance_variable_set(:@foo, :bar) }.to(expectation)
30
30
  end
31
31
 
32
- its(:frozen?) { should be(true) }
32
+ describe '#frozen?' do
33
+ subject { super().frozen? }
34
+ it { is_expected.to be(true) }
35
+ end
33
36
 
34
37
  it 'allows to access attribute' do
35
- subject.name.should eql('John')
38
+ expect(subject.name).to eql('John')
36
39
  end
37
40
  end
@@ -1,5 +1,5 @@
1
1
  shared_examples_for 'an idempotent method' do
2
2
  it 'is idempotent' do
3
- should equal(subject)
3
+ is_expected.to equal(subject)
4
4
  end
5
5
  end
@@ -2,15 +2,15 @@ shared_examples_for 'an options class method' do
2
2
  context 'with no argument' do
3
3
  subject { object.send(method) }
4
4
 
5
- it { should be(default) }
5
+ it { is_expected.to be(default) }
6
6
  end
7
7
 
8
8
  context 'with a default value' do
9
9
  subject { object.send(method, value) }
10
10
 
11
- let(:value) { double('value') }
11
+ let(:value) { mock('value') }
12
12
 
13
- it { should equal(object) }
13
+ it { is_expected.to equal(object) }
14
14
 
15
15
  it 'sets the default value for the class method' do
16
16
  expect { subject }.to change { object.send(method) }.from(default).to(value)
data/spec/spec_helper.rb CHANGED
@@ -1,25 +1,11 @@
1
- if ENV['COVERAGE'] == 'true'
1
+ if RUBY_ENGINE == 'ruby' && RUBY_VERSION >= '3.0'
2
2
  require 'simplecov'
3
- require 'coveralls'
4
-
5
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
6
- SimpleCov::Formatter::HTMLFormatter,
7
- Coveralls::SimpleCov::Formatter
8
- ]
9
-
10
- SimpleCov.start do
11
- command_name 'spec:unit'
12
- add_filter 'config/'
13
- add_filter 'spec'
14
- add_filter '.bundle'
15
- minimum_coverage 98
16
- end
3
+ SimpleCov.start
17
4
  end
18
5
 
19
6
  require 'rspec'
20
7
  require 'bogus/rspec'
21
8
  require 'virtus'
22
- require 'inflecto' # for resolving namespaced constant names
23
9
 
24
10
  module Virtus
25
11
  def self.warn(*)
@@ -33,7 +19,6 @@ ENV['TZ'] = 'UTC'
33
19
  Dir[File.expand_path('../shared/**/*.rb', __FILE__)].each { |file| require file }
34
20
 
35
21
  RSpec.configure do |config|
36
-
37
22
  # Remove anonymous- and example- Attribute classes from Attribute descendants
38
23
  config.after :all do
39
24
  stack = [ Virtus::Attribute ]
@@ -53,5 +38,4 @@ RSpec.configure do |config|
53
38
  end
54
39
  end
55
40
  end
56
-
57
41
  end
@@ -10,13 +10,13 @@ describe Virtus::Attribute::Boolean, '#coerce' do
10
10
  context 'with a truthy value' do
11
11
  let(:input) { 1 }
12
12
 
13
- it { should be(true) }
13
+ it { is_expected.to be(true) }
14
14
  end
15
15
 
16
16
  context 'with a falsy value' do
17
17
  let(:input) { 0 }
18
18
 
19
- it { should be(false) }
19
+ it { is_expected.to be(false) }
20
20
  end
21
21
  end
22
22
 
@@ -26,7 +26,7 @@ describe Virtus::Attribute::Boolean, '#coerce' do
26
26
  context 'with a coercible input' do
27
27
  let(:input) { 1 }
28
28
 
29
- it { should be(true) }
29
+ it { is_expected.to be(true) }
30
30
  end
31
31
 
32
32
  context 'with a non-coercible input' do
@@ -8,18 +8,18 @@ describe Virtus::Attribute::Boolean, '#value_coerced?' do
8
8
  context 'when input is true' do
9
9
  let(:input) { true }
10
10
 
11
- it { should be(true) }
11
+ it { is_expected.to be(true) }
12
12
  end
13
13
 
14
14
  context 'when input is false' do
15
15
  let(:input) { false }
16
16
 
17
- it { should be(true) }
17
+ it { is_expected.to be(true) }
18
18
  end
19
19
 
20
20
  context 'when input is not coerced' do
21
21
  let(:input) { 1 }
22
22
 
23
- it { should be(false) }
23
+ it { is_expected.to be(false) }
24
24
  end
25
25
  end
@@ -7,19 +7,19 @@ describe Virtus::Attribute, '.build' do
7
7
  let(:type) { String }
8
8
  let(:options) { {} }
9
9
 
10
- share_examples_for 'a valid attribute instance' do
11
- it { should be_instance_of(Virtus::Attribute) }
10
+ shared_examples_for 'a valid attribute instance' do
11
+ it { is_expected.to be_instance_of(Virtus::Attribute) }
12
12
 
13
- it { should be_frozen }
13
+ it { is_expected.to be_frozen }
14
14
  end
15
15
 
16
16
  context 'without options' do
17
17
  it_behaves_like 'a valid attribute instance'
18
18
 
19
- it { should be_coercible }
20
- it { should be_public_reader }
21
- it { should be_public_writer }
22
- it { should_not be_lazy }
19
+ it { is_expected.to be_coercible }
20
+ it { is_expected.to be_public_reader }
21
+ it { is_expected.to be_public_writer }
22
+ it { is_expected.not_to be_lazy }
23
23
 
24
24
  it 'sets up a coercer' do
25
25
  expect(subject.options[:coerce]).to be(true)
@@ -30,7 +30,10 @@ describe Virtus::Attribute, '.build' do
30
30
  context 'when name is passed as a string' do
31
31
  let(:name) { 'something' }
32
32
 
33
- its(:name) { should be(:something) }
33
+ describe '#name' do
34
+ subject { super().name }
35
+ it { is_expected.to be(:something) }
36
+ end
34
37
  end
35
38
 
36
39
  context 'when coercion is turned off in options' do
@@ -38,7 +41,7 @@ describe Virtus::Attribute, '.build' do
38
41
 
39
42
  it_behaves_like 'a valid attribute instance'
40
43
 
41
- it { should_not be_coercible }
44
+ it { is_expected.not_to be_coercible }
42
45
  end
43
46
 
44
47
  context 'when options specify reader visibility' do
@@ -46,8 +49,8 @@ describe Virtus::Attribute, '.build' do
46
49
 
47
50
  it_behaves_like 'a valid attribute instance'
48
51
 
49
- it { should_not be_public_reader }
50
- it { should be_public_writer }
52
+ it { is_expected.not_to be_public_reader }
53
+ it { is_expected.to be_public_writer }
51
54
  end
52
55
 
53
56
  context 'when options specify writer visibility' do
@@ -55,8 +58,8 @@ describe Virtus::Attribute, '.build' do
55
58
 
56
59
  it_behaves_like 'a valid attribute instance'
57
60
 
58
- it { should be_public_reader }
59
- it { should_not be_public_writer }
61
+ it { is_expected.to be_public_reader }
62
+ it { is_expected.not_to be_public_writer }
60
63
  end
61
64
 
62
65
  context 'when options specify lazy accessor' do
@@ -64,7 +67,7 @@ describe Virtus::Attribute, '.build' do
64
67
 
65
68
  it_behaves_like 'a valid attribute instance'
66
69
 
67
- it { should be_lazy }
70
+ it { is_expected.to be_lazy }
68
71
  end
69
72
 
70
73
  context 'when options specify strict mode' do
@@ -72,7 +75,15 @@ describe Virtus::Attribute, '.build' do
72
75
 
73
76
  it_behaves_like 'a valid attribute instance'
74
77
 
75
- it { should be_strict }
78
+ it { is_expected.to be_strict }
79
+ end
80
+
81
+ context 'when options specify nullify blank mode' do
82
+ let(:options) { { :nullify_blank => true } }
83
+
84
+ it_behaves_like 'a valid attribute instance'
85
+
86
+ it { is_expected.to be_nullify_blank }
76
87
  end
77
88
 
78
89
  context 'when type is a string' do
@@ -80,7 +91,21 @@ describe Virtus::Attribute, '.build' do
80
91
 
81
92
  it_behaves_like 'a valid attribute instance'
82
93
 
83
- its(:type) { should be(Axiom::Types::Integer) }
94
+ describe '#type' do
95
+ subject { super().type }
96
+ it { is_expected.to be(Axiom::Types::Integer) }
97
+ end
98
+ end
99
+
100
+ context 'when type is a range' do
101
+ let(:type) { 0..10 }
102
+
103
+ it_behaves_like 'a valid attribute instance'
104
+
105
+ describe '#type' do
106
+ subject { super().type }
107
+ it { is_expected.to be(Axiom::Types.infer(Range)) }
108
+ end
84
109
  end
85
110
 
86
111
  context 'when type is a symbol of an existing class constant' do
@@ -88,7 +113,10 @@ describe Virtus::Attribute, '.build' do
88
113
 
89
114
  it_behaves_like 'a valid attribute instance'
90
115
 
91
- its(:type) { should be(Axiom::Types::String) }
116
+ describe '#type' do
117
+ subject { super().type }
118
+ it { is_expected.to be(Axiom::Types::String) }
119
+ end
92
120
  end
93
121
 
94
122
  context 'when type is an axiom type' do
@@ -96,7 +124,10 @@ describe Virtus::Attribute, '.build' do
96
124
 
97
125
  it_behaves_like 'a valid attribute instance'
98
126
 
99
- its(:type) { should be(type) }
127
+ describe '#type' do
128
+ subject { super().type }
129
+ it { is_expected.to be(type) }
130
+ end
100
131
  end
101
132
 
102
133
  context 'when custom attribute class exists for a given primitive' do
@@ -107,9 +138,12 @@ describe Virtus::Attribute, '.build' do
107
138
  attribute.primitive(type)
108
139
  end
109
140
 
110
- it { should be_instance_of(attribute) }
141
+ it { is_expected.to be_instance_of(attribute) }
111
142
 
112
- its(:type) { should be(Axiom::Types::Object) }
143
+ describe '#type' do
144
+ subject { super().type }
145
+ it { is_expected.to be(Axiom::Types::Object) }
146
+ end
113
147
  end
114
148
 
115
149
  context 'when custom attribute class exists for a given array with member coercion defined' do
@@ -120,9 +154,12 @@ describe Virtus::Attribute, '.build' do
120
154
  attribute.primitive(type.class)
121
155
  end
122
156
 
123
- it { should be_instance_of(attribute) }
157
+ it { is_expected.to be_instance_of(attribute) }
124
158
 
125
- its(:type) { should be < Axiom::Types::Collection }
159
+ describe '#type' do
160
+ subject { super().type }
161
+ it { is_expected.to be < Axiom::Types::Collection }
162
+ end
126
163
  end
127
164
 
128
165
  context 'when custom collection-like attribute class exists for a given enumerable primitive' do
@@ -133,8 +170,11 @@ describe Virtus::Attribute, '.build' do
133
170
  attribute.primitive(type)
134
171
  end
135
172
 
136
- it { should be_instance_of(attribute) }
173
+ it { is_expected.to be_instance_of(attribute) }
137
174
 
138
- its(:type) { should be < Axiom::Types::Collection }
175
+ describe '#type' do
176
+ subject { super().type }
177
+ it { is_expected.to be < Axiom::Types::Collection }
178
+ end
139
179
  end
140
180
  end