active_attr 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (45) hide show
  1. data/.travis.yml +11 -1
  2. data/CHANGELOG.md +9 -0
  3. data/Gemfile +4 -6
  4. data/README.md +29 -11
  5. data/active_attr.gemspec +3 -3
  6. data/gemfiles/rails_3_2.gemfile +11 -0
  7. data/gemfiles/rails_head.gemfile +3 -0
  8. data/lib/active_attr.rb +0 -1
  9. data/lib/active_attr/mass_assignment.rb +30 -2
  10. data/lib/active_attr/matchers/have_attribute_matcher.rb +17 -4
  11. data/lib/active_attr/model.rb +2 -2
  12. data/lib/active_attr/typecasting/big_decimal_typecaster.rb +2 -0
  13. data/lib/active_attr/typecasting/date_typecaster.rb +1 -1
  14. data/lib/active_attr/version.rb +1 -1
  15. data/spec/functional/active_attr/attribute_defaults_spec.rb +12 -12
  16. data/spec/functional/active_attr/attributes_spec.rb +12 -12
  17. data/spec/functional/active_attr/chainable_initialization_spec.rb +3 -3
  18. data/spec/functional/active_attr/mass_assignment_spec.rb +125 -0
  19. data/spec/functional/active_attr/matchers/have_attribute_matcher_spec.rb +147 -66
  20. data/spec/functional/active_attr/model_spec.rb +27 -19
  21. data/spec/functional/active_attr/serialization_spec.rb +5 -5
  22. data/spec/functional/active_attr/typecasted_attributes_spec.rb +45 -45
  23. data/spec/support/mass_assignment_shared_examples.rb +12 -12
  24. data/spec/unit/active_attr/attribute_defaults_spec.rb +6 -6
  25. data/spec/unit/active_attr/attribute_definition_spec.rb +6 -6
  26. data/spec/unit/active_attr/attributes_spec.rb +38 -38
  27. data/spec/unit/active_attr/logger_spec.rb +16 -16
  28. data/spec/unit/active_attr/mass_assignment_spec.rb +1 -1
  29. data/spec/unit/active_attr/matchers_spec.rb +3 -4
  30. data/spec/unit/active_attr/query_attributes_spec.rb +75 -75
  31. data/spec/unit/active_attr/typecasted_attributes_spec.rb +10 -10
  32. data/spec/unit/active_attr/typecasting/big_decimal_typecaster_spec.rb +9 -7
  33. data/spec/unit/active_attr/typecasting/boolean_typecaster_spec.rb +27 -25
  34. data/spec/unit/active_attr/typecasting/date_time_typecaster_spec.rb +12 -10
  35. data/spec/unit/active_attr/typecasting/date_typecaster_spec.rb +14 -12
  36. data/spec/unit/active_attr/typecasting/float_typecaster_spec.rb +6 -4
  37. data/spec/unit/active_attr/typecasting/integer_typecaster_spec.rb +8 -6
  38. data/spec/unit/active_attr/typecasting/object_typecaster_spec.rb +3 -1
  39. data/spec/unit/active_attr/typecasting/string_typecaster_spec.rb +5 -3
  40. data/spec/unit/active_attr/typecasting_spec.rb +3 -5
  41. data/spec/unit/active_attr/version_spec.rb +5 -5
  42. metadata +20 -17
  43. data/lib/active_attr/mass_assignment_security.rb +0 -54
  44. data/spec/functional/active_attr/mass_assignment_security_spec.rb +0 -45
  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
- subject.should_receive(:attribute_before_type_cast).with("first_name")
39
- subject.first_name_before_type_cast
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
- subject.should_receive(:attribute_before_type_cast).with("last_name")
44
- subject.last_name_before_type_cast
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
- subject.attribute_before_type_cast(:amount).should be_nil
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
- subject.amount = value
70
- subject.attribute_before_type_cast(:amount).should equal value
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
- subject.amount = value
76
- subject.attribute_before_type_cast('amount').should equal value
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
- subject.call(value).should equal value
12
+ typecaster.call(value).should equal value
11
13
  end
12
14
 
13
15
  it "casts nil to a zero BigDecimal" do
14
- subject.call(nil).should eql BigDecimal.new("0.0")
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
- subject.call("2").should eql BigDecimal.new("2.0")
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
- subject.call("bob").should eql BigDecimal.new("0.0")
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
- subject.call(Rational(1, 2)).should eql BigDecimal.new("0.5")
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
- subject.call(1.2).should eql BigDecimal.new("1.2")
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
- subject.call(2).should eql BigDecimal.new("2.0")
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
- subject.call(true).should equal true
12
+ typecaster.call(true).should equal true
11
13
  end
12
14
 
13
15
  it "returns false for false" do
14
- subject.call(false).should equal false
16
+ typecaster.call(false).should equal false
15
17
  end
16
18
 
17
19
  it "casts nil to false" do
18
- subject.call(nil).should equal false
20
+ typecaster.call(nil).should equal false
19
21
  end
20
22
 
21
23
  it "casts an Object to true" do
22
- subject.call(Object.new).should equal true
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
- subject.call("").should equal false
29
+ typecaster.call("").should equal false
28
30
  end
29
31
 
30
32
  it "casts a non-empty String to true" do
31
- subject.call("abc").should equal true
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
- subject.call(value).should equal result
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
- subject.call(0).should equal false
73
+ typecaster.call(0).should equal false
72
74
  end
73
75
 
74
76
  it "casts 1 to true" do
75
- subject.call(1).should equal true
77
+ typecaster.call(1).should equal true
76
78
  end
77
79
 
78
80
  it "casts 0.0 to false" do
79
- subject.call(0.0).should equal false
81
+ typecaster.call(0.0).should equal false
80
82
  end
81
83
 
82
84
  it "casts 0.1 to true" do
83
- subject.call(0.1).should equal true
85
+ typecaster.call(0.1).should equal true
84
86
  end
85
87
 
86
88
  it "casts a zero BigDecimal to false" do
87
- subject.call(BigDecimal.new("0.0")).should equal false
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
- subject.call(BigDecimal.new("0.1")).should equal true
93
+ typecaster.call(BigDecimal.new("0.1")).should equal true
92
94
  end
93
95
 
94
96
  it "casts -1 to true" do
95
- subject.call(-1).should equal true
97
+ typecaster.call(-1).should equal true
96
98
  end
97
99
 
98
100
  it "casts -0.0 to false" do
99
- subject.call(-0.0).should equal false
101
+ typecaster.call(-0.0).should equal false
100
102
  end
101
103
 
102
104
  it "casts -0.1 to true" do
103
- subject.call(-0.1).should equal true
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
- subject.call(BigDecimal.new("-0.0")).should equal false
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
- subject.call(BigDecimal.new("-0.1")).should equal true
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
- subject.call("0").should equal false
119
+ typecaster.call("0").should equal false
118
120
  end
119
121
 
120
122
  it "casts '1' to true" do
121
- subject.call("1").should equal true
123
+ typecaster.call("1").should equal true
122
124
  end
123
125
 
124
126
  it "casts '0.0' to false" do
125
- subject.call("0.0").should equal false
127
+ typecaster.call("0.0").should equal false
126
128
  end
127
129
 
128
130
  it "casts '0.1' to true" do
129
- subject.call("0.1").should equal true
131
+ typecaster.call("0.1").should equal true
130
132
  end
131
133
 
132
134
  it "casts '-1' to true" do
133
- subject.call("-1").should equal true
135
+ typecaster.call("-1").should equal true
134
136
  end
135
137
 
136
138
  it "casts '-0.0' to false" do
137
- subject.call("-0.0").should equal false
139
+ typecaster.call("-0.0").should equal false
138
140
  end
139
141
 
140
142
  it "casts '-0.1' to true" do
141
- subject.call("-0.1").should equal true
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
- subject.call(value).should equal value
12
+ typecaster.call(value).should equal value
11
13
  end
12
14
 
13
15
  it "returns nil for nil" do
14
- subject.call(nil).should equal nil
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 = subject.call(Date.new(2012, 1, 1))
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 = subject.call(Time.utc(2012, 1, 1, 12, 0, 0))
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 = subject.call(value)
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 = subject.call("2012-01-01")
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 = subject.call("Sat, 03 Feb 2001 00:00:00 GMT")
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 = subject.call("2001-02-03T04:05:06+07:00")
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 = subject.call(Time.utc(2012, 1, 1, 1, 1, 1).in_time_zone("UTC"))
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 = subject.call(Time.utc(2012, 1, 1, 0, 0, 0).in_time_zone("Alaska"))
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
- subject.call(value).should equal value
12
+ typecaster.call(value).should equal value
11
13
  end
12
14
 
13
15
  it "returns nil for nil" do
14
- subject.call(nil).should equal nil
16
+ typecaster.call(nil).should equal nil
15
17
  end
16
18
 
17
19
  it "returns nil for an invalid String" do
18
- subject.call("x").should equal nil
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
- subject.call(Time.utc(2012, 1, 1, 0, 0, 0)).should eql Date.new(2012, 1, 1)
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
- subject.call(Time.local(2012, 1, 1, 0, 0, 0)).should eql Date.new(2012, 1, 1)
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
- subject.call(DateTime.new(2012, 1, 1, 0, 0, 0)).should eql Date.new(2012, 1, 1)
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
- subject.call(DateTime.new(2012, 1, 1, 0, 0, 0, "-12:00")).should eql Date.new(2012, 1, 1)
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
- subject.call("2012-01-01").should eql Date.new(2012, 1, 1)
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
- subject.call("Sat, 03 Feb 2001 00:00:00 GMT").should eql Date.new(2001, 2, 3)
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
- subject.call("2001-02-03T04:05:06+07:00").should eql Date.new(2001, 2, 3)
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
- subject.call(Time.utc(2012, 1, 1, 0, 0, 0).in_time_zone("UTC")).should eql Date.new(2012, 1, 1)
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
- subject.call(Time.utc(2012, 1, 1, 0, 0, 0).in_time_zone("Alaska")).should eql Date.new(2011, 12, 31)
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
- subject.call(value).should equal value
12
+ typecaster.call(value).should equal value
11
13
  end
12
14
 
13
15
  it "casts nil to 0.0" do
14
- subject.call(nil).should eql 0.0
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
- subject.call("2").should eql 2.0
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
- subject.call(Object.new).should be_nil
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
- subject.call(value).should equal value
12
+ typecaster.call(value).should equal value
11
13
  end
12
14
 
13
15
  it "casts nil to 0" do
14
- subject.call(nil).should eql 0
16
+ typecaster.call(nil).should eql 0
15
17
  end
16
18
 
17
19
  it "returns the integer version of a String" do
18
- subject.call("2").should eql 2
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
- subject.call(Object.new).should be_nil
24
+ typecaster.call(Object.new).should be_nil
23
25
  end
24
26
 
25
27
  it "returns nil for Float::INFINITY" do
26
- subject.call(1.0 / 0.0).should be_nil
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
- subject.call(0.0 / 0.0).should be_nil
32
+ typecaster.call(0.0 / 0.0).should be_nil
31
33
  end
32
34
  end
33
35
  end