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
@@ -1,5 +1,6 @@
1
1
  require "spec_helper"
2
2
  require "active_attr/model"
3
+ require "active_model/mass_assignment_security"
3
4
  require "active_support/core_ext/hash/conversions"
4
5
  require "active_support/json/decoding"
5
6
 
@@ -8,6 +9,7 @@ module ActiveAttr
8
9
  let :model_class do
9
10
  Class.new do
10
11
  include Model
12
+ include ActiveModel::MassAssignmentSecurity
11
13
 
12
14
  attribute :first_name
13
15
  attribute :last_name
@@ -21,19 +23,22 @@ module ActiveAttr
21
23
  end
22
24
  end
23
25
 
24
- subject { model_class.new }
25
- it_should_behave_like "ActiveModel"
26
+ subject(:model) { model_class.new }
27
+
28
+ it_should_behave_like "ActiveModel" do
29
+ subject { model_class.new }
30
+ end
26
31
 
27
32
  it "reads and writes attributes" do
28
- subject.first_name = "Chris"
29
- subject.first_name.should eq "Chris"
30
- subject.attributes["first_name"].should == "Chris"
33
+ model.first_name = "Chris"
34
+ model.first_name.should eq "Chris"
35
+ model.attributes["first_name"].should == "Chris"
31
36
  end
32
37
 
33
38
  it "can query attributes" do
34
- subject.first_name?.should be_false
35
- subject.first_name = "Chris"
36
- subject.first_name?.should be_true
39
+ model.first_name?.should be_false
40
+ model.first_name = "Chris"
41
+ model.first_name?.should be_true
37
42
  end
38
43
 
39
44
  it "initializes with a block that can use attributes" do
@@ -51,14 +56,14 @@ module ActiveAttr
51
56
  it "has a logger" do
52
57
  logger = double("logger")
53
58
  model_class.logger?.should be_false
54
- subject.logger?.should be_false
59
+ model.logger?.should be_false
55
60
 
56
61
  model_class.logger = logger
57
62
 
58
63
  model_class.logger?.should be_true
59
64
  model_class.logger.should eq logger
60
- subject.logger?.should be_true
61
- subject.logger.should == logger
65
+ model.logger?.should be_true
66
+ model.logger.should == logger
62
67
  end
63
68
 
64
69
  it "supports mass assignment with security" do
@@ -68,17 +73,19 @@ module ActiveAttr
68
73
  end
69
74
 
70
75
  it "does not use strict mass assignment" do
71
- expect { subject.assign_attributes :middle_initial => "J" }.not_to raise_error
76
+ expect { model.assign_attributes :middle_initial => "J" }.not_to raise_error
72
77
  end
73
78
 
74
79
  it "serializes to/from JSON" do
75
- subject.first_name = "Chris"
76
- model_class.new.from_json(subject.to_json).first_name.should == "Chris"
80
+ model.first_name = "Chris"
81
+ model_class.new.from_json(model.to_json).first_name.should == "Chris"
77
82
  end
78
83
 
79
84
  it "serializes to/from XML" do
80
- subject.first_name = "Chris"
81
- model_class.new.from_xml(subject.to_xml).first_name.should == "Chris"
85
+ model.first_name = "Chris"
86
+ model.last_name = "Griego"
87
+ model.age = 21
88
+ model_class.new.from_xml(model.to_xml).first_name.should == "Chris"
82
89
  end
83
90
 
84
91
  it "supports attribute name translation" do
@@ -86,14 +93,15 @@ module ActiveAttr
86
93
  end
87
94
 
88
95
  it "typecasts attributes" do
89
- subject.age = "29"
90
- subject.age.should eql 29
96
+ model.age = "29"
97
+ model.age.should eql 29
91
98
  end
92
99
 
93
100
  context "attribute defaults" do
94
101
  let :model_class do
95
102
  Class.new do
96
103
  include Model
104
+ include ActiveModel::MassAssignmentSecurity
97
105
 
98
106
  attribute :start_date
99
107
  attribute :end_date, :default => lambda { start_date }
@@ -102,7 +110,7 @@ module ActiveAttr
102
110
  end
103
111
 
104
112
  it "are applied" do
105
- subject.age_limit.should == 21
113
+ model.age_limit.should == 21
106
114
  end
107
115
 
108
116
  it "are overridden by mass assigned attributes" do
@@ -16,16 +16,16 @@ module ActiveAttr
16
16
  end
17
17
  end
18
18
 
19
- subject { model_class.new }
19
+ subject(:model) { model_class.new }
20
20
 
21
21
  it "serializes to/from JSON" do
22
- subject.first_name = "Chris"
23
- model_class.new.from_json(subject.to_json).first_name.should == "Chris"
22
+ model.first_name = "Chris"
23
+ model_class.new.from_json(model.to_json).first_name.should == "Chris"
24
24
  end
25
25
 
26
26
  it "serializes to/from XML" do
27
- subject.first_name = "Chris"
28
- model_class.new.from_xml(subject.to_xml).first_name.should == "Chris"
27
+ model.first_name = "Chris"
28
+ model_class.new.from_xml(model.to_xml).first_name.should == "Chris"
29
29
  end
30
30
  end
31
31
  end
@@ -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
@@ -30,118 +30,118 @@ module ActiveAttr
30
30
 
31
31
  context "when assigning nil" do
32
32
  it "a typeless attribute returns nil" do
33
- subject.typeless = nil
34
- subject.typeless.should be_nil
33
+ model.typeless = nil
34
+ model.typeless.should be_nil
35
35
  end
36
36
 
37
37
  it "an attribute with no known typecaster raises" do
38
- subject.unknown = nil
39
- expect { subject.unknown }.to raise_error Typecasting::UnknownTypecasterError, "Unable to cast to type Unknown"
38
+ model.unknown = nil
39
+ expect { model.unknown }.to raise_error Typecasting::UnknownTypecasterError, "Unable to cast to type Unknown"
40
40
  end
41
41
 
42
42
  it "an attribute with an inline typecaster returns nil" do
43
- subject.age = nil
44
- subject.age.should be_nil
43
+ model.age = nil
44
+ model.age.should be_nil
45
45
  end
46
46
 
47
47
  it "an Object attribute returns nil" do
48
- subject.object = nil
49
- subject.object.should be_nil
48
+ model.object = nil
49
+ model.object.should be_nil
50
50
  end
51
51
 
52
52
  it "a BigDecimal attribute returns nil" do
53
- subject.big_decimal = nil
54
- subject.big_decimal.should be_nil
53
+ model.big_decimal = nil
54
+ model.big_decimal.should be_nil
55
55
  end
56
56
 
57
57
  it "a Boolean attribute returns nil" do
58
- subject.boolean = nil
59
- subject.boolean.should be_nil
58
+ model.boolean = nil
59
+ model.boolean.should be_nil
60
60
  end
61
61
 
62
62
  it "a Date attribute returns nil" do
63
- subject.date = nil
64
- subject.date.should be_nil
63
+ model.date = nil
64
+ model.date.should be_nil
65
65
  end
66
66
 
67
67
  it "a DateTime attribute returns nil" do
68
- subject.date_time = nil
69
- subject.date_time.should be_nil
68
+ model.date_time = nil
69
+ model.date_time.should be_nil
70
70
  end
71
71
 
72
72
  it "a Float attribute returns nil" do
73
- subject.float = nil
74
- subject.float.should be_nil
73
+ model.float = nil
74
+ model.float.should be_nil
75
75
  end
76
76
 
77
77
  it "an Integer attribute returns nil" do
78
- subject.integer = nil
79
- subject.integer.should be_nil
78
+ model.integer = nil
79
+ model.integer.should be_nil
80
80
  end
81
81
 
82
82
  it "a String attribute returns nil" do
83
- subject.string = nil
84
- subject.string.should be_nil
83
+ model.string = nil
84
+ model.string.should be_nil
85
85
  end
86
86
  end
87
87
 
88
88
  context "when assigning a valid String" do
89
89
  it "a typeless attribute returns the original String" do
90
90
  value = "test"
91
- subject.typeless = value
92
- subject.typeless.should equal value
91
+ model.typeless = value
92
+ model.typeless.should equal value
93
93
  end
94
94
 
95
95
  it "an Object attribute returns the original String" do
96
96
  value = "test"
97
- subject.object = value
98
- subject.object.should equal value
97
+ model.object = value
98
+ model.object.should equal value
99
99
  end
100
100
 
101
101
  it "a BigDecimal attribute returns a BigDecimal" do
102
- subject.big_decimal = "1.1"
103
- subject.big_decimal.should eql BigDecimal.new("1.1")
102
+ model.big_decimal = "1.1"
103
+ model.big_decimal.should eql BigDecimal.new("1.1")
104
104
  end
105
105
 
106
106
  it "a Boolean attribute returns a Boolean" do
107
- subject.boolean = "false"
108
- subject.boolean.should eql false
107
+ model.boolean = "false"
108
+ model.boolean.should eql false
109
109
  end
110
110
 
111
111
  it "a Date attribute returns a Date" do
112
- subject.date = "2012-01-01"
113
- subject.date.should eql Date.new(2012, 1, 1)
112
+ model.date = "2012-01-01"
113
+ model.date.should eql Date.new(2012, 1, 1)
114
114
  end
115
115
 
116
116
  it "a Date attribute before typecasting returns the original String" do
117
117
  value = "2012-01-01"
118
- subject.date = value
119
- subject.date_before_type_cast.should equal value
118
+ model.date = value
119
+ model.date_before_type_cast.should equal value
120
120
  end
121
121
 
122
122
  it "a DateTime attribute returns a DateTime" do
123
- subject.date_time = "2012-01-01"
124
- subject.date_time.should eql DateTime.new(2012, 1, 1)
123
+ model.date_time = "2012-01-01"
124
+ model.date_time.should eql DateTime.new(2012, 1, 1)
125
125
  end
126
126
 
127
127
  it "a Float attribute returns a Float" do
128
- subject.float = "1.1"
129
- subject.float.should eql 1.1
128
+ model.float = "1.1"
129
+ model.float.should eql 1.1
130
130
  end
131
131
 
132
132
  it "an Integer attribute returns an Integer" do
133
- subject.integer = "1"
134
- subject.integer.should eql 1
133
+ model.integer = "1"
134
+ model.integer.should eql 1
135
135
  end
136
136
 
137
137
  it "a String attribute returns the String" do
138
- subject.string = "1.0"
139
- subject.string.should eql "1.0"
138
+ model.string = "1.0"
139
+ model.string.should eql "1.0"
140
140
  end
141
141
 
142
142
  it "an attribute using an inline typecaster returns the result of the inline typecaster" do
143
- subject.age = 2
144
- subject.age.should == Age.new(2)
143
+ model.age = 2
144
+ model.age.should == Age.new(2)
145
145
  end
146
146
  end
147
147
  end
@@ -12,7 +12,7 @@ shared_examples "mass assignment class", :mass_assignment => true do
12
12
  end
13
13
  end
14
14
 
15
- let(:person) { subject.new }
15
+ let(:person) { model_class.new }
16
16
  let(:first_name) { "Chris" }
17
17
  let(:last_name) { "Griego" }
18
18
 
@@ -52,19 +52,19 @@ shared_examples "#assign_attribures", :assign_attributes => true do
52
52
  end
53
53
 
54
54
  it "raises ArgumentError when called with three arguments" do
55
- expect { subject.new.assign_attributes({}, {}, nil) }.to raise_error ArgumentError
55
+ expect { model_class.new.assign_attributes({}, {}, nil) }.to raise_error ArgumentError
56
56
  end
57
57
 
58
58
  it "does not raise when called with two arguments" do
59
- expect { subject.new.assign_attributes({}, {}) }.not_to raise_error
59
+ expect { model_class.new.assign_attributes({}, {}) }.not_to raise_error
60
60
  end
61
61
 
62
62
  it "does not raise when called with a single argument" do
63
- expect { subject.new.assign_attributes({}) }.not_to raise_error
63
+ expect { model_class.new.assign_attributes({}) }.not_to raise_error
64
64
  end
65
65
 
66
66
  it "raises ArgumentError when called with no arguments" do
67
- expect { subject.new.assign_attributes }.to raise_error ArgumentError
67
+ expect { model_class.new.assign_attributes }.to raise_error ArgumentError
68
68
  end
69
69
  end
70
70
 
@@ -81,30 +81,30 @@ end
81
81
 
82
82
  shared_examples "#initialize", :initialize => true do
83
83
  def mass_assign_attributes(attributes)
84
- subject.new(attributes)
84
+ model_class.new(attributes)
85
85
  end
86
86
 
87
87
  def mass_assign_attributes_with_options(attributes, options)
88
- subject.new(attributes, options)
88
+ model_class.new(attributes, options)
89
89
  end
90
90
 
91
91
  it "invokes the superclass initializer" do
92
- subject.new.should be_initialized
92
+ model_class.new.should be_initialized
93
93
  end
94
94
 
95
95
  it "raises ArgumentError when called with three arguments" do
96
- expect { subject.new({}, {}, nil) }.to raise_error ArgumentError
96
+ expect { model_class.new({}, {}, nil) }.to raise_error ArgumentError
97
97
  end
98
98
 
99
99
  it "does not raise when called with two arguments" do
100
- expect { subject.new({}, {}) }.not_to raise_error
100
+ expect { model_class.new({}, {}) }.not_to raise_error
101
101
  end
102
102
 
103
103
  it "does not raise when called with a single argument" do
104
- expect { subject.new({}) }.not_to raise_error
104
+ expect { model_class.new({}) }.not_to raise_error
105
105
  end
106
106
 
107
107
  it "does not raise when called with no arguments" do
108
- expect { subject.new }.not_to raise_error
108
+ expect { model_class.new }.not_to raise_error
109
109
  end
110
110
  end
@@ -3,7 +3,7 @@ require "active_attr/attribute_defaults"
3
3
 
4
4
  module ActiveAttr
5
5
  describe AttributeDefaults 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
@@ -16,21 +16,21 @@ module ActiveAttr
16
16
  end
17
17
 
18
18
  describe "#attribute_defaults" do
19
- subject { model_class.new.attribute_defaults }
19
+ subject(:attribute_defaults) { model_class.new.attribute_defaults }
20
20
 
21
21
  it { should be_a_kind_of Hash }
22
22
 
23
23
  it "includes declared literal string attribute defaults" do
24
- subject["first_name"].should == "John"
24
+ attribute_defaults["first_name"].should == "John"
25
25
  end
26
26
 
27
27
  it "includes declared nil attribute defaults" do
28
- subject.should include "age"
29
- subject["age"].should be_nil
28
+ attribute_defaults.should include "age"
29
+ attribute_defaults["age"].should be_nil
30
30
  end
31
31
 
32
32
  it "includes declared dynamic attribute defaults" do
33
- subject["created_at"].should be_a_kind_of Time
33
+ attribute_defaults["created_at"].should be_a_kind_of Time
34
34
  end
35
35
  end
36
36
 
@@ -3,15 +3,15 @@ require "active_attr/attribute_definition"
3
3
 
4
4
  module ActiveAttr
5
5
  describe AttributeDefinition do
6
- subject { described_class.new(:amount, :default => "default") }
6
+ subject(:attribute_definition) { described_class.new(:amount, :default => "default") }
7
7
 
8
8
  describe "#<=>" do
9
9
  it "is nil if the right side is not an #{described_class}" do
10
- (subject <=> nil).should be_nil
10
+ (attribute_definition <=> nil).should be_nil
11
11
  end
12
12
 
13
13
  it "prefers neither when both sides use the same attribute name and options" do
14
- (subject <=> subject).should == 0
14
+ (attribute_definition <=> attribute_definition).should == 0
15
15
  end
16
16
 
17
17
  it "prefers the left side when the left side name sorts alphabetically before the right side name" do
@@ -39,7 +39,7 @@ module ActiveAttr
39
39
 
40
40
  describe "#[]" do
41
41
  it "reads an attribute option" do
42
- subject[:default].should == "default"
42
+ attribute_definition[:default].should == "default"
43
43
  end
44
44
  end
45
45
 
@@ -91,13 +91,13 @@ module ActiveAttr
91
91
 
92
92
  describe "#to_s" do
93
93
  it "renders the name as a String" do
94
- subject.to_s.should == "amount"
94
+ attribute_definition.to_s.should == "amount"
95
95
  end
96
96
  end
97
97
 
98
98
  describe "#to_sym" do
99
99
  it "renders the name as a Symbol" do
100
- subject.to_sym.should == :amount
100
+ attribute_definition.to_sym.should == :amount
101
101
  end
102
102
  end
103
103
  end