virtus 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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