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
@@ -3,7 +3,7 @@ require "active_attr/typecasted_attributes"
|
|
3
3
|
|
4
4
|
module ActiveAttr
|
5
5
|
describe TypecastedAttributes do
|
6
|
-
subject { model_class.new }
|
6
|
+
subject(:model) { model_class.new }
|
7
7
|
|
8
8
|
let :model_class do
|
9
9
|
Class.new do
|
@@ -35,13 +35,13 @@ module ActiveAttr
|
|
35
35
|
|
36
36
|
describe ".attribute" do
|
37
37
|
it "defines an attribute pre-typecasting reader that calls #attribute_before_type_cast" do
|
38
|
-
|
39
|
-
|
38
|
+
model.should_receive(:attribute_before_type_cast).with("first_name")
|
39
|
+
model.first_name_before_type_cast
|
40
40
|
end
|
41
41
|
|
42
42
|
it "defines an attribute reader that can be called via super" do
|
43
|
-
|
44
|
-
|
43
|
+
model.should_receive(:attribute_before_type_cast).with("last_name")
|
44
|
+
model.last_name_before_type_cast
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -61,19 +61,19 @@ module ActiveAttr
|
|
61
61
|
|
62
62
|
describe "#attribute_before_type_cast" do
|
63
63
|
it "returns nil when the attribute has not been assigned yet" do
|
64
|
-
|
64
|
+
model.attribute_before_type_cast(:amount).should be_nil
|
65
65
|
end
|
66
66
|
|
67
67
|
it "returns the assigned attribute value, without typecasting, when given an attribute name as a Symbol" do
|
68
68
|
value = :value
|
69
|
-
|
70
|
-
|
69
|
+
model.amount = value
|
70
|
+
model.attribute_before_type_cast(:amount).should equal value
|
71
71
|
end
|
72
72
|
|
73
73
|
it "returns the assigned attribute value, without typecasting, when given an attribute name as a String" do
|
74
74
|
value = :value
|
75
|
-
|
76
|
-
|
75
|
+
model.amount = value
|
76
|
+
model.attribute_before_type_cast('amount').should equal value
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
@@ -4,34 +4,36 @@ require "active_attr/typecasting/big_decimal_typecaster"
|
|
4
4
|
module ActiveAttr
|
5
5
|
module Typecasting
|
6
6
|
describe BigDecimalTypecaster do
|
7
|
+
subject(:typecaster) { described_class.new }
|
8
|
+
|
7
9
|
describe "#call" do
|
8
10
|
it "returns the original BigDecimal for a BigDecimal" do
|
9
11
|
value = BigDecimal.new("2.0")
|
10
|
-
|
12
|
+
typecaster.call(value).should equal value
|
11
13
|
end
|
12
14
|
|
13
15
|
it "casts nil to a zero BigDecimal" do
|
14
|
-
|
16
|
+
typecaster.call(nil).should eql BigDecimal.new("0.0")
|
15
17
|
end
|
16
18
|
|
17
19
|
it "casts a numeric String to a BigDecimal" do
|
18
|
-
|
20
|
+
typecaster.call("2").should eql BigDecimal.new("2.0")
|
19
21
|
end
|
20
22
|
|
21
23
|
it "casts a alpha String to a zero BigDecimal" do
|
22
|
-
|
24
|
+
typecaster.call("bob").should eql BigDecimal.new("0.0")
|
23
25
|
end
|
24
26
|
|
25
27
|
it "casts a Rational to a BigDecimal" do
|
26
|
-
|
28
|
+
typecaster.call(Rational(1, 2)).should eql BigDecimal.new("0.5")
|
27
29
|
end
|
28
30
|
|
29
31
|
it "casts a Float to a BigDecimal" do
|
30
|
-
|
32
|
+
typecaster.call(1.2).should eql BigDecimal.new("1.2")
|
31
33
|
end
|
32
34
|
|
33
35
|
it "cases an Integer to a BigDecimal" do
|
34
|
-
|
36
|
+
typecaster.call(2).should eql BigDecimal.new("2.0")
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -5,30 +5,32 @@ require "bigdecimal"
|
|
5
5
|
module ActiveAttr
|
6
6
|
module Typecasting
|
7
7
|
describe BooleanTypecaster do
|
8
|
+
subject(:typecaster) { described_class.new }
|
9
|
+
|
8
10
|
describe "#call" do
|
9
11
|
it "returns true for true" do
|
10
|
-
|
12
|
+
typecaster.call(true).should equal true
|
11
13
|
end
|
12
14
|
|
13
15
|
it "returns false for false" do
|
14
|
-
|
16
|
+
typecaster.call(false).should equal false
|
15
17
|
end
|
16
18
|
|
17
19
|
it "casts nil to false" do
|
18
|
-
|
20
|
+
typecaster.call(nil).should equal false
|
19
21
|
end
|
20
22
|
|
21
23
|
it "casts an Object to true" do
|
22
|
-
|
24
|
+
typecaster.call(Object.new).should equal true
|
23
25
|
end
|
24
26
|
|
25
27
|
context "when the value is a String" do
|
26
28
|
it "casts an empty String to false" do
|
27
|
-
|
29
|
+
typecaster.call("").should equal false
|
28
30
|
end
|
29
31
|
|
30
32
|
it "casts a non-empty String to true" do
|
31
|
-
|
33
|
+
typecaster.call("abc").should equal true
|
32
34
|
end
|
33
35
|
|
34
36
|
{
|
@@ -61,84 +63,84 @@ module ActiveAttr
|
|
61
63
|
"OFF" => false,
|
62
64
|
}.each_pair do |value, result|
|
63
65
|
it "casts #{value.inspect} to #{result.inspect}" do
|
64
|
-
|
66
|
+
typecaster.call(value).should equal result
|
65
67
|
end
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
69
71
|
context "when the value is Numeric" do
|
70
72
|
it "casts 0 to false" do
|
71
|
-
|
73
|
+
typecaster.call(0).should equal false
|
72
74
|
end
|
73
75
|
|
74
76
|
it "casts 1 to true" do
|
75
|
-
|
77
|
+
typecaster.call(1).should equal true
|
76
78
|
end
|
77
79
|
|
78
80
|
it "casts 0.0 to false" do
|
79
|
-
|
81
|
+
typecaster.call(0.0).should equal false
|
80
82
|
end
|
81
83
|
|
82
84
|
it "casts 0.1 to true" do
|
83
|
-
|
85
|
+
typecaster.call(0.1).should equal true
|
84
86
|
end
|
85
87
|
|
86
88
|
it "casts a zero BigDecimal to false" do
|
87
|
-
|
89
|
+
typecaster.call(BigDecimal.new("0.0")).should equal false
|
88
90
|
end
|
89
91
|
|
90
92
|
it "casts a non-zero BigDecimal to true" do
|
91
|
-
|
93
|
+
typecaster.call(BigDecimal.new("0.1")).should equal true
|
92
94
|
end
|
93
95
|
|
94
96
|
it "casts -1 to true" do
|
95
|
-
|
97
|
+
typecaster.call(-1).should equal true
|
96
98
|
end
|
97
99
|
|
98
100
|
it "casts -0.0 to false" do
|
99
|
-
|
101
|
+
typecaster.call(-0.0).should equal false
|
100
102
|
end
|
101
103
|
|
102
104
|
it "casts -0.1 to true" do
|
103
|
-
|
105
|
+
typecaster.call(-0.1).should equal true
|
104
106
|
end
|
105
107
|
|
106
108
|
it "casts a negative zero BigDecimal to false" do
|
107
|
-
|
109
|
+
typecaster.call(BigDecimal.new("-0.0")).should equal false
|
108
110
|
end
|
109
111
|
|
110
112
|
it "casts a negative BigDecimal to true" do
|
111
|
-
|
113
|
+
typecaster.call(BigDecimal.new("-0.1")).should equal true
|
112
114
|
end
|
113
115
|
end
|
114
116
|
|
115
117
|
context "when the value is the String version of a Numeric" do
|
116
118
|
it "casts '0' to false" do
|
117
|
-
|
119
|
+
typecaster.call("0").should equal false
|
118
120
|
end
|
119
121
|
|
120
122
|
it "casts '1' to true" do
|
121
|
-
|
123
|
+
typecaster.call("1").should equal true
|
122
124
|
end
|
123
125
|
|
124
126
|
it "casts '0.0' to false" do
|
125
|
-
|
127
|
+
typecaster.call("0.0").should equal false
|
126
128
|
end
|
127
129
|
|
128
130
|
it "casts '0.1' to true" do
|
129
|
-
|
131
|
+
typecaster.call("0.1").should equal true
|
130
132
|
end
|
131
133
|
|
132
134
|
it "casts '-1' to true" do
|
133
|
-
|
135
|
+
typecaster.call("-1").should equal true
|
134
136
|
end
|
135
137
|
|
136
138
|
it "casts '-0.0' to false" do
|
137
|
-
|
139
|
+
typecaster.call("-0.0").should equal false
|
138
140
|
end
|
139
141
|
|
140
142
|
it "casts '-0.1' to true" do
|
141
|
-
|
143
|
+
typecaster.call("-0.1").should equal true
|
142
144
|
end
|
143
145
|
end
|
144
146
|
end
|
@@ -4,61 +4,63 @@ require "active_attr/typecasting/date_time_typecaster"
|
|
4
4
|
module ActiveAttr
|
5
5
|
module Typecasting
|
6
6
|
describe DateTimeTypecaster do
|
7
|
+
subject(:typecaster) { described_class.new }
|
8
|
+
|
7
9
|
describe "#call" do
|
8
10
|
it "returns the original DateTime for a DateTime" do
|
9
11
|
value = DateTime.now
|
10
|
-
|
12
|
+
typecaster.call(value).should equal value
|
11
13
|
end
|
12
14
|
|
13
15
|
it "returns nil for nil" do
|
14
|
-
|
16
|
+
typecaster.call(nil).should equal nil
|
15
17
|
end
|
16
18
|
|
17
19
|
it "casts a Date to a DateTime at the beginning of the day with no offset" do
|
18
|
-
result =
|
20
|
+
result = typecaster.call(Date.new(2012, 1, 1))
|
19
21
|
result.should eql DateTime.new(2012, 1, 1)
|
20
22
|
result.should be_instance_of DateTime
|
21
23
|
end
|
22
24
|
|
23
25
|
it "casts a UTC Time to a DateTime with no offset" do
|
24
|
-
result =
|
26
|
+
result = typecaster.call(Time.utc(2012, 1, 1, 12, 0, 0))
|
25
27
|
result.should eql DateTime.new(2012, 1, 1, 12, 0, 0, 0)
|
26
28
|
result.should be_instance_of DateTime
|
27
29
|
end
|
28
30
|
|
29
31
|
it "casts a local Time to a DateTime with a matching offset" do
|
30
32
|
value = Time.local(2012, 1, 1, 12, 0, 0)
|
31
|
-
result =
|
33
|
+
result = typecaster.call(value)
|
32
34
|
result.should eql DateTime.new(2012, 1, 1, 12, 0, 0, Rational(value.utc_offset, 86400))
|
33
35
|
result.should be_instance_of DateTime
|
34
36
|
end
|
35
37
|
|
36
38
|
it "casts an ISO8601 date String to a Date" do
|
37
|
-
result =
|
39
|
+
result = typecaster.call("2012-01-01")
|
38
40
|
result.should eql DateTime.new(2012, 1, 1)
|
39
41
|
result.should be_instance_of DateTime
|
40
42
|
end
|
41
43
|
|
42
44
|
it "casts an RFC2616 date and GMT time String to a DateTime" do
|
43
|
-
result =
|
45
|
+
result = typecaster.call("Sat, 03 Feb 2001 00:00:00 GMT")
|
44
46
|
result.should eql DateTime.new(2001, 2, 3)
|
45
47
|
result.should be_instance_of DateTime
|
46
48
|
end
|
47
49
|
|
48
50
|
it "casts an RFC3339 date and offset time String to a DateTime" do
|
49
|
-
result =
|
51
|
+
result = typecaster.call("2001-02-03T04:05:06+07:00")
|
50
52
|
result.should eql DateTime.new(2001, 2, 3, 4, 5, 6, "+07:00")
|
51
53
|
result.should be_instance_of DateTime
|
52
54
|
end
|
53
55
|
|
54
56
|
it "casts a UTC ActiveSupport::TimeWithZone to a DateTime" do
|
55
|
-
result =
|
57
|
+
result = typecaster.call(Time.utc(2012, 1, 1, 1, 1, 1).in_time_zone("UTC"))
|
56
58
|
result.should eql DateTime.new(2012, 1, 1, 1, 1, 1, 0)
|
57
59
|
result.should be_instance_of DateTime
|
58
60
|
end
|
59
61
|
|
60
62
|
it "casts an Alaska ActiveSupport::TimeWithZone to a Date representing the date portion" do
|
61
|
-
result =
|
63
|
+
result = typecaster.call(Time.utc(2012, 1, 1, 0, 0, 0).in_time_zone("Alaska"))
|
62
64
|
result.should eql DateTime.new(2011, 12, 31, 15, 0, 0, "-09:00")
|
63
65
|
result.should be_instance_of DateTime
|
64
66
|
end
|
@@ -4,54 +4,56 @@ require "active_attr/typecasting/date_typecaster"
|
|
4
4
|
module ActiveAttr
|
5
5
|
module Typecasting
|
6
6
|
describe DateTypecaster do
|
7
|
+
subject(:typecaster) { described_class.new }
|
8
|
+
|
7
9
|
describe "#call" do
|
8
10
|
it "returns the original date for a Date" do
|
9
11
|
value = Date.today
|
10
|
-
|
12
|
+
typecaster.call(value).should equal value
|
11
13
|
end
|
12
14
|
|
13
15
|
it "returns nil for nil" do
|
14
|
-
|
16
|
+
typecaster.call(nil).should equal nil
|
15
17
|
end
|
16
18
|
|
17
19
|
it "returns nil for an invalid String" do
|
18
|
-
|
20
|
+
typecaster.call("x").should equal nil
|
19
21
|
end
|
20
22
|
|
21
23
|
it "casts a UTC Time to a Date representing the date portion" do
|
22
|
-
|
24
|
+
typecaster.call(Time.utc(2012, 1, 1, 0, 0, 0)).should eql Date.new(2012, 1, 1)
|
23
25
|
end
|
24
26
|
|
25
27
|
it "casts a local Time to a Date representing the date portion" do
|
26
|
-
|
28
|
+
typecaster.call(Time.local(2012, 1, 1, 0, 0, 0)).should eql Date.new(2012, 1, 1)
|
27
29
|
end
|
28
30
|
|
29
31
|
it "casts a UTC DateTime to a Date representing the date portion" do
|
30
|
-
|
32
|
+
typecaster.call(DateTime.new(2012, 1, 1, 0, 0, 0)).should eql Date.new(2012, 1, 1)
|
31
33
|
end
|
32
34
|
|
33
35
|
it "casts an offset DateTime to a Date representing the date portion" do
|
34
|
-
|
36
|
+
typecaster.call(DateTime.new(2012, 1, 1, 0, 0, 0, "-12:00")).should eql Date.new(2012, 1, 1)
|
35
37
|
end
|
36
38
|
|
37
39
|
it "casts an ISO8601 date String to a Date" do
|
38
|
-
|
40
|
+
typecaster.call("2012-01-01").should eql Date.new(2012, 1, 1)
|
39
41
|
end
|
40
42
|
|
41
43
|
it "casts an RFC2616 date and GMT time String to a Date representing the date portion" do
|
42
|
-
|
44
|
+
typecaster.call("Sat, 03 Feb 2001 00:00:00 GMT").should eql Date.new(2001, 2, 3)
|
43
45
|
end
|
44
46
|
|
45
47
|
it "casts an RFC3339 date and offset time String to a Date representing the date portion" do
|
46
|
-
|
48
|
+
typecaster.call("2001-02-03T04:05:06+07:00").should eql Date.new(2001, 2, 3)
|
47
49
|
end
|
48
50
|
|
49
51
|
it "casts a UTC ActiveSupport::TimeWithZone to a Date representing the date portion" do
|
50
|
-
|
52
|
+
typecaster.call(Time.utc(2012, 1, 1, 0, 0, 0).in_time_zone("UTC")).should eql Date.new(2012, 1, 1)
|
51
53
|
end
|
52
54
|
|
53
55
|
it "casts an Alaska ActiveSupport::TimeWithZone to a Date representing the date portion" do
|
54
|
-
|
56
|
+
typecaster.call(Time.utc(2012, 1, 1, 0, 0, 0).in_time_zone("Alaska")).should eql Date.new(2011, 12, 31)
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
@@ -4,22 +4,24 @@ require "active_attr/typecasting/float_typecaster"
|
|
4
4
|
module ActiveAttr
|
5
5
|
module Typecasting
|
6
6
|
describe FloatTypecaster do
|
7
|
+
subject(:typecaster) { described_class.new }
|
8
|
+
|
7
9
|
describe "#call" do
|
8
10
|
it "returns the original float for a Float" do
|
9
11
|
value = 2.0
|
10
|
-
|
12
|
+
typecaster.call(value).should equal value
|
11
13
|
end
|
12
14
|
|
13
15
|
it "casts nil to 0.0" do
|
14
|
-
|
16
|
+
typecaster.call(nil).should eql 0.0
|
15
17
|
end
|
16
18
|
|
17
19
|
it "returns the float version of a String" do
|
18
|
-
|
20
|
+
typecaster.call("2").should eql 2.0
|
19
21
|
end
|
20
22
|
|
21
23
|
it "returns nil for an object that does not respond to #to_f" do
|
22
|
-
|
24
|
+
typecaster.call(Object.new).should be_nil
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
@@ -4,30 +4,32 @@ require "active_attr/typecasting/integer_typecaster"
|
|
4
4
|
module ActiveAttr
|
5
5
|
module Typecasting
|
6
6
|
describe IntegerTypecaster do
|
7
|
+
subject(:typecaster) { described_class.new }
|
8
|
+
|
7
9
|
describe "#call" do
|
8
10
|
it "returns the original integer for a FixNum" do
|
9
11
|
value = 2
|
10
|
-
|
12
|
+
typecaster.call(value).should equal value
|
11
13
|
end
|
12
14
|
|
13
15
|
it "casts nil to 0" do
|
14
|
-
|
16
|
+
typecaster.call(nil).should eql 0
|
15
17
|
end
|
16
18
|
|
17
19
|
it "returns the integer version of a String" do
|
18
|
-
|
20
|
+
typecaster.call("2").should eql 2
|
19
21
|
end
|
20
22
|
|
21
23
|
it "returns nil for an object that does not respond to #to_i" do
|
22
|
-
|
24
|
+
typecaster.call(Object.new).should be_nil
|
23
25
|
end
|
24
26
|
|
25
27
|
it "returns nil for Float::INFINITY" do
|
26
|
-
|
28
|
+
typecaster.call(1.0 / 0.0).should be_nil
|
27
29
|
end
|
28
30
|
|
29
31
|
it "returns nil for Float::NAN" do
|
30
|
-
|
32
|
+
typecaster.call(0.0 / 0.0).should be_nil
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|