active_attr 0.4.1 → 0.5.0.alpha1

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.

Potentially problematic release.


This version of active_attr might be problematic. Click here for more details.

Files changed (53) hide show
  1. data/.travis.yml +7 -0
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +57 -25
  4. data/Rakefile +2 -0
  5. data/active_attr.gemspec +3 -2
  6. data/gemfiles/rails_3_1.gemfile +6 -0
  7. data/lib/active_attr.rb +3 -2
  8. data/lib/active_attr/attribute_defaults.rb +120 -0
  9. data/lib/active_attr/attribute_definition.rb +25 -2
  10. data/lib/active_attr/attributes.rb +44 -33
  11. data/lib/active_attr/logger.rb +8 -8
  12. data/lib/active_attr/mass_assignment.rb +2 -1
  13. data/lib/active_attr/matchers/have_attribute_matcher.rb +28 -10
  14. data/lib/active_attr/model.rb +2 -0
  15. data/lib/active_attr/query_attributes.rb +2 -5
  16. data/lib/active_attr/typecasted_attributes.rb +77 -0
  17. data/lib/active_attr/typecasting.rb +60 -0
  18. data/lib/active_attr/typecasting/boolean.rb +6 -0
  19. data/lib/active_attr/typecasting/boolean_typecaster.rb +21 -0
  20. data/lib/active_attr/typecasting/date_time_typecaster.rb +14 -0
  21. data/lib/active_attr/typecasting/date_typecaster.rb +14 -0
  22. data/lib/active_attr/typecasting/float_typecaster.rb +11 -0
  23. data/lib/active_attr/typecasting/integer_typecaster.rb +12 -0
  24. data/lib/active_attr/typecasting/object_typecaster.rb +9 -0
  25. data/lib/active_attr/typecasting/string_typecaster.rb +11 -0
  26. data/lib/active_attr/version.rb +1 -1
  27. data/spec/functional/active_attr/attribute_defaults_spec.rb +136 -0
  28. data/spec/functional/active_attr/attributes_spec.rb +19 -5
  29. data/spec/functional/active_attr/model_spec.rb +34 -4
  30. data/spec/functional/active_attr/typecasted_attributes_spec.rb +116 -0
  31. data/spec/support/mass_assignment_shared_examples.rb +1 -1
  32. data/spec/unit/active_attr/attribute_defaults_spec.rb +43 -0
  33. data/spec/unit/active_attr/attribute_definition_spec.rb +12 -8
  34. data/spec/unit/active_attr/attributes_spec.rb +22 -10
  35. data/spec/unit/active_attr/mass_assignment_spec.rb +1 -0
  36. data/spec/unit/active_attr/matchers/have_attribute_matcher_spec.rb +94 -15
  37. data/spec/unit/active_attr/query_attributes_spec.rb +1 -1
  38. data/spec/unit/active_attr/typecasted_attributes_spec.rb +76 -0
  39. data/spec/unit/active_attr/typecasting/boolean_spec.rb +10 -0
  40. data/spec/unit/active_attr/typecasting/boolean_typecaster_spec.rb +147 -0
  41. data/spec/unit/active_attr/typecasting/date_time_typecaster_spec.rb +67 -0
  42. data/spec/unit/active_attr/typecasting/date_typecaster_spec.rb +55 -0
  43. data/spec/unit/active_attr/typecasting/float_typecaster_spec.rb +27 -0
  44. data/spec/unit/active_attr/typecasting/integer_typecaster_spec.rb +35 -0
  45. data/spec/unit/active_attr/typecasting/object_typecaster_spec.rb +15 -0
  46. data/spec/unit/active_attr/typecasting/string_typecaster_spec.rb +24 -0
  47. data/spec/unit/active_attr/typecasting_spec.rb +87 -0
  48. data/spec/unit/active_attr/version_spec.rb +11 -2
  49. metadata +75 -29
  50. data/lib/active_attr/strict_mass_assignment.rb +0 -44
  51. data/lib/active_attr/unknown_attributes_error.rb +0 -18
  52. data/spec/unit/active_attr/strict_mass_assignment_spec.rb +0 -38
  53. data/spec/unit/active_attr/unknown_attributes_error_spec.rb +0 -9
@@ -11,12 +11,16 @@ module ActiveAttr
11
11
  include Attributes
12
12
 
13
13
  attribute :parent
14
+ attribute :redefined, :type => Symbol
14
15
  end
15
16
  end
16
17
 
17
18
  let! :child_class do
18
- Class.new(parent_class) do
19
- attribute :child
19
+ Class.new(parent_class).tap do |child_class|
20
+ child_class.instance_eval do
21
+ attribute :child
22
+ attribute :redefined, :type => String
23
+ end
20
24
  end
21
25
  end
22
26
 
@@ -32,7 +36,7 @@ module ActiveAttr
32
36
  end
33
37
 
34
38
  it "add attribute definitions to the child" do
35
- child_class.attributes.map(&:name).should include :parent
39
+ child_class.attribute_names.should include "parent"
36
40
  end
37
41
  end
38
42
 
@@ -48,7 +52,17 @@ module ActiveAttr
48
52
  end
49
53
 
50
54
  it "don't add attribute definitions to the parent" do
51
- parent_class.attributes.map(&:name).should_not include :child
55
+ parent_class.attribute_names.should_not include "child"
56
+ end
57
+ end
58
+
59
+ context "attributes redefined on the child" do
60
+ it "redefines the child attribute" do
61
+ child_class.attributes[:redefined].should == AttributeDefinition.new(:redefined, :type => String)
62
+ end
63
+
64
+ it "does not redefine the parent attribute" do
65
+ parent_class.attributes[:redefined].should == AttributeDefinition.new(:redefined, :type => Symbol)
52
66
  end
53
67
  end
54
68
  end
@@ -145,7 +159,7 @@ module ActiveAttr
145
159
  end
146
160
 
147
161
  it "sets the attributes" do
148
- subject.first_name.should == "Chris"
162
+ subject.first_name.should eq "Chris"
149
163
  subject.last_name.should == "Griego"
150
164
  end
151
165
  end
@@ -25,7 +25,7 @@ module ActiveAttr
25
25
 
26
26
  it "reads and writes attributes" do
27
27
  subject.first_name = "Chris"
28
- subject.first_name.should == "Chris"
28
+ subject.first_name.should eq "Chris"
29
29
  subject.attributes["first_name"].should == "Chris"
30
30
  end
31
31
 
@@ -41,7 +41,7 @@ module ActiveAttr
41
41
  end.read_attribute(:first_name).should == "Chris"
42
42
  end
43
43
 
44
- it "processes mass assignment yielding an initialization block" do
44
+ it "processes mass assignment before yielding to an initialization block" do
45
45
  model_class.new(:first_name => "Chris") do |person|
46
46
  person.first_name.should == "Chris"
47
47
  end
@@ -55,14 +55,14 @@ module ActiveAttr
55
55
  model_class.logger = logger
56
56
 
57
57
  model_class.logger?.should be_true
58
- model_class.logger.should == logger
58
+ model_class.logger.should eq logger
59
59
  subject.logger?.should be_true
60
60
  subject.logger.should == logger
61
61
  end
62
62
 
63
63
  it "supports mass assignment with security" do
64
64
  person = model_class.new(:first_name => "Chris", :last_name => "Griego")
65
- person.first_name.should == "Chris"
65
+ person.first_name.should eq "Chris"
66
66
  person.last_name.should be_nil
67
67
  end
68
68
 
@@ -83,5 +83,35 @@ module ActiveAttr
83
83
  it "supports attribute name translation" do
84
84
  model_class.human_attribute_name(:first_name).should == "First name"
85
85
  end
86
+
87
+ context "attribute defaults" do
88
+ let :model_class do
89
+ Class.new do
90
+ include Model
91
+
92
+ attribute :start_date
93
+ attribute :end_date, :default => lambda { start_date }
94
+ attribute :age_limit, :default => 21
95
+ end
96
+ end
97
+
98
+ it "are applied" do
99
+ subject.age_limit.should == 21
100
+ end
101
+
102
+ it "are overridden by mass assigned attributes" do
103
+ model_class.new(:age_limit => 18).age_limit.should == 18
104
+ end
105
+
106
+ it "can access mass assigned attributes" do
107
+ model_class.new(:start_date => Date.today).end_date.should == Date.today
108
+ end
109
+
110
+ it "can access attributes assigned in the initialization block" do
111
+ model_class.new do |event|
112
+ event.start_date = Date.today
113
+ end.end_date.should == Date.today
114
+ end
115
+ end
86
116
  end
87
117
  end
@@ -0,0 +1,116 @@
1
+ require "spec_helper"
2
+ require "active_attr/typecasted_attributes"
3
+ require "active_attr/mass_assignment"
4
+
5
+ module ActiveAttr
6
+ describe TypecastedAttributes do
7
+ subject { model_class.new }
8
+
9
+ let :model_class do
10
+ Class.new do
11
+ include TypecastedAttributes
12
+
13
+ attribute :typeless
14
+ attribute :object, :type => Object
15
+ attribute :boolean, :type => Typecasting::Boolean
16
+ attribute :date, :type => Date
17
+ attribute :date_time, :type => DateTime
18
+ attribute :float, :type => Float
19
+ attribute :integer, :type => Integer
20
+ attribute :string, :type => String
21
+ end
22
+ end
23
+
24
+ context "when assigning nil" do
25
+ it "a typeless attribute returns nil" do
26
+ subject.typeless = nil
27
+ subject.typeless.should be_nil
28
+ end
29
+
30
+ it "an Object attribute returns nil" do
31
+ subject.object = nil
32
+ subject.object.should be_nil
33
+ end
34
+
35
+ it "a Boolean attribute returns nil" do
36
+ subject.boolean = nil
37
+ subject.boolean.should be_nil
38
+ end
39
+
40
+ it "a Date attribute returns nil" do
41
+ subject.date = nil
42
+ subject.date.should be_nil
43
+ end
44
+
45
+ it "a DateTime attribute returns nil" do
46
+ subject.date_time = nil
47
+ subject.date_time.should be_nil
48
+ end
49
+
50
+ it "a Float attribute returns nil" do
51
+ subject.float = nil
52
+ subject.float.should be_nil
53
+ end
54
+
55
+ it "an Integer attribute returns nil" do
56
+ subject.integer = nil
57
+ subject.integer.should be_nil
58
+ end
59
+
60
+ it "a String attribute returns nil" do
61
+ subject.string = nil
62
+ subject.string.should be_nil
63
+ end
64
+ end
65
+
66
+ context "when assigning a valid String" do
67
+ it "a typeless attribute returns the original String" do
68
+ value = "test"
69
+ subject.typeless = value
70
+ subject.typeless.should equal value
71
+ end
72
+
73
+ it "an Object attribute returns the original String" do
74
+ value = "test"
75
+ subject.object = value
76
+ subject.object.should equal value
77
+ end
78
+
79
+ it "a Boolean attribute returns a Boolean" do
80
+ subject.boolean = "false"
81
+ subject.boolean.should eql false
82
+ end
83
+
84
+ it "a Date attribute returns a Date" do
85
+ subject.date = "2012-01-01"
86
+ subject.date.should eql Date.new(2012, 1, 1)
87
+ end
88
+
89
+ it "a Date attribute before typecasting returns the original String" do
90
+ value = "2012-01-01"
91
+ subject.date = value
92
+ subject.date_before_type_cast.should equal value
93
+ end
94
+
95
+ it "a DateTime attribute returns a DateTime" do
96
+ subject.date_time = "2012-01-01"
97
+ subject.date_time.should eql DateTime.new(2012, 1, 1)
98
+ end
99
+
100
+ it "a Float attribute returns a Float" do
101
+ subject.float = "1.1"
102
+ subject.float.should eql 1.1
103
+ end
104
+
105
+ it "an Integer attribute returns an Integer" do
106
+ subject.integer = "1"
107
+ subject.integer.should eql 1
108
+ end
109
+
110
+ it "a String attribute returns the String" do
111
+ subject.string = "1.0"
112
+ subject.string.should eql "1.0"
113
+ end
114
+ end
115
+ end
116
+ end
@@ -17,7 +17,7 @@ shared_examples "mass assignment class", :mass_assignment => true do
17
17
  let(:last_name) { "Griego" }
18
18
 
19
19
  def should_assign_names_to(person)
20
- person.first_name.should == first_name
20
+ person.first_name.should eq first_name
21
21
  person.last_name.should == last_name
22
22
  end
23
23
  end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+ require "active_attr/attribute_defaults"
3
+
4
+ module ActiveAttr
5
+ describe AttributeDefaults do
6
+ subject { model_class.new }
7
+
8
+ let :model_class do
9
+ Class.new do
10
+ include InitializationVerifier
11
+ include AttributeDefaults
12
+ attribute :first_name, :default => "John"
13
+ attribute :age, :default => nil
14
+ attribute :created_at, :default => lambda { Time.now }
15
+ end
16
+ end
17
+
18
+ describe "#attribute_defaults" do
19
+ subject { model_class.new.attribute_defaults }
20
+
21
+ it { should be_a_kind_of Hash }
22
+
23
+ it "includes declared literal string attribute defaults" do
24
+ subject["first_name"].should == "John"
25
+ end
26
+
27
+ it "includes declared nil attribute defaults" do
28
+ subject.should include "age"
29
+ subject['age'].should be_nil
30
+ end
31
+
32
+ it "includes declared dynamic attribute defaults" do
33
+ subject['created_at'].should be_a_kind_of Time
34
+ end
35
+ end
36
+
37
+ describe "#initialize" do
38
+ it "invokes the superclass initializer" do
39
+ should be_initialized
40
+ end
41
+ end
42
+ end
43
+ end
@@ -3,14 +3,14 @@ require "active_attr/attribute_definition"
3
3
 
4
4
  module ActiveAttr
5
5
  describe AttributeDefinition do
6
- subject { described_class.new(:amount) }
6
+ subject { described_class.new(:amount, :default => "default") }
7
7
 
8
8
  describe "#<=>" do
9
9
  it "is nil if the right side is not an #{described_class}" do
10
10
  (subject <=> nil).should be_nil
11
11
  end
12
12
 
13
- it "prefers neither when both sides use the same attribute name" do
13
+ it "prefers neither when both sides use the same attribute name and options" do
14
14
  (subject <=> subject).should == 0
15
15
  end
16
16
 
@@ -31,6 +31,16 @@ module ActiveAttr
31
31
  it "returns false when another object is compared" do
32
32
  described_class.new(:amount).should_not == Struct.new(:name).new(:amount)
33
33
  end
34
+
35
+ it "returns false when options differ" do
36
+ described_class.new(:amount).should_not == described_class.new(:amount, :type => String)
37
+ end
38
+ end
39
+
40
+ describe "#[]" do
41
+ it "reads an attribute option" do
42
+ subject[:default].should == "default"
43
+ end
34
44
  end
35
45
 
36
46
  describe "#initialize" do
@@ -51,12 +61,6 @@ module ActiveAttr
51
61
  end
52
62
  end
53
63
 
54
- describe "#inspect" do
55
- it "renders the name" do
56
- subject.inspect.should == "amount"
57
- end
58
- end
59
-
60
64
  describe "#name" do
61
65
  it { should respond_to(:name) }
62
66
  end
@@ -8,7 +8,6 @@ module ActiveAttr
8
8
 
9
9
  let :model_class do
10
10
  Class.new do
11
- include InitializationVerifier
12
11
  include Attributes
13
12
  attribute :first_name
14
13
  attribute :last_name
@@ -35,7 +34,7 @@ module ActiveAttr
35
34
  end
36
35
 
37
36
  def initialize(first_name=nil)
38
- super
37
+ super()
39
38
  write_attribute(:first_name, first_name)
40
39
  end
41
40
  end
@@ -53,7 +52,7 @@ module ActiveAttr
53
52
 
54
53
  describe ".attribute" do
55
54
  it "creates an attribute with no options" do
56
- model_class.attributes.should include(AttributeDefinition.new(:first_name))
55
+ model_class.attributes.values.should include(AttributeDefinition.new(:first_name))
57
56
  end
58
57
 
59
58
  it "returns the attribute definition" do
@@ -87,11 +86,30 @@ module ActiveAttr
87
86
  attribute :name
88
87
  end.should have(1).attributes
89
88
  end
89
+
90
+ it "redefining an attribute replaces the attribute definition" do
91
+ klass = Class.new do
92
+ include Attributes
93
+ attribute :name, :type => Symbol
94
+ attribute :name, :type => String
95
+ end
96
+
97
+ klass.should have(1).attributes
98
+ klass.attributes[:name].should == AttributeDefinition.new(:name, :type => String)
99
+ end
90
100
  end
91
101
 
92
102
  describe ".attributes" do
93
103
  it { model_class.should respond_to(:attributes) }
94
104
 
105
+ it "can access AttributeDefinition with a Symbol" do
106
+ model_class.attributes[:first_name].should == AttributeDefinition.new(:first_name)
107
+ end
108
+
109
+ it "can access AttributeDefinition with a String" do
110
+ model_class.attributes['first_name'].should == AttributeDefinition.new(:first_name)
111
+ end
112
+
95
113
  context "when no attributes exist" do
96
114
  it { attributeless.attributes.should be_empty }
97
115
  end
@@ -99,7 +117,7 @@ module ActiveAttr
99
117
 
100
118
  describe ".inspect" do
101
119
  it "renders the class name" do
102
- model_class.inspect.should match /^Foo\(.*\)$/
120
+ model_class.inspect.should match(/^Foo\(.*\)$/)
103
121
  end
104
122
 
105
123
  it "renders the attribute names in alphabetical order" do
@@ -153,12 +171,6 @@ module ActiveAttr
153
171
  end
154
172
  end
155
173
 
156
- describe "#initialize" do
157
- it "invokes the superclass initializer" do
158
- should be_initialized
159
- end
160
- end
161
-
162
174
  describe "#inspect" do
163
175
  before { subject.first_name = "Ben" }
164
176
 
@@ -14,6 +14,7 @@ module ActiveAttr
14
14
 
15
15
  it "ignores attributes which do not have a writer" do
16
16
  person = mass_assign_attributes(:middle_initial => "J")
17
+ person.instance_eval { @middle_initial ||= nil }
17
18
  person.instance_variable_get("@middle_initial").should be_nil
18
19
  person.should_not respond_to :middle_initial
19
20
  end
@@ -10,14 +10,14 @@ module ActiveAttr
10
10
  it { should respond_to(:have_attribute).with(1).argument }
11
11
 
12
12
  describe "#have_attribute" do
13
- subject { dsl.have_attribute(:name) }
13
+ subject { dsl.have_attribute(:first_name) }
14
14
 
15
- it "builds a HaveAttributeMatcher with the given attribute name" do
15
+ it "builds a HaveAttributeMatcher" do
16
16
  should be_a_kind_of Matchers::HaveAttributeMatcher
17
17
  end
18
18
 
19
19
  it "uses the given attribute name to construct the matcher" do
20
- subject.attribute_name.should == :name
20
+ subject.send(:attribute_name).should == :first_name
21
21
  end
22
22
  end
23
23
  end
@@ -27,7 +27,9 @@ module ActiveAttr
27
27
  let :model_class do
28
28
  Class.new do
29
29
  include Attributes
30
- attribute :name
30
+ attribute :first_name, :default => "John"
31
+ attribute :last_name
32
+ attribute :admin, :default => false
31
33
 
32
34
  def self.to_s
33
35
  "Person"
@@ -36,24 +38,27 @@ module ActiveAttr
36
38
  end
37
39
 
38
40
  subject { positive_matcher }
39
- let(:positive_matcher) { described_class.new(:name) }
41
+ let(:positive_matcher) { described_class.new(:first_name) }
40
42
  let(:negative_matcher) { described_class.new(:age) }
43
+ let(:positive_matcher_with_default) { described_class.new(:first_name).with_default_value_of("John") }
44
+ let(:positive_matcher_with_false_default) { described_class.new(:admin).with_default_value_of(false) }
45
+ let(:negative_matcher_with_wrong_default) { described_class.new(:first_name).with_default_value_of("Doe") }
46
+ let(:negative_matcher_with_default_no_attribute) { described_class.new(:age).with_default_value_of(21) }
47
+ let(:negative_matcher_with_nil_default) { described_class.new(:first_name).with_default_value_of(nil) }
41
48
 
42
49
  it { described_class.should respond_to(:new).with(1).argument }
43
50
 
44
- describe "#attribute_name" do
45
- it "returns the value used to initialize the matcher" do
46
- subject.attribute_name.should == :name
51
+ describe "#description" do
52
+ it "returns a description appropriate to the expectation" do
53
+ subject.description.should == "have attribute named first_name"
47
54
  end
48
55
 
49
- it "converts the value used to initialize the matcher to a symbol" do
50
- described_class.new('name').attribute_name.should == :name
56
+ it "mentions the default value if set" do
57
+ positive_matcher_with_default.description.should == %{have attribute named first_name with a default value of "John"}
51
58
  end
52
- end
53
59
 
54
- describe "#description" do
55
- it "returns a description appropriate to the expectation" do
56
- subject.description.should == "have attribute named name"
60
+ it "mentions the default value if set to false" do
61
+ positive_matcher_with_false_default.description.should == %{have attribute named admin with a default value of false}
57
62
  end
58
63
  end
59
64
 
@@ -63,6 +68,18 @@ module ActiveAttr
63
68
  matcher.matches? model_class
64
69
  end.failure_message.should == "Expected Person to have attribute named age"
65
70
  end
71
+
72
+ it "mentions the default value if set" do
73
+ negative_matcher_with_wrong_default.tap do |matcher|
74
+ matcher.matches? model_class
75
+ end.failure_message.should == %{Expected Person to have attribute named first_name with a default value of "Doe"}
76
+ end
77
+
78
+ it "mentions the default value if set to false" do
79
+ negative_matcher_with_nil_default.tap do |matcher|
80
+ matcher.matches? model_class
81
+ end.failure_message.should == %{Expected Person to have attribute named first_name with a default value of nil}
82
+ end
66
83
  end
67
84
 
68
85
  describe "#initialize" do
@@ -89,13 +106,75 @@ module ActiveAttr
89
106
  it "is false with a model class that does not have the attribute" do
90
107
  negative_matcher.matches?(model_class).should be_false
91
108
  end
109
+
110
+ context "when the matcher specifies a default value" do
111
+ it "is true with an instance of a model class that has the attribute with the default value" do
112
+ positive_matcher_with_default.matches?(model_class).should be_true
113
+ end
114
+
115
+ it "is true with a model class that has the attribute with the default value" do
116
+ positive_matcher_with_default.matches?(model_class).should be_true
117
+ end
118
+
119
+ it "is false with an instance of a model class that does not have the attribute" do
120
+ negative_matcher_with_default_no_attribute.matches?(model_instance).should be_false
121
+ end
122
+
123
+ it "is false with a model class that does not have the attribute" do
124
+ negative_matcher_with_default_no_attribute.matches?(model_class).should be_false
125
+ end
126
+
127
+ it "is false with an instance of a model class that has the attribute but not with the specified default value" do
128
+ negative_matcher_with_wrong_default.matches?(model_instance).should be_false
129
+ end
130
+
131
+ it "is false with a model class that has the attribute but not with the specified default value" do
132
+ negative_matcher_with_wrong_default.matches?(model_class).should be_false
133
+ end
134
+
135
+ it "is true with an instance of a model class that has the attribute with the default value of false" do
136
+ positive_matcher_with_false_default.matches?(model_class).should be_true
137
+ end
138
+
139
+ it "is true with a model class that has the attribute with the default value where the default value is false" do
140
+ positive_matcher_with_false_default.matches?(model_class).should be_true
141
+ end
142
+
143
+ it "is true with an instance of a model class that has the attribute with the default value where the default value is false" do
144
+ positive_matcher_with_false_default.matches?(model_class).should be_true
145
+ end
146
+
147
+ it "is true with a model class that has the attribute with the default value false" do
148
+ positive_matcher_with_false_default.matches?(model_class).should be_true
149
+ end
150
+
151
+ it "is false with an instance of a model class that has the attribute but not with the specified default value where the specified default value is nil" do
152
+ negative_matcher_with_nil_default.matches?(model_instance).should be_false
153
+ end
154
+
155
+ it "is false with a model class that has the attribute but not with the specified default value where the specified default value is nil" do
156
+ negative_matcher_with_nil_default.matches?(model_class).should be_false
157
+ end
158
+ end
92
159
  end
93
160
 
94
161
  describe "#negative_failure_message" do
95
162
  it "returns a failure message appropriate to the expectation and subject" do
96
163
  positive_matcher.tap do |matcher|
97
164
  matcher.matches? model_class
98
- end.negative_failure_message.should == "Expected Person to not have attribute named name"
165
+ end.negative_failure_message.should == "Expected Person to not have attribute named first_name"
166
+ end
167
+
168
+ it "mentions the default value if set" do
169
+ positive_matcher_with_default.tap do |matcher|
170
+ matcher.matches? model_class
171
+ end.negative_failure_message.should == %{Expected Person to not have attribute named first_name with a default value of "John"}
172
+ end
173
+
174
+ it "mentions the default value if set to false" do
175
+ positive_matcher_with_false_default.tap do |matcher|
176
+ matcher.matches? model_class
177
+ end.negative_failure_message.should == %{Expected Person to not have attribute named admin with a default value of false}
99
178
  end
100
179
  end
101
180
  end