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.

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