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
@@ -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
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
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
|
-
|
61
|
-
|
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 {
|
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
|
-
|
76
|
-
model_class.new.from_json(
|
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
|
-
|
81
|
-
|
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
|
-
|
90
|
-
|
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
|
-
|
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
|
-
|
23
|
-
model_class.new.from_json(
|
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
|
-
|
28
|
-
model_class.new.from_xml(
|
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
|
-
|
34
|
-
|
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
|
-
|
39
|
-
expect {
|
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
|
-
|
44
|
-
|
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
|
-
|
49
|
-
|
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
|
-
|
54
|
-
|
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
|
-
|
59
|
-
|
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
|
-
|
64
|
-
|
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
|
-
|
69
|
-
|
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
|
-
|
74
|
-
|
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
|
-
|
79
|
-
|
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
|
-
|
84
|
-
|
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
|
-
|
92
|
-
|
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
|
-
|
98
|
-
|
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
|
-
|
103
|
-
|
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
|
-
|
108
|
-
|
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
|
-
|
113
|
-
|
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
|
-
|
119
|
-
|
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
|
-
|
124
|
-
|
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
|
-
|
129
|
-
|
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
|
-
|
134
|
-
|
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
|
-
|
139
|
-
|
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
|
-
|
144
|
-
|
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) {
|
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 {
|
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 {
|
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 {
|
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 {
|
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
|
-
|
84
|
+
model_class.new(attributes)
|
85
85
|
end
|
86
86
|
|
87
87
|
def mass_assign_attributes_with_options(attributes, options)
|
88
|
-
|
88
|
+
model_class.new(attributes, options)
|
89
89
|
end
|
90
90
|
|
91
91
|
it "invokes the superclass initializer" do
|
92
|
-
|
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 {
|
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 {
|
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 {
|
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 {
|
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
|
-
|
24
|
+
attribute_defaults["first_name"].should == "John"
|
25
25
|
end
|
26
26
|
|
27
27
|
it "includes declared nil attribute defaults" do
|
28
|
-
|
29
|
-
|
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
|
-
|
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
|
-
(
|
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
|
-
(
|
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
|
-
|
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
|
-
|
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
|
-
|
100
|
+
attribute_definition.to_sym.should == :amount
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|