active_attr 0.13.1 → 0.14.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 (37) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +0 -17
  4. data/CHANGELOG.md +14 -0
  5. data/Gemfile +4 -5
  6. data/README.md +140 -112
  7. data/active_attr.gemspec +8 -1
  8. data/gemfiles/rails_3_0.gemfile +0 -4
  9. data/gemfiles/rails_3_1.gemfile +0 -4
  10. data/gemfiles/rails_3_2.gemfile +0 -4
  11. data/gemfiles/rails_4_0.gemfile +1 -1
  12. data/gemfiles/rails_4_1.gemfile +1 -1
  13. data/gemfiles/rails_4_2.gemfile +1 -1
  14. data/gemfiles/rails_5_0.gemfile +1 -1
  15. data/gemfiles/rails_5_1.gemfile +1 -1
  16. data/gemfiles/rails_5_2.gemfile +1 -1
  17. data/gemfiles/rails_head.gemfile +1 -1
  18. data/lib/active_attr.rb +1 -1
  19. data/lib/active_attr/attributes.rb +62 -9
  20. data/lib/active_attr/chainable_initialization.rb +2 -6
  21. data/lib/active_attr/logger.rb +1 -1
  22. data/lib/active_attr/mass_assignment.rb +2 -2
  23. data/lib/active_attr/matchers/have_attribute_matcher.rb +1 -1
  24. data/lib/active_attr/model.rb +1 -0
  25. data/lib/active_attr/query_attributes.rb +1 -1
  26. data/lib/active_attr/railtie.rb +5 -0
  27. data/lib/active_attr/typecasting/boolean_typecaster.rb +8 -0
  28. data/lib/active_attr/version.rb +1 -1
  29. data/spec/functional/active_attr/attributes_spec.rb +8 -8
  30. data/spec/functional/active_attr/matchers/have_attribute_matcher_spec.rb +48 -0
  31. data/spec/functional/active_attr/model_spec.rb +47 -0
  32. data/spec/unit/active_attr/attribute_defaults_spec.rb +8 -0
  33. data/spec/unit/active_attr/attributes_spec.rb +91 -0
  34. data/spec/unit/active_attr/typecasting/big_decimal_typecaster_spec.rb +4 -0
  35. data/spec/unit/active_attr/typecasting/boolean_typecaster_spec.rb +3 -3
  36. metadata +27 -13
  37. data/.ruby-version +0 -1
@@ -120,5 +120,52 @@ module ActiveAttr
120
120
  end.end_date.should == Date.today
121
121
  end
122
122
  end
123
+
124
+ context "when define validation callbacks" do
125
+ let :model_class do
126
+ Class.new do
127
+ include Model
128
+
129
+ attribute :name
130
+ attribute :status
131
+
132
+ validates :name, :presence => true, :length => {:maximum => 6}
133
+
134
+ before_validation :remove_whitespaces
135
+ after_validation :set_status
136
+
137
+ def self.name
138
+ "Person"
139
+ end
140
+
141
+ private
142
+
143
+ def remove_whitespaces
144
+ name.strip!
145
+ end
146
+
147
+ def set_status
148
+ self.status = errors.empty?
149
+ end
150
+ end
151
+ end
152
+
153
+ it "can call before_validation" do
154
+ person = model_class.new(:name => " bob ")
155
+
156
+ expect(person.valid?).to be(true)
157
+ expect(person.name).to eq("bob")
158
+ end
159
+
160
+ it "can call after_validation" do
161
+ person = model_class.new(:name => "")
162
+ expect(person.valid?).to be(false)
163
+ expect(person.status).to be(false)
164
+
165
+ person = model_class.new(:name => "alice")
166
+ expect(person.valid?).to be(true)
167
+ expect(person.status).to be(true)
168
+ end
169
+ end
123
170
  end
124
171
  end
@@ -4,14 +4,18 @@ require "active_attr/attribute_defaults"
4
4
  module ActiveAttr
5
5
  describe AttributeDefaults do
6
6
  subject(:model) { model_class.new }
7
+ let(:non_duplicable) { double("non-duplicable", :duplicable? => false) }
7
8
 
8
9
  let :model_class do
10
+ non_duplicable_default = non_duplicable
11
+
9
12
  Class.new do
10
13
  include InitializationVerifier
11
14
  include AttributeDefaults
12
15
  attribute :first_name, :default => "John"
13
16
  attribute :age, :default => nil
14
17
  attribute :created_at, :default => lambda { Time.now }
18
+ attribute :non_duplicable, :default => non_duplicable_default
15
19
  end
16
20
  end
17
21
 
@@ -32,6 +36,10 @@ module ActiveAttr
32
36
  it "includes declared dynamic attribute defaults" do
33
37
  attribute_defaults["created_at"].should be_a_kind_of Time
34
38
  end
39
+
40
+ it "includes non-duplicable attribute defaults" do
41
+ attribute_defaults["non_duplicable"].should == non_duplicable
42
+ end
35
43
  end
36
44
 
37
45
  describe "#initialize" do
@@ -9,6 +9,7 @@ module ActiveAttr
9
9
  let :model_class do
10
10
  Class.new do
11
11
  include Attributes
12
+
12
13
  attribute :first_name
13
14
  attribute :last_name
14
15
  attribute :amount
@@ -133,6 +134,11 @@ module ActiveAttr
133
134
  model.should_receive(:attribute=).with("first_name", "Ben")
134
135
  model.first_name = "Ben"
135
136
  end
137
+
138
+ it "returns the new attribute definition" do
139
+ result = attributeless.attribute! :first_name
140
+ result.should == AttributeDefinition.new(:first_name)
141
+ end
136
142
  end
137
143
 
138
144
  describe ".attributes" do
@@ -151,6 +157,38 @@ module ActiveAttr
151
157
  end
152
158
  end
153
159
 
160
+ describe "#{described_class}.filter_attributes" do
161
+ after { described_class.send(:remove_instance_variable, "@filter_attributes") }
162
+
163
+ it "defaults to an empty array" do
164
+ described_class.filter_attributes.should == []
165
+ end
166
+
167
+ it "can be mutated" do
168
+ described_class.filter_attributes << :password
169
+ described_class.filter_attributes.should == [:password]
170
+ end
171
+
172
+ it "can be assigned" do
173
+ described_class.filter_attributes += [:password]
174
+ described_class.filter_attributes.should == [:password]
175
+ end
176
+
177
+ it "initiailizes new classes using the module config" do
178
+ described_class.filter_attributes += [:password]
179
+ model_class.filter_attributes.should == [:password]
180
+ end
181
+
182
+ it "subclasses should inherit from the parent class" do
183
+ model_class.filter_attributes = [:password]
184
+ Class.new(model_class).filter_attributes.should == [:password]
185
+ end
186
+
187
+ it "cannot be overridden on instances" do
188
+ model_class.new.should_not respond_to(:filter_attributes=)
189
+ end
190
+ end
191
+
154
192
  describe ".inspect" do
155
193
  it "renders the class name" do
156
194
  model_class.inspect.should match(/^Foo\(.*\)$/)
@@ -214,6 +252,59 @@ module ActiveAttr
214
252
  model.inspect.should == %{#<Foo amount: nil, first_name: "Ben", last_name: "#{last_name}">}
215
253
  end
216
254
 
255
+ context "filtering attributes with a Symbol" do
256
+ before { model_class.filter_attributes = [:amount] }
257
+
258
+ it "does not filter an attribute with a nil value" do
259
+ model.inspect.should == %{#<Foo amount: nil, first_name: "Ben", last_name: "#{last_name}">}
260
+ end
261
+
262
+ it "filters filtered attributes that have a value" do
263
+ model.amount = 100
264
+ model.inspect.should == %{#<Foo amount: [FILTERED], first_name: "Ben", last_name: "#{last_name}">}
265
+ end
266
+ end
267
+
268
+ context "filtering attributes with a String" do
269
+ before { model_class.filter_attributes = ["amount"] }
270
+
271
+ it "does not filter an attribute with a nil value" do
272
+ model.inspect.should == %{#<Foo amount: nil, first_name: "Ben", last_name: "#{last_name}">}
273
+ end
274
+
275
+ it "filters filtered attributes that have a value" do
276
+ model.amount = 100
277
+ model.inspect.should == %{#<Foo amount: [FILTERED], first_name: "Ben", last_name: "#{last_name}">}
278
+ end
279
+ end
280
+
281
+ context "filtering attributes with a partial attribute name" do
282
+ before { model_class.filter_attributes = [:name] }
283
+
284
+ it "filters filtered attributes that have a value and whose attribute contains the filtered attribute name" do
285
+ model.inspect.should == %{#<Foo amount: nil, first_name: [FILTERED], last_name: [FILTERED]>}
286
+ end
287
+ end
288
+
289
+ context "filtering attributes with a Regexp" do
290
+ before { model_class.filter_attributes = [/name/i] }
291
+
292
+ it "filters filtered attributes that have a value and whose attribute matches the Regexp" do
293
+ model.inspect.should == %{#<Foo amount: nil, first_name: [FILTERED], last_name: [FILTERED]>}
294
+ end
295
+ end
296
+
297
+ context "filtering attributes with a Proc with 2 arguments" do
298
+ before do
299
+ model.amount = 100
300
+ model_class.filter_attributes = [->(key, value) { value.reverse! if key =~ /name/ }]
301
+ end
302
+
303
+ it "filters filtered attributes that have a value by mutating the attributes" do
304
+ model.inspect.should == %{#<Foo amount: 100, first_name: "neB", last_name: "iksewoP">}
305
+ end
306
+ end
307
+
217
308
  it "doesn't format the inspection string for attributes if the model does not have any" do
218
309
  attributeless.new.inspect.should == %{#<Foo>}
219
310
  end
@@ -24,6 +24,10 @@ module ActiveAttr
24
24
  typecaster.call("bob").should eql BigDecimal("0.0")
25
25
  end
26
26
 
27
+ it "casts an alpha string coercable object to a zero BigDecimal" do
28
+ typecaster.call(double(to_s: "bob")).should eql BigDecimal("0.0")
29
+ end
30
+
27
31
  it "casts a Rational to a BigDecimal" do
28
32
  typecaster.call(Rational(1, 2)).should eql BigDecimal("0.5")
29
33
  end
@@ -16,8 +16,8 @@ module ActiveAttr
16
16
  typecaster.call(false).should equal false
17
17
  end
18
18
 
19
- it "casts nil to false" do
20
- typecaster.call(nil).should equal false
19
+ it "casts nil to nil" do
20
+ typecaster.call(nil).should equal nil
21
21
  end
22
22
 
23
23
  it "casts an Object to true" do
@@ -26,7 +26,7 @@ module ActiveAttr
26
26
 
27
27
  context "when the value is a String" do
28
28
  it "casts an empty String to false" do
29
- typecaster.call("").should equal false
29
+ typecaster.call("").should equal nil
30
30
  end
31
31
 
32
32
  it "casts a non-empty String to true" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_attr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Griego
@@ -9,8 +9,28 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-04-25 00:00:00.000000000 Z
12
+ date: 2019-06-10 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: actionpack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 3.0.2
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '6.1'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: 3.0.2
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '6.1'
14
34
  - !ruby/object:Gem::Dependency
15
35
  name: activemodel
16
36
  requirement: !ruby/object:Gem::Requirement
@@ -66,12 +86,9 @@ dependencies:
66
86
  - !ruby/object:Gem::Version
67
87
  version: '1.0'
68
88
  - !ruby/object:Gem::Dependency
69
- name: factory_girl
89
+ name: factory_bot
70
90
  requirement: !ruby/object:Gem::Requirement
71
91
  requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '2.2'
75
92
  - - "<"
76
93
  - !ruby/object:Gem::Version
77
94
  version: '5.0'
@@ -79,9 +96,6 @@ dependencies:
79
96
  prerelease: false
80
97
  version_requirements: !ruby/object:Gem::Requirement
81
98
  requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- version: '2.2'
85
99
  - - "<"
86
100
  - !ruby/object:Gem::Version
87
101
  version: '5.0'
@@ -157,7 +171,6 @@ extra_rdoc_files: []
157
171
  files:
158
172
  - ".gitignore"
159
173
  - ".rspec"
160
- - ".ruby-version"
161
174
  - ".travis.yml"
162
175
  - ".yardopts"
163
176
  - CHANGELOG.md
@@ -252,7 +265,8 @@ files:
252
265
  homepage: https://github.com/cgriego/active_attr
253
266
  licenses:
254
267
  - MIT
255
- metadata: {}
268
+ metadata:
269
+ changelog_uri: https://github.com/cgriego/active_attr/blob/master/CHANGELOG.md
256
270
  post_install_message:
257
271
  rdoc_options: []
258
272
  require_paths:
@@ -261,7 +275,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
261
275
  requirements:
262
276
  - - ">="
263
277
  - !ruby/object:Gem::Version
264
- version: '0'
278
+ version: 1.9.2
265
279
  required_rubygems_version: !ruby/object:Gem::Requirement
266
280
  requirements:
267
281
  - - ">="
@@ -269,7 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
269
283
  version: '0'
270
284
  requirements: []
271
285
  rubyforge_project:
272
- rubygems_version: 2.6.12
286
+ rubygems_version: 2.7.9
273
287
  signing_key:
274
288
  specification_version: 4
275
289
  summary: What ActiveModel left out
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.4.1