active_attr 0.2.2 → 0.3.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/CHANGELOG.md +15 -0
- data/README.md +83 -11
- data/active_attr.gemspec +4 -3
- data/lib/active_attr.rb +5 -0
- data/lib/active_attr/attributes.rb +72 -24
- data/lib/active_attr/block_initialization.rb +37 -0
- data/lib/active_attr/chainable_initialization.rb +6 -4
- data/lib/active_attr/dangerous_attribute_error.rb +11 -0
- data/lib/active_attr/logger.rb +46 -0
- data/lib/active_attr/mass_assignment_security.rb +42 -0
- data/lib/active_attr/query_attributes.rb +62 -0
- data/lib/active_attr/railtie.rb +10 -0
- data/lib/active_attr/unknown_attribute_error.rb +19 -0
- data/lib/active_attr/version.rb +1 -1
- data/spec/functional/active_attr/attributes_spec.rb +104 -0
- data/spec/functional/active_attr/query_attributes_spec.rb +32 -0
- data/spec/support/mass_assignment_shared_examples.rb +9 -0
- data/spec/unit/active_attr/attributes_spec.rb +73 -39
- data/spec/unit/active_attr/block_initialization_spec.rb +39 -0
- data/spec/unit/active_attr/dangerous_attribute_error_spec.rb +9 -0
- data/spec/unit/active_attr/logger_spec.rb +186 -0
- data/spec/unit/active_attr/mass_assignment_security_spec.rb +62 -0
- data/spec/unit/active_attr/query_attributes_spec.rb +225 -0
- data/spec/unit/active_attr/unknown_attribute_error_spec.rb +9 -0
- metadata +48 -17
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "active_attr/block_initialization"
|
3
|
+
|
4
|
+
module ActiveAttr
|
5
|
+
describe BlockInitialization do
|
6
|
+
subject { model_class.new("arg") {} }
|
7
|
+
|
8
|
+
let :model_class do
|
9
|
+
Class.new do
|
10
|
+
include InitializationVerifier
|
11
|
+
include BlockInitialization
|
12
|
+
|
13
|
+
def initialize(arg)
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#initialize" do
|
20
|
+
it "invokes the superclass initializer" do
|
21
|
+
should be_initialized
|
22
|
+
end
|
23
|
+
|
24
|
+
it "doesn't raise when not passed a block" do
|
25
|
+
expect { model_class.new("arg") }.not_to raise_error
|
26
|
+
end
|
27
|
+
|
28
|
+
it "yields the new instance" do
|
29
|
+
yielded_instance = nil
|
30
|
+
|
31
|
+
returned_instance = model_class.new("arg") do |yielded|
|
32
|
+
yielded_instance = yielded
|
33
|
+
end
|
34
|
+
|
35
|
+
returned_instance.should equal yielded_instance
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "active_attr/logger"
|
3
|
+
|
4
|
+
module ActiveAttr
|
5
|
+
describe Logger do
|
6
|
+
subject { model_class.new }
|
7
|
+
let(:logger) { double "logger" }
|
8
|
+
let(:child_class) { Class.new(parent_class) }
|
9
|
+
let(:parent_class) { model_class }
|
10
|
+
|
11
|
+
let :model_class do
|
12
|
+
Class.new do
|
13
|
+
include Logger
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when the logger is not set" do
|
18
|
+
it "#{described_class}.logger is nil" do
|
19
|
+
described_class.logger.should be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it "#{described_class}.logger? is false" do
|
23
|
+
described_class.logger?.should == false
|
24
|
+
end
|
25
|
+
|
26
|
+
it ".logger is nil" do
|
27
|
+
model_class.logger.should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it ".logger? is false" do
|
31
|
+
model_class.logger?.should == false
|
32
|
+
end
|
33
|
+
|
34
|
+
it "#logger is nil" do
|
35
|
+
subject.logger.should be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "#logger? is false" do
|
39
|
+
subject.logger?.should == false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when the logger is set on the module" do
|
44
|
+
before { described_class.logger = logger }
|
45
|
+
after { described_class.logger = nil }
|
46
|
+
|
47
|
+
it "#{described_class}.logger is the logger" do
|
48
|
+
described_class.logger.should == logger
|
49
|
+
end
|
50
|
+
|
51
|
+
it "#{described_class}.logger? is true" do
|
52
|
+
described_class.logger?.should == true
|
53
|
+
end
|
54
|
+
|
55
|
+
it ".logger is the logger" do
|
56
|
+
model_class.logger.should == logger
|
57
|
+
end
|
58
|
+
|
59
|
+
it ".logger? is true" do
|
60
|
+
model_class.logger?.should == true
|
61
|
+
end
|
62
|
+
|
63
|
+
it "#logger is the logger" do
|
64
|
+
subject.logger.should == logger
|
65
|
+
end
|
66
|
+
|
67
|
+
it "#logger? is true" do
|
68
|
+
subject.logger?.should == true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when the logger is set on the class" do
|
73
|
+
before { model_class.logger = logger }
|
74
|
+
|
75
|
+
it "#{described_class}.logger is nil" do
|
76
|
+
described_class.logger.should be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it "#{described_class}.logger? is false" do
|
80
|
+
described_class.logger?.should == false
|
81
|
+
end
|
82
|
+
|
83
|
+
it ".logger is the logger" do
|
84
|
+
model_class.logger.should == logger
|
85
|
+
end
|
86
|
+
|
87
|
+
it ".logger? is true" do
|
88
|
+
model_class.logger?.should == true
|
89
|
+
end
|
90
|
+
|
91
|
+
it "#logger is the logger" do
|
92
|
+
subject.logger.should == logger
|
93
|
+
end
|
94
|
+
|
95
|
+
it "#logger? is true" do
|
96
|
+
subject.logger?.should == true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "when the logger is set on a parent class" do
|
101
|
+
before { parent_class.logger = logger }
|
102
|
+
subject { child_class.new }
|
103
|
+
|
104
|
+
it "#{described_class}.logger is nil" do
|
105
|
+
described_class.logger.should be_nil
|
106
|
+
end
|
107
|
+
|
108
|
+
it "#{described_class}.logger? is false" do
|
109
|
+
described_class.logger?.should == false
|
110
|
+
end
|
111
|
+
|
112
|
+
it ".logger is the logger" do
|
113
|
+
child_class.logger.should == logger
|
114
|
+
end
|
115
|
+
|
116
|
+
it ".logger? is true" do
|
117
|
+
child_class.logger?.should == true
|
118
|
+
end
|
119
|
+
|
120
|
+
it "#logger is the logger" do
|
121
|
+
subject.logger.should == logger
|
122
|
+
end
|
123
|
+
|
124
|
+
it "#logger? is true" do
|
125
|
+
subject.logger?.should == true
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "when the logger is set on a child class" do
|
130
|
+
before { child_class.logger = logger }
|
131
|
+
subject { parent_class.new }
|
132
|
+
|
133
|
+
it "#{described_class}.logger is nil" do
|
134
|
+
described_class.logger.should be_nil
|
135
|
+
end
|
136
|
+
|
137
|
+
it "#{described_class}.logger? is false" do
|
138
|
+
described_class.logger?.should == false
|
139
|
+
end
|
140
|
+
|
141
|
+
it ".logger is nil" do
|
142
|
+
parent_class.logger.should be_nil
|
143
|
+
end
|
144
|
+
|
145
|
+
it ".logger? is false" do
|
146
|
+
parent_class.logger?.should == false
|
147
|
+
end
|
148
|
+
|
149
|
+
it "#logger is nil" do
|
150
|
+
subject.logger.should be_nil
|
151
|
+
end
|
152
|
+
|
153
|
+
it "#logger? is false" do
|
154
|
+
subject.logger?.should == false
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "when the logger is set on the instance" do
|
159
|
+
before { subject.logger = logger }
|
160
|
+
|
161
|
+
it "#{described_class}.logger is nil" do
|
162
|
+
described_class.logger.should be_nil
|
163
|
+
end
|
164
|
+
|
165
|
+
it "#{described_class}.logger? is false" do
|
166
|
+
described_class.logger?.should == false
|
167
|
+
end
|
168
|
+
|
169
|
+
it ".logger is nil" do
|
170
|
+
model_class.logger.should be_nil
|
171
|
+
end
|
172
|
+
|
173
|
+
it ".logger? is false" do
|
174
|
+
model_class.logger?.should == false
|
175
|
+
end
|
176
|
+
|
177
|
+
it "#logger is the logger" do
|
178
|
+
subject.logger.should == logger
|
179
|
+
end
|
180
|
+
|
181
|
+
it "#logger? is true" do
|
182
|
+
subject.logger?.should == true
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "active_attr/mass_assignment_security"
|
3
|
+
|
4
|
+
module ActiveAttr
|
5
|
+
describe MassAssignmentSecurity, :mass_assignment do
|
6
|
+
subject { model_class }
|
7
|
+
|
8
|
+
before do
|
9
|
+
model_class.class_eval do
|
10
|
+
include MassAssignmentSecurity
|
11
|
+
attr_accessor :age
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
shared_examples "secure mass assignment method", :secure_mass_assignment_method => true do
|
16
|
+
include_examples "mass assignment method"
|
17
|
+
|
18
|
+
it "ignores assigning a protected attribute" do
|
19
|
+
person = mass_assign_attributes(:age => 21)
|
20
|
+
person.age.should be_nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
shared_examples "secure mass assignment method with options", :secure_mass_assignment_method_with_options => true do
|
25
|
+
it "supports role-based mass assignment security" do
|
26
|
+
person = mass_assign_attributes_with_options({ :age => 21 }, :as => :admin)
|
27
|
+
person.age.should == 21
|
28
|
+
end
|
29
|
+
|
30
|
+
it "skips security if passed the :without_protection option" do
|
31
|
+
person = mass_assign_attributes_with_options({ :age => 21 }, :without_protection => true)
|
32
|
+
person.age.should == 21
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "white listing attributes" do
|
37
|
+
before do
|
38
|
+
model_class.class_eval do
|
39
|
+
attr_accessible :first_name, :last_name, :name
|
40
|
+
attr_accessible :age, :as => :admin
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#assign_attributes", :assign_attributes, :secure_mass_assignment_method, :secure_mass_assignment_method_with_options
|
45
|
+
describe "#attributes=", :attributes=, :secure_mass_assignment_method
|
46
|
+
describe "#initialize", :initialize, :secure_mass_assignment_method, :secure_mass_assignment_method_with_options
|
47
|
+
end
|
48
|
+
|
49
|
+
context "black listing attributes" do
|
50
|
+
before do
|
51
|
+
model_class.class_eval do
|
52
|
+
attr_protected :age
|
53
|
+
attr_protected :as => :admin
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#assign_attributes", :assign_attributes, :secure_mass_assignment_method, :secure_mass_assignment_method_with_options
|
58
|
+
describe "#attributes=", :attributes=, :secure_mass_assignment_method
|
59
|
+
describe "#initialize", :initialize, :secure_mass_assignment_method, :secure_mass_assignment_method_with_options
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "active_attr/query_attributes"
|
3
|
+
require "bigdecimal"
|
4
|
+
|
5
|
+
module ActiveAttr
|
6
|
+
describe QueryAttributes do
|
7
|
+
subject { model_class.new }
|
8
|
+
|
9
|
+
let :model_class do
|
10
|
+
Class.new do
|
11
|
+
include QueryAttributes
|
12
|
+
|
13
|
+
attribute :value
|
14
|
+
attribute :overridden
|
15
|
+
|
16
|
+
def overridden?
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def true?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def false?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".attribute" do
|
31
|
+
it "defines an attribute predicate method that calls #attribute?" do
|
32
|
+
subject.should_receive(:attribute?).with("value")
|
33
|
+
subject.value?
|
34
|
+
end
|
35
|
+
|
36
|
+
it "defines an attribute reader that can be called via super" do
|
37
|
+
subject.should_receive(:attribute?).with("overridden")
|
38
|
+
subject.overridden?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#query_attribute" do
|
43
|
+
it "raises ArgumentError when called with two arguments" do
|
44
|
+
expect { subject.query_attribute(:a, :b) }.to raise_error ArgumentError
|
45
|
+
end
|
46
|
+
|
47
|
+
it "does not raise when called with a single argument" do
|
48
|
+
expect { subject.query_attribute(:a) }.not_to raise_error ArgumentError
|
49
|
+
end
|
50
|
+
|
51
|
+
it "raises ArgumentError when called with no arguments" do
|
52
|
+
expect { subject.query_attribute }.to raise_error ArgumentError
|
53
|
+
end
|
54
|
+
|
55
|
+
it "calls the predicate method if defined" do
|
56
|
+
subject.query_attribute(:true).should == true
|
57
|
+
subject.query_attribute(:false).should == false
|
58
|
+
end
|
59
|
+
|
60
|
+
it "raises when getting an undefined attribute" do
|
61
|
+
expect { subject.query_attribute(:initials) }.to raise_error UnknownAttributeError, "unknown attribute: initials"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "is false when the attribute is false" do
|
65
|
+
subject.value = false
|
66
|
+
subject.value?.should == false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "is true when the attribute is true" do
|
70
|
+
subject.value = true
|
71
|
+
subject.value?.should == true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "is false when the attribute is nil" do
|
75
|
+
subject.value = nil
|
76
|
+
subject.value?.should == false
|
77
|
+
end
|
78
|
+
|
79
|
+
it "is true when the attribute is an Object" do
|
80
|
+
subject.value = Object.new
|
81
|
+
subject.value?.should == true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "is false when the attribute is an empty string" do
|
85
|
+
subject.value = ""
|
86
|
+
subject.value?.should == false
|
87
|
+
end
|
88
|
+
|
89
|
+
it "is true when the attribute is a non-empty string" do
|
90
|
+
subject.value = "Chris"
|
91
|
+
subject.value?.should == true
|
92
|
+
end
|
93
|
+
|
94
|
+
it "is false when the attribute is 0" do
|
95
|
+
subject.value = 0
|
96
|
+
subject.value?.should == false
|
97
|
+
end
|
98
|
+
|
99
|
+
it "is true when the attribute is 1" do
|
100
|
+
subject.value = 1
|
101
|
+
subject.value?.should == true
|
102
|
+
end
|
103
|
+
|
104
|
+
it "is false when the attribute is 0.0" do
|
105
|
+
subject.value = 0.0
|
106
|
+
subject.value?.should == false
|
107
|
+
end
|
108
|
+
|
109
|
+
it "is true when the attribute is 0.1" do
|
110
|
+
subject.value = 0.1
|
111
|
+
subject.value?.should == true
|
112
|
+
end
|
113
|
+
|
114
|
+
it "is false when the attribute is a zero BigDecimal" do
|
115
|
+
subject.value = BigDecimal.new("0.0")
|
116
|
+
subject.value?.should == false
|
117
|
+
end
|
118
|
+
|
119
|
+
it "is true when the attribute is a non-zero BigDecimal" do
|
120
|
+
subject.value = BigDecimal.new("0.1")
|
121
|
+
subject.value?.should == true
|
122
|
+
end
|
123
|
+
|
124
|
+
it "is true when the attribute is -1" do
|
125
|
+
subject.value = -1
|
126
|
+
subject.value?.should == true
|
127
|
+
end
|
128
|
+
|
129
|
+
it "is false when the attribute is -0.0" do
|
130
|
+
subject.value = -0.0
|
131
|
+
subject.value?.should == false
|
132
|
+
end
|
133
|
+
|
134
|
+
it "is true when the attribute is -0.1" do
|
135
|
+
subject.value = -0.1
|
136
|
+
subject.value?.should == true
|
137
|
+
end
|
138
|
+
|
139
|
+
it "is false when the attribute is a negative zero BigDecimal" do
|
140
|
+
subject.value = BigDecimal.new("-0.0")
|
141
|
+
subject.value?.should == false
|
142
|
+
end
|
143
|
+
|
144
|
+
it "is true when the attribute is a negative BigDecimal" do
|
145
|
+
subject.value = BigDecimal.new("-0.1")
|
146
|
+
subject.value?.should == true
|
147
|
+
end
|
148
|
+
|
149
|
+
it "is false when the attribute is '0'" do
|
150
|
+
subject.value = "0"
|
151
|
+
subject.value?.should == false
|
152
|
+
end
|
153
|
+
|
154
|
+
it "is true when the attribute is '1'" do
|
155
|
+
subject.value = "1"
|
156
|
+
subject.value?.should == true
|
157
|
+
end
|
158
|
+
|
159
|
+
it "is false when the attribute is '0.0'" do
|
160
|
+
subject.value = "0.0"
|
161
|
+
subject.value?.should == false
|
162
|
+
end
|
163
|
+
|
164
|
+
it "is true when the attribute is '0.1'" do
|
165
|
+
subject.value = "0.1"
|
166
|
+
subject.value?.should == true
|
167
|
+
end
|
168
|
+
|
169
|
+
it "is true when the attribute is '-1'" do
|
170
|
+
subject.value = "-1"
|
171
|
+
subject.value?.should == true
|
172
|
+
end
|
173
|
+
|
174
|
+
it "is false when the attribute is '-0.0'" do
|
175
|
+
subject.value = "-0.0"
|
176
|
+
subject.value?.should == false
|
177
|
+
end
|
178
|
+
|
179
|
+
it "is true when the attribute is '-0.1'" do
|
180
|
+
subject.value = "-0.1"
|
181
|
+
subject.value?.should == true
|
182
|
+
end
|
183
|
+
|
184
|
+
it "is true when the attribute is 'true'" do
|
185
|
+
subject.value = "true"
|
186
|
+
subject.value?.should == true
|
187
|
+
end
|
188
|
+
|
189
|
+
it "is false when the attribute is 'false'" do
|
190
|
+
subject.value = "false"
|
191
|
+
subject.value?.should == false
|
192
|
+
end
|
193
|
+
|
194
|
+
it "is true when the attribute is 't'" do
|
195
|
+
subject.value = "t"
|
196
|
+
subject.value?.should == true
|
197
|
+
end
|
198
|
+
|
199
|
+
it "is false when the attribute is 'f'" do
|
200
|
+
subject.value = "f"
|
201
|
+
subject.value?.should == false
|
202
|
+
end
|
203
|
+
|
204
|
+
it "is true when the attribute is 'T'" do
|
205
|
+
subject.value = "T"
|
206
|
+
subject.value?.should == true
|
207
|
+
end
|
208
|
+
|
209
|
+
it "is false when the attribute is 'F'" do
|
210
|
+
subject.value = "F"
|
211
|
+
subject.value?.should == false
|
212
|
+
end
|
213
|
+
|
214
|
+
it "is true when the attribute is 'TRUE'" do
|
215
|
+
subject.value = "TRUE"
|
216
|
+
subject.value?.should == true
|
217
|
+
end
|
218
|
+
|
219
|
+
it "is false when the attribute is 'FALSE" do
|
220
|
+
subject.value = "FALSE"
|
221
|
+
subject.value?.should == false
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|