active_attr 0.7.0 → 0.8.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.
Potentially problematic release.
This version of active_attr might be problematic. Click here for more details.
- data/.travis.yml +11 -1
- data/CHANGELOG.md +9 -0
- data/Gemfile +4 -6
- data/README.md +29 -11
- data/active_attr.gemspec +3 -3
- data/gemfiles/rails_3_2.gemfile +11 -0
- data/gemfiles/rails_head.gemfile +3 -0
- data/lib/active_attr.rb +0 -1
- data/lib/active_attr/mass_assignment.rb +30 -2
- data/lib/active_attr/matchers/have_attribute_matcher.rb +17 -4
- data/lib/active_attr/model.rb +2 -2
- data/lib/active_attr/typecasting/big_decimal_typecaster.rb +2 -0
- data/lib/active_attr/typecasting/date_typecaster.rb +1 -1
- data/lib/active_attr/version.rb +1 -1
- data/spec/functional/active_attr/attribute_defaults_spec.rb +12 -12
- data/spec/functional/active_attr/attributes_spec.rb +12 -12
- data/spec/functional/active_attr/chainable_initialization_spec.rb +3 -3
- data/spec/functional/active_attr/mass_assignment_spec.rb +125 -0
- data/spec/functional/active_attr/matchers/have_attribute_matcher_spec.rb +147 -66
- data/spec/functional/active_attr/model_spec.rb +27 -19
- data/spec/functional/active_attr/serialization_spec.rb +5 -5
- data/spec/functional/active_attr/typecasted_attributes_spec.rb +45 -45
- data/spec/support/mass_assignment_shared_examples.rb +12 -12
- data/spec/unit/active_attr/attribute_defaults_spec.rb +6 -6
- data/spec/unit/active_attr/attribute_definition_spec.rb +6 -6
- data/spec/unit/active_attr/attributes_spec.rb +38 -38
- data/spec/unit/active_attr/logger_spec.rb +16 -16
- data/spec/unit/active_attr/mass_assignment_spec.rb +1 -1
- data/spec/unit/active_attr/matchers_spec.rb +3 -4
- data/spec/unit/active_attr/query_attributes_spec.rb +75 -75
- data/spec/unit/active_attr/typecasted_attributes_spec.rb +10 -10
- data/spec/unit/active_attr/typecasting/big_decimal_typecaster_spec.rb +9 -7
- data/spec/unit/active_attr/typecasting/boolean_typecaster_spec.rb +27 -25
- data/spec/unit/active_attr/typecasting/date_time_typecaster_spec.rb +12 -10
- data/spec/unit/active_attr/typecasting/date_typecaster_spec.rb +14 -12
- data/spec/unit/active_attr/typecasting/float_typecaster_spec.rb +6 -4
- data/spec/unit/active_attr/typecasting/integer_typecaster_spec.rb +8 -6
- data/spec/unit/active_attr/typecasting/object_typecaster_spec.rb +3 -1
- data/spec/unit/active_attr/typecasting/string_typecaster_spec.rb +5 -3
- data/spec/unit/active_attr/typecasting_spec.rb +3 -5
- data/spec/unit/active_attr/version_spec.rb +5 -5
- metadata +20 -17
- data/lib/active_attr/mass_assignment_security.rb +0 -54
- data/spec/functional/active_attr/mass_assignment_security_spec.rb +0 -45
- data/spec/unit/active_attr/mass_assignment_security_spec.rb +0 -67
@@ -4,12 +4,12 @@ require "active_support/concern"
|
|
4
4
|
|
5
5
|
module ActiveAttr
|
6
6
|
describe ChainableInitialization do
|
7
|
-
subject { model_class.new("arg") }
|
7
|
+
subject(:model) { model_class.new("arg") }
|
8
8
|
|
9
9
|
shared_examples "chained initialization" do
|
10
10
|
describe "#initialize" do
|
11
|
-
it { expect {
|
12
|
-
it {
|
11
|
+
it { expect { model }.not_to raise_error }
|
12
|
+
it { model.initialized?.should be_true }
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "active_attr/mass_assignment"
|
3
|
+
require "active_model"
|
4
|
+
require "active_model/mass_assignment_security"
|
5
|
+
|
6
|
+
module ActiveAttr
|
7
|
+
describe MassAssignment, :mass_assignment do
|
8
|
+
context "integrating with protected_attributes" do
|
9
|
+
before do
|
10
|
+
model_class.class_eval do
|
11
|
+
include MassAssignment
|
12
|
+
include ActiveModel::MassAssignmentSecurity
|
13
|
+
attr_accessor :age
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
shared_examples "secure mass assignment method", :secure_mass_assignment_method => true do
|
18
|
+
include_examples "mass assignment method"
|
19
|
+
|
20
|
+
it "ignores assigning an attribute protected by role-based security", :active_model_version => ">= 3.1.0" do
|
21
|
+
person = mass_assign_attributes(:age => 21)
|
22
|
+
person.age.should be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "ignores assigning a protected attribute" do
|
26
|
+
person = mass_assign_attributes(:first_name => "Chris")
|
27
|
+
person.age.should be_nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
shared_examples "secure mass assignment method with options", :secure_mass_assignment_method_with_options => true do
|
32
|
+
it "supports role-based mass assignment security", :active_model_version => ">= 3.1.0" do
|
33
|
+
person = mass_assign_attributes_with_options({ :age => 21 }, :as => :admin)
|
34
|
+
person.age.should == 21
|
35
|
+
end
|
36
|
+
|
37
|
+
it "skips security if passed the :without_protection option" do
|
38
|
+
person = mass_assign_attributes_with_options({ :age => 21 }, :without_protection => true)
|
39
|
+
person.age.should == 21
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "white listing attributes" do
|
44
|
+
before do
|
45
|
+
model_class.class_eval do
|
46
|
+
attr_accessible :first_name, :last_name, :name
|
47
|
+
attr_accessible :age, :as => :admin
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#assign_attributes", :assign_attributes, :secure_mass_assignment_method, :secure_mass_assignment_method_with_options
|
52
|
+
describe "#attributes=", :attributes=, :secure_mass_assignment_method
|
53
|
+
describe "#initialize", :initialize, :secure_mass_assignment_method, :secure_mass_assignment_method_with_options
|
54
|
+
end
|
55
|
+
|
56
|
+
context "black listing attributes" do
|
57
|
+
before do
|
58
|
+
model_class.class_eval do
|
59
|
+
attr_protected :age
|
60
|
+
attr_protected :as => :admin
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#assign_attributes", :assign_attributes, :secure_mass_assignment_method, :secure_mass_assignment_method_with_options
|
65
|
+
describe "#attributes=", :attributes=, :secure_mass_assignment_method
|
66
|
+
describe "#initialize", :initialize, :secure_mass_assignment_method, :secure_mass_assignment_method_with_options
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "integrating with strong_parameters", :active_model_version => ">= 3.2.0" do
|
71
|
+
let(:rails3) { Gem::Requirement.create("~> 3.2.0").satisfied_by?(Gem::Version.new(ActiveModel::VERSION::STRING)) }
|
72
|
+
|
73
|
+
before do
|
74
|
+
if rails3
|
75
|
+
require "strong_parameters"
|
76
|
+
|
77
|
+
model_class.class_eval do
|
78
|
+
include ActiveAttr::MassAssignment
|
79
|
+
include ActiveModel::MassAssignmentSecurity
|
80
|
+
include ActiveModel::ForbiddenAttributesProtection
|
81
|
+
attr_accessor :age
|
82
|
+
end
|
83
|
+
else
|
84
|
+
require "action_controller"
|
85
|
+
|
86
|
+
model_class.class_eval do
|
87
|
+
include ActiveAttr::MassAssignment
|
88
|
+
include ActiveModel::MassAssignmentSecurity
|
89
|
+
include ActiveModel::ForbiddenAttributesProtection
|
90
|
+
attr_accessor :age
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
let :forbidden_attributes_error_class do
|
96
|
+
rails3 ? ActiveModel::ForbiddenAttributes : ActiveModel::ForbiddenAttributesError
|
97
|
+
end
|
98
|
+
|
99
|
+
shared_examples "strong mass assignment method", :strong_mass_assignment_method => true do
|
100
|
+
it "raises if provided parameters when none are permitted" do
|
101
|
+
expect { mass_assign_attributes(ActionController::Parameters.new(:age => 21)) }.to raise_error forbidden_attributes_error_class
|
102
|
+
end
|
103
|
+
|
104
|
+
it "sets a permitted parameter" do
|
105
|
+
person = mass_assign_attributes(ActionController::Parameters.new(:age => 21).permit(:age))
|
106
|
+
person.age.should == 21
|
107
|
+
end
|
108
|
+
|
109
|
+
it "does not set forbidden parameters" do
|
110
|
+
person = mass_assign_attributes(ActionController::Parameters.new(:age => 21).permit(:first_name))
|
111
|
+
person.age.should be_nil
|
112
|
+
end
|
113
|
+
|
114
|
+
it "continues to set normal attributes" do
|
115
|
+
person = mass_assign_attributes(:age => 21)
|
116
|
+
person.age.should == 21
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "#assign_attributes", :assign_attributes, :strong_mass_assignment_method
|
121
|
+
describe "#attributes=", :attributes=, :strong_mass_assignment_method
|
122
|
+
describe "#initialize", :initialize, :strong_mass_assignment_method
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -3,6 +3,7 @@ require "active_attr/attributes"
|
|
3
3
|
require "active_attr/attribute_defaults"
|
4
4
|
require "active_attr/matchers/have_attribute_matcher"
|
5
5
|
require "active_attr/typecasted_attributes"
|
6
|
+
require "active_support/core_ext/string/strip"
|
6
7
|
|
7
8
|
module ActiveAttr
|
8
9
|
module Matchers
|
@@ -29,13 +30,13 @@ module ActiveAttr
|
|
29
30
|
end
|
30
31
|
|
31
32
|
describe "#matches?" do
|
32
|
-
it {
|
33
|
+
it { matcher.matches?(model_class).should be_false }
|
33
34
|
end
|
34
35
|
|
35
36
|
describe "#failure_message" do
|
36
|
-
before {
|
37
|
+
before { matcher.matches?(model_class) }
|
37
38
|
|
38
|
-
it {
|
39
|
+
it { matcher.failure_message.should == %{expected #{model_class.name} to include ActiveAttr::Attributes} }
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
@@ -51,13 +52,13 @@ module ActiveAttr
|
|
51
52
|
end
|
52
53
|
|
53
54
|
describe "#matches?" do
|
54
|
-
it {
|
55
|
+
it { matcher.matches?(model_class).should be_false }
|
55
56
|
end
|
56
57
|
|
57
58
|
describe "#failure_message" do
|
58
|
-
before {
|
59
|
+
before { matcher.matches?(model_class) }
|
59
60
|
|
60
|
-
it {
|
61
|
+
it { matcher.failure_message.should == %{expected #{model_class.name} to include ActiveAttr::AttributeDefaults} }
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
@@ -73,18 +74,18 @@ module ActiveAttr
|
|
73
74
|
end
|
74
75
|
|
75
76
|
describe "#matches?" do
|
76
|
-
it {
|
77
|
+
it { matcher.matches?(model_class).should be_false }
|
77
78
|
end
|
78
79
|
|
79
80
|
describe "#failure_message" do
|
80
|
-
before {
|
81
|
+
before { matcher.matches?(model_class) }
|
81
82
|
|
82
|
-
it {
|
83
|
+
it { matcher.failure_message.should == %{expected #{model_class.name} to include ActiveAttr::TypecastedAttributes} }
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
86
87
|
context "a matcher with just an attribute name" do
|
87
|
-
subject { described_class.new(:first_name) }
|
88
|
+
subject(:matcher) { described_class.new(:first_name) }
|
88
89
|
|
89
90
|
it_should_behave_like "a matcher matching a class without ActiveAttr::Attributes"
|
90
91
|
|
@@ -92,31 +93,36 @@ module ActiveAttr
|
|
92
93
|
before { model_class.attribute :first_name }
|
93
94
|
|
94
95
|
describe "#matches?" do
|
95
|
-
it {
|
96
|
+
it { matcher.matches?(model_class).should be_true }
|
96
97
|
end
|
97
98
|
|
98
99
|
describe "#negative_failure_message" do
|
99
|
-
before {
|
100
|
+
before { matcher.matches?(model_class) }
|
100
101
|
|
101
|
-
it
|
102
|
+
it do
|
103
|
+
matcher.negative_failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
104
|
+
expected not: attribute :first_name
|
105
|
+
got: attribute :first_name
|
106
|
+
MESSAGE
|
107
|
+
end
|
102
108
|
end
|
103
109
|
end
|
104
110
|
|
105
111
|
context "a class without the attribute" do
|
106
112
|
describe "#matches?" do
|
107
|
-
it {
|
113
|
+
it { matcher.matches?(model_class).should be_false }
|
108
114
|
end
|
109
115
|
|
110
116
|
describe "#failure_message" do
|
111
|
-
before {
|
117
|
+
before { matcher.matches?(model_class) }
|
112
118
|
|
113
|
-
it {
|
119
|
+
it { matcher.failure_message.should == %{expected Person to have attribute named first_name} }
|
114
120
|
end
|
115
121
|
end
|
116
122
|
end
|
117
123
|
|
118
124
|
context "a matcher with a default value" do
|
119
|
-
subject { described_class.new(:first_name).with_default_value_of("John") }
|
125
|
+
subject(:matcher) { described_class.new(:first_name).with_default_value_of("John") }
|
120
126
|
|
121
127
|
it_should_behave_like "a matcher matching a class without ActiveAttr::Attributes"
|
122
128
|
it_should_behave_like "a matcher matching a class without ActiveAttr::AttributeDefaults"
|
@@ -125,13 +131,18 @@ module ActiveAttr
|
|
125
131
|
before { model_class.attribute :first_name }
|
126
132
|
|
127
133
|
describe "#matches?" do
|
128
|
-
it {
|
134
|
+
it { matcher.matches?(model_class).should be_false }
|
129
135
|
end
|
130
136
|
|
131
137
|
describe "#failure_message" do
|
132
|
-
before {
|
138
|
+
before { matcher.matches?(model_class) }
|
133
139
|
|
134
|
-
it
|
140
|
+
it do
|
141
|
+
matcher.failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
142
|
+
expected: attribute :first_name, :default => "John"
|
143
|
+
got: attribute :first_name
|
144
|
+
MESSAGE
|
145
|
+
end
|
135
146
|
end
|
136
147
|
end
|
137
148
|
|
@@ -139,13 +150,18 @@ module ActiveAttr
|
|
139
150
|
before { model_class.attribute :first_name, :default => "Doe" }
|
140
151
|
|
141
152
|
describe "#matches?" do
|
142
|
-
it {
|
153
|
+
it { matcher.matches?(model_class).should be_false }
|
143
154
|
end
|
144
155
|
|
145
156
|
describe "#failure_message" do
|
146
|
-
before {
|
157
|
+
before { matcher.matches?(model_class) }
|
147
158
|
|
148
|
-
it
|
159
|
+
it do
|
160
|
+
matcher.failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
161
|
+
expected: attribute :first_name, :default => "John"
|
162
|
+
got: attribute :first_name, :default => "Doe"
|
163
|
+
MESSAGE
|
164
|
+
end
|
149
165
|
end
|
150
166
|
end
|
151
167
|
|
@@ -153,19 +169,24 @@ module ActiveAttr
|
|
153
169
|
before { model_class.attribute :first_name, :default => "John" }
|
154
170
|
|
155
171
|
describe "#matches?" do
|
156
|
-
it {
|
172
|
+
it { matcher.matches?(model_class).should be_true }
|
157
173
|
end
|
158
174
|
|
159
175
|
describe "#negative_failure_message" do
|
160
|
-
before {
|
176
|
+
before { matcher.matches?(model_class) }
|
161
177
|
|
162
|
-
it
|
178
|
+
it do
|
179
|
+
matcher.negative_failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
180
|
+
expected not: attribute :first_name, :default => "John"
|
181
|
+
got: attribute :first_name, :default => "John"
|
182
|
+
MESSAGE
|
183
|
+
end
|
163
184
|
end
|
164
185
|
end
|
165
186
|
end
|
166
187
|
|
167
188
|
context "a matcher with a default value of false" do
|
168
|
-
subject { described_class.new(:admin).with_default_value_of(false) }
|
189
|
+
subject(:matcher) { described_class.new(:admin).with_default_value_of(false) }
|
169
190
|
|
170
191
|
it_should_behave_like "a matcher matching a class without ActiveAttr::Attributes"
|
171
192
|
it_should_behave_like "a matcher matching a class without ActiveAttr::AttributeDefaults"
|
@@ -174,13 +195,18 @@ module ActiveAttr
|
|
174
195
|
before { model_class.attribute :admin }
|
175
196
|
|
176
197
|
describe "#matches?" do
|
177
|
-
it {
|
198
|
+
it { matcher.matches?(model_class).should be_false }
|
178
199
|
end
|
179
200
|
|
180
201
|
describe "#failure_message" do
|
181
|
-
before {
|
202
|
+
before { matcher.matches?(model_class) }
|
182
203
|
|
183
|
-
it
|
204
|
+
it do
|
205
|
+
matcher.failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
206
|
+
expected: attribute :admin, :default => false
|
207
|
+
got: attribute :admin
|
208
|
+
MESSAGE
|
209
|
+
end
|
184
210
|
end
|
185
211
|
end
|
186
212
|
|
@@ -188,13 +214,18 @@ module ActiveAttr
|
|
188
214
|
before { model_class.attribute :admin, :default => nil }
|
189
215
|
|
190
216
|
describe "#matches?" do
|
191
|
-
it {
|
217
|
+
it { matcher.matches?(model_class).should be_false }
|
192
218
|
end
|
193
219
|
|
194
220
|
describe "#failure_message" do
|
195
|
-
before {
|
221
|
+
before { matcher.matches?(model_class) }
|
196
222
|
|
197
|
-
it
|
223
|
+
it do
|
224
|
+
matcher.failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
225
|
+
expected: attribute :admin, :default => false
|
226
|
+
got: attribute :admin, :default => nil
|
227
|
+
MESSAGE
|
228
|
+
end
|
198
229
|
end
|
199
230
|
end
|
200
231
|
|
@@ -202,19 +233,24 @@ module ActiveAttr
|
|
202
233
|
before { model_class.attribute :admin, :default => false }
|
203
234
|
|
204
235
|
describe "#matches?" do
|
205
|
-
it {
|
236
|
+
it { matcher.matches?(model_class).should be_true }
|
206
237
|
end
|
207
238
|
|
208
239
|
describe "#negative_failure_message" do
|
209
|
-
before {
|
240
|
+
before { matcher.matches?(model_class) }
|
210
241
|
|
211
|
-
it
|
242
|
+
it do
|
243
|
+
matcher.negative_failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
244
|
+
expected not: attribute :admin, :default => false
|
245
|
+
got: attribute :admin, :default => false
|
246
|
+
MESSAGE
|
247
|
+
end
|
212
248
|
end
|
213
249
|
end
|
214
250
|
end
|
215
251
|
|
216
252
|
context "a matcher with a default value of nil" do
|
217
|
-
subject { described_class.new(:first_name).with_default_value_of(nil) }
|
253
|
+
subject(:matcher) { described_class.new(:first_name).with_default_value_of(nil) }
|
218
254
|
|
219
255
|
it_should_behave_like "a matcher matching a class without ActiveAttr::Attributes"
|
220
256
|
it_should_behave_like "a matcher matching a class without ActiveAttr::AttributeDefaults"
|
@@ -223,13 +259,18 @@ module ActiveAttr
|
|
223
259
|
before { model_class.attribute :first_name }
|
224
260
|
|
225
261
|
describe "#matches?" do
|
226
|
-
it {
|
262
|
+
it { matcher.matches?(model_class).should be_true }
|
227
263
|
end
|
228
264
|
|
229
265
|
describe "#negative_failure_message" do
|
230
|
-
before {
|
266
|
+
before { matcher.matches?(model_class) }
|
231
267
|
|
232
|
-
it
|
268
|
+
it do
|
269
|
+
matcher.negative_failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
270
|
+
expected not: attribute :first_name, :default => nil
|
271
|
+
got: attribute :first_name
|
272
|
+
MESSAGE
|
273
|
+
end
|
233
274
|
end
|
234
275
|
end
|
235
276
|
|
@@ -237,13 +278,18 @@ module ActiveAttr
|
|
237
278
|
before { model_class.attribute :first_name, :default => false }
|
238
279
|
|
239
280
|
describe "#matches?" do
|
240
|
-
it {
|
281
|
+
it { matcher.matches?(model_class).should be_false }
|
241
282
|
end
|
242
283
|
|
243
284
|
describe "#failure_message" do
|
244
|
-
before {
|
285
|
+
before { matcher.matches?(model_class) }
|
245
286
|
|
246
|
-
it
|
287
|
+
it do
|
288
|
+
matcher.failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
289
|
+
expected: attribute :first_name, :default => nil
|
290
|
+
got: attribute :first_name, :default => false
|
291
|
+
MESSAGE
|
292
|
+
end
|
247
293
|
end
|
248
294
|
end
|
249
295
|
|
@@ -251,19 +297,24 @@ module ActiveAttr
|
|
251
297
|
before { model_class.attribute :first_name, :default => nil }
|
252
298
|
|
253
299
|
describe "#matches?" do
|
254
|
-
it {
|
300
|
+
it { matcher.matches?(model_class).should be_true }
|
255
301
|
end
|
256
302
|
|
257
303
|
describe "#negative_failure_message" do
|
258
|
-
before {
|
304
|
+
before { matcher.matches?(model_class) }
|
259
305
|
|
260
|
-
it
|
306
|
+
it do
|
307
|
+
matcher.negative_failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
308
|
+
expected not: attribute :first_name, :default => nil
|
309
|
+
got: attribute :first_name, :default => nil
|
310
|
+
MESSAGE
|
311
|
+
end
|
261
312
|
end
|
262
313
|
end
|
263
314
|
end
|
264
315
|
|
265
316
|
context "a matcher with a type" do
|
266
|
-
subject { described_class.new(:first_name).of_type(String) }
|
317
|
+
subject(:matcher) { described_class.new(:first_name).of_type(String) }
|
267
318
|
|
268
319
|
it_should_behave_like "a matcher matching a class without ActiveAttr::Attributes"
|
269
320
|
it_should_behave_like "a matcher matching a class without ActiveAttr::TypecastedAttributes"
|
@@ -272,13 +323,18 @@ module ActiveAttr
|
|
272
323
|
before { model_class.attribute :first_name }
|
273
324
|
|
274
325
|
describe "#matches?" do
|
275
|
-
it {
|
326
|
+
it { matcher.matches?(model_class).should be_false }
|
276
327
|
end
|
277
328
|
|
278
329
|
describe "#failure_message" do
|
279
|
-
before {
|
330
|
+
before { matcher.matches?(model_class) }
|
280
331
|
|
281
|
-
it
|
332
|
+
it do
|
333
|
+
matcher.failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
334
|
+
expected: attribute :first_name, :type => String
|
335
|
+
got: attribute :first_name
|
336
|
+
MESSAGE
|
337
|
+
end
|
282
338
|
end
|
283
339
|
end
|
284
340
|
|
@@ -286,13 +342,18 @@ module ActiveAttr
|
|
286
342
|
before { model_class.attribute :first_name, :type => Symbol }
|
287
343
|
|
288
344
|
describe "#matches?" do
|
289
|
-
it {
|
345
|
+
it { matcher.matches?(model_class).should be_false }
|
290
346
|
end
|
291
347
|
|
292
348
|
describe "#failure_message" do
|
293
|
-
before {
|
349
|
+
before { matcher.matches?(model_class) }
|
294
350
|
|
295
|
-
it
|
351
|
+
it do
|
352
|
+
matcher.failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
353
|
+
expected: attribute :first_name, :type => String
|
354
|
+
got: attribute :first_name, :type => Symbol
|
355
|
+
MESSAGE
|
356
|
+
end
|
296
357
|
end
|
297
358
|
end
|
298
359
|
|
@@ -300,19 +361,24 @@ module ActiveAttr
|
|
300
361
|
before { model_class.attribute :first_name, :type => String }
|
301
362
|
|
302
363
|
describe "#matches?" do
|
303
|
-
it {
|
364
|
+
it { matcher.matches?(model_class).should be_true }
|
304
365
|
end
|
305
366
|
|
306
367
|
describe "#negative_failure_message" do
|
307
|
-
before {
|
368
|
+
before { matcher.matches?(model_class) }
|
308
369
|
|
309
|
-
it
|
370
|
+
it do
|
371
|
+
matcher.negative_failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
372
|
+
expected not: attribute :first_name, :type => String
|
373
|
+
got: attribute :first_name, :type => String
|
374
|
+
MESSAGE
|
375
|
+
end
|
310
376
|
end
|
311
377
|
end
|
312
378
|
end
|
313
379
|
|
314
380
|
context "a matcher with a type of Object" do
|
315
|
-
subject { described_class.new(:first_name).of_type(Object) }
|
381
|
+
subject(:matcher) { described_class.new(:first_name).of_type(Object) }
|
316
382
|
|
317
383
|
it_should_behave_like "a matcher matching a class without ActiveAttr::Attributes"
|
318
384
|
it_should_behave_like "a matcher matching a class without ActiveAttr::TypecastedAttributes"
|
@@ -321,13 +387,18 @@ module ActiveAttr
|
|
321
387
|
before { model_class.attribute :first_name }
|
322
388
|
|
323
389
|
describe "#matches?" do
|
324
|
-
it {
|
390
|
+
it { matcher.matches?(model_class).should be_true }
|
325
391
|
end
|
326
392
|
|
327
393
|
describe "#negative_failure_message" do
|
328
|
-
before {
|
394
|
+
before { matcher.matches?(model_class) }
|
329
395
|
|
330
|
-
it
|
396
|
+
it do
|
397
|
+
matcher.negative_failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
398
|
+
expected not: attribute :first_name, :type => Object
|
399
|
+
got: attribute :first_name
|
400
|
+
MESSAGE
|
401
|
+
end
|
331
402
|
end
|
332
403
|
end
|
333
404
|
|
@@ -335,13 +406,18 @@ module ActiveAttr
|
|
335
406
|
before { model_class.attribute :first_name, :type => String }
|
336
407
|
|
337
408
|
describe "#matches?" do
|
338
|
-
it {
|
409
|
+
it { matcher.matches?(model_class).should be_false }
|
339
410
|
end
|
340
411
|
|
341
412
|
describe "#failure_message" do
|
342
|
-
before {
|
413
|
+
before { matcher.matches?(model_class) }
|
343
414
|
|
344
|
-
it
|
415
|
+
it do
|
416
|
+
matcher.failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
417
|
+
expected: attribute :first_name, :type => Object
|
418
|
+
got: attribute :first_name, :type => String
|
419
|
+
MESSAGE
|
420
|
+
end
|
345
421
|
end
|
346
422
|
end
|
347
423
|
|
@@ -349,13 +425,18 @@ module ActiveAttr
|
|
349
425
|
before { model_class.attribute :first_name, :type => Object }
|
350
426
|
|
351
427
|
describe "#matches?" do
|
352
|
-
it {
|
428
|
+
it { matcher.matches?(model_class).should be_true }
|
353
429
|
end
|
354
430
|
|
355
431
|
describe "#negative_failure_message" do
|
356
|
-
before {
|
432
|
+
before { matcher.matches?(model_class) }
|
357
433
|
|
358
|
-
it
|
434
|
+
it do
|
435
|
+
matcher.negative_failure_message.should == <<-MESSAGE.strip_heredoc.chomp
|
436
|
+
expected not: attribute :first_name, :type => Object
|
437
|
+
got: attribute :first_name, :type => Object
|
438
|
+
MESSAGE
|
439
|
+
end
|
359
440
|
end
|
360
441
|
end
|
361
442
|
end
|