active_attr 0.13.0 → 0.15.2
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.
- checksums.yaml +5 -5
- data/.github/workflows/test.yaml +180 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +34 -0
- data/Gemfile +6 -8
- data/README.md +145 -117
- data/active_attr.gemspec +14 -7
- data/gemfiles/rails_3_0.gemfile +0 -4
- data/gemfiles/rails_3_1.gemfile +1 -8
- data/gemfiles/rails_3_2.gemfile +1 -12
- data/gemfiles/rails_4_0.gemfile +1 -1
- data/gemfiles/rails_4_1.gemfile +1 -1
- data/gemfiles/rails_4_2.gemfile +1 -1
- data/gemfiles/rails_5_0.gemfile +2 -1
- data/gemfiles/rails_5_1.gemfile +2 -1
- data/gemfiles/rails_5_2.gemfile +10 -0
- data/gemfiles/rails_6_0.gemfile +10 -0
- data/gemfiles/rails_head.gemfile +3 -2
- data/lib/active_attr.rb +1 -1
- data/lib/active_attr/attributes.rb +63 -9
- data/lib/active_attr/chainable_initialization.rb +2 -6
- data/lib/active_attr/logger.rb +1 -1
- data/lib/active_attr/mass_assignment.rb +2 -2
- data/lib/active_attr/matchers/have_attribute_matcher.rb +1 -1
- data/lib/active_attr/model.rb +1 -0
- data/lib/active_attr/query_attributes.rb +1 -1
- data/lib/active_attr/railtie.rb +5 -0
- data/lib/active_attr/typecasting/big_decimal_typecaster.rb +3 -0
- data/lib/active_attr/typecasting/boolean_typecaster.rb +8 -0
- data/lib/active_attr/typecasting/float_typecaster.rb +3 -1
- data/lib/active_attr/typecasting/integer_typecaster.rb +3 -1
- data/lib/active_attr/version.rb +1 -1
- data/spec/functional/active_attr/attributes_spec.rb +8 -40
- data/spec/functional/active_attr/mass_assignment_spec.rb +2 -2
- data/spec/functional/active_attr/matchers/have_attribute_matcher_spec.rb +48 -0
- data/spec/functional/active_attr/model_spec.rb +47 -0
- data/spec/unit/active_attr/attribute_defaults_spec.rb +8 -0
- data/spec/unit/active_attr/attributes_spec.rb +91 -0
- data/spec/unit/active_attr/typecasting/big_decimal_typecaster_spec.rb +11 -3
- data/spec/unit/active_attr/typecasting/boolean_typecaster_spec.rb +3 -3
- data/spec/unit/active_attr/typecasting/float_typecaster_spec.rb +10 -2
- data/spec/unit/active_attr/typecasting/integer_typecaster_spec.rb +10 -2
- metadata +48 -33
- data/.ruby-version +0 -1
- data/.travis.yml +0 -94
data/active_attr.gemspec
CHANGED
@@ -4,11 +4,15 @@ require File.expand_path("../lib/active_attr/version", __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Chris Griego", "Ben Poweski"]
|
6
6
|
gem.email = ["cgriego@gmail.com", "bpoweski@gmail.com"]
|
7
|
-
gem.description = %q{Create plain old
|
7
|
+
gem.description = %q{Create plain old Ruby models without reinventing the wheel.}
|
8
8
|
gem.summary = %q{What ActiveModel left out}
|
9
9
|
gem.homepage = "https://github.com/cgriego/active_attr"
|
10
10
|
gem.license = "MIT"
|
11
11
|
|
12
|
+
gem.metadata = {
|
13
|
+
"changelog_uri" => "https://github.com/cgriego/active_attr/blob/master/CHANGELOG.md",
|
14
|
+
}
|
15
|
+
|
12
16
|
gem.files = `git ls-files`.split($\)
|
13
17
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
@@ -16,13 +20,16 @@ Gem::Specification.new do |gem|
|
|
16
20
|
gem.require_paths = ["lib"]
|
17
21
|
gem.version = ActiveAttr::VERSION
|
18
22
|
|
19
|
-
gem.
|
20
|
-
|
23
|
+
gem.required_ruby_version = ">= 2.1.0"
|
24
|
+
|
25
|
+
gem.add_runtime_dependency "actionpack", ">= 3.0.2", "< 7.0"
|
26
|
+
gem.add_runtime_dependency "activemodel", ">= 3.0.2", "< 7.0"
|
27
|
+
gem.add_runtime_dependency "activesupport", ">= 3.0.2", "< 7.0"
|
21
28
|
|
22
|
-
gem.add_development_dependency "bundler"
|
23
|
-
gem.add_development_dependency "
|
29
|
+
gem.add_development_dependency "bundler"
|
30
|
+
gem.add_development_dependency "factory_bot", "< 5.0"
|
24
31
|
gem.add_development_dependency "minitest"
|
25
|
-
gem.add_development_dependency "rake", ">= 0.9.0", "<
|
32
|
+
gem.add_development_dependency "rake", ">= 0.9.0", "< 13.1"
|
26
33
|
gem.add_development_dependency "rspec", "~> 3.0"
|
27
|
-
gem.add_development_dependency "tzinfo"
|
34
|
+
gem.add_development_dependency "tzinfo"
|
28
35
|
end
|
data/gemfiles/rails_3_0.gemfile
CHANGED
data/gemfiles/rails_3_1.gemfile
CHANGED
@@ -2,13 +2,6 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
gemspec :development_group => :test, :path => ".."
|
4
4
|
|
5
|
-
if RUBY_VERSION < "1.9.2"
|
6
|
-
gem "factory_girl", "< 3.0", :group => :test
|
7
|
-
end
|
8
|
-
|
9
|
-
if RUBY_VERSION < "1.9.3"
|
10
|
-
gem "i18n", "< 0.7"
|
11
|
-
end
|
12
|
-
|
13
5
|
gem "activemodel", "~> 3.1.0"
|
14
6
|
gem "activesupport", "~> 3.1.0"
|
7
|
+
gem "tzinfo", "< 2"
|
data/gemfiles/rails_3_2.gemfile
CHANGED
@@ -2,18 +2,7 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
gemspec :development_group => :test, :path => ".."
|
4
4
|
|
5
|
-
if RUBY_VERSION < "1.9.2"
|
6
|
-
gem "factory_girl", "< 3.0", :group => :test
|
7
|
-
end
|
8
|
-
|
9
|
-
if RUBY_VERSION < "1.9.3"
|
10
|
-
gem "i18n", "< 0.7"
|
11
|
-
end
|
12
|
-
|
13
|
-
if RUBY_VERSION < "1.9.3"
|
14
|
-
gem "rack-cache", "< 1.3", :group => :test
|
15
|
-
end
|
16
|
-
|
17
5
|
gem "activemodel", "~> 3.2.0"
|
18
6
|
gem "activesupport", "~> 3.2.0"
|
19
7
|
gem "strong_parameters", ">= 0.2.0", :group => :test
|
8
|
+
gem "tzinfo", "< 2"
|
data/gemfiles/rails_4_0.gemfile
CHANGED
data/gemfiles/rails_4_1.gemfile
CHANGED
data/gemfiles/rails_4_2.gemfile
CHANGED
data/gemfiles/rails_5_0.gemfile
CHANGED
@@ -4,6 +4,7 @@ gemspec :development_group => :test, :path => ".."
|
|
4
4
|
|
5
5
|
gem "activemodel", "~> 5.0.0"
|
6
6
|
gem "activesupport", "~> 5.0.0"
|
7
|
-
gem "actionpack", "~> 5.0.0"
|
7
|
+
gem "actionpack", "~> 5.0.0"
|
8
8
|
gem "activemodel-serializers-xml", :group => :test
|
9
|
+
gem "rexml", :group => :test
|
9
10
|
gem "protected_attributes_continued", :group => :test
|
data/gemfiles/rails_5_1.gemfile
CHANGED
@@ -4,6 +4,7 @@ gemspec :development_group => :test, :path => ".."
|
|
4
4
|
|
5
5
|
gem "activemodel", "~> 5.1.0"
|
6
6
|
gem "activesupport", "~> 5.1.0"
|
7
|
-
gem "actionpack", "~> 5.1.0"
|
7
|
+
gem "actionpack", "~> 5.1.0"
|
8
8
|
gem "activemodel-serializers-xml", :group => :test
|
9
|
+
gem "rexml", :group => :test
|
9
10
|
gem "protected_attributes_continued", :group => :test
|
@@ -0,0 +1,10 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec :development_group => :test, :path => ".."
|
4
|
+
|
5
|
+
gem "activemodel", "~> 5.2.0"
|
6
|
+
gem "activesupport", "~> 5.2.0"
|
7
|
+
gem "actionpack", "~> 5.2.0"
|
8
|
+
gem "activemodel-serializers-xml", :group => :test
|
9
|
+
gem "rexml", :group => :test
|
10
|
+
gem "protected_attributes_continued", :group => :test
|
@@ -0,0 +1,10 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec :development_group => :test, :path => ".."
|
4
|
+
|
5
|
+
gem "activemodel", "~> 6.0.0"
|
6
|
+
gem "activesupport", "~> 6.0.0"
|
7
|
+
gem "actionpack", "~> 6.0.0"
|
8
|
+
gem "activemodel-serializers-xml", :group => :test
|
9
|
+
gem "rexml", :group => :test
|
10
|
+
gem "protected_attributes_continued", :group => :test
|
data/gemfiles/rails_head.gemfile
CHANGED
@@ -2,12 +2,13 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
gemspec :development_group => :test, :path => ".."
|
4
4
|
|
5
|
-
git "git://github.com/rails/rails.git" do
|
5
|
+
git "git://github.com/rails/rails.git", :branch => "main" do
|
6
6
|
gem "activemodel"
|
7
7
|
gem "activesupport"
|
8
|
-
gem "actionpack"
|
8
|
+
gem "actionpack"
|
9
9
|
end
|
10
10
|
|
11
11
|
gem "activemodel-serializers-xml", :group => :test, :git => "git://github.com/rails/activemodel-serializers-xml.git"
|
12
|
+
gem "rexml", :group => :test
|
12
13
|
gem "protected_attributes_continued", :group => :test, :git => "git://github.com/westonganger/protected_attributes_continued"
|
13
14
|
gem "rack", :group => :test, :git => "git://github.com/rack/rack.git"
|
data/lib/active_attr.rb
CHANGED
@@ -4,7 +4,7 @@ require "active_support/dependencies/autoload"
|
|
4
4
|
# ActiveAttr is a set of modules to enhance Plain Old Ruby Objects (POROs)
|
5
5
|
#
|
6
6
|
# These modules give your objects the type of features that are normally found
|
7
|
-
# in popular Object Relation Mappers (ORMs) like ActiveRecord,
|
7
|
+
# in popular Object Relation Mappers (ORMs) like ActiveRecord, Sequel, and
|
8
8
|
# Mongoid. The goal is to lower the bar for creating easy-to-use Ruby models.
|
9
9
|
module ActiveAttr
|
10
10
|
extend ActiveSupport::Autoload
|
@@ -3,8 +3,15 @@ require "active_attr/dangerous_attribute_error"
|
|
3
3
|
require "active_attr/unknown_attribute_error"
|
4
4
|
require "active_model"
|
5
5
|
require "active_support/concern"
|
6
|
+
require "active_support/core_ext/class/attribute"
|
6
7
|
require "active_support/hash_with_indifferent_access"
|
7
8
|
|
9
|
+
begin
|
10
|
+
require "active_support/parameter_filter"
|
11
|
+
rescue LoadError
|
12
|
+
require "action_dispatch/http/parameter_filter"
|
13
|
+
end
|
14
|
+
|
8
15
|
module ActiveAttr
|
9
16
|
# Attributes provides a set of class methods for defining an attributes
|
10
17
|
# schema and instance methods for reading and writing attributes.
|
@@ -23,11 +30,42 @@ module ActiveAttr
|
|
23
30
|
extend ActiveSupport::Concern
|
24
31
|
include ActiveModel::AttributeMethods
|
25
32
|
|
26
|
-
#
|
27
|
-
# @since 0.
|
28
|
-
|
33
|
+
# @private
|
34
|
+
# @since 0.14.0
|
35
|
+
FILTERED = '[FILTERED]'.freeze
|
36
|
+
|
37
|
+
# @private
|
38
|
+
# @since 0.14.0
|
39
|
+
PARAMETER_FILTER = if defined?(ActiveSupport::ParameterFilter)
|
40
|
+
ActiveSupport::ParameterFilter
|
41
|
+
else
|
42
|
+
ActionDispatch::Http::ParameterFilter
|
43
|
+
end
|
44
|
+
|
45
|
+
# Specifies attributes which won't be exposed while calling #inspect
|
46
|
+
#
|
47
|
+
# @return [Array<#to_s, Regexp, Proc>] filter_attributes Configured
|
48
|
+
# global default filtered attributes
|
49
|
+
#
|
50
|
+
# @since 0.14.0
|
51
|
+
def self.filter_attributes
|
52
|
+
@filter_attributes ||= []
|
53
|
+
end
|
54
|
+
|
55
|
+
# Configure the global default filtered attributes
|
56
|
+
#
|
57
|
+
# @param [Array<#to_s, Regexp, Proc>] new_filter_attributes The new
|
58
|
+
# global default filtered attributes
|
59
|
+
#
|
60
|
+
# @since 0.14.0
|
61
|
+
def self.filter_attributes=(new_filter_attributes)
|
62
|
+
@filter_attributes = new_filter_attributes
|
63
|
+
end
|
29
64
|
|
30
65
|
included do
|
66
|
+
class_attribute :filter_attributes, :instance_writer => false
|
67
|
+
self.filter_attributes = Attributes.filter_attributes
|
68
|
+
|
31
69
|
attribute_method_suffix "" if attribute_method_matchers.none? { |matcher| matcher.prefix == "" && matcher.suffix == "" }
|
32
70
|
attribute_method_suffix "="
|
33
71
|
end
|
@@ -70,7 +108,20 @@ module ActiveAttr
|
|
70
108
|
#
|
71
109
|
# @since 0.2.0
|
72
110
|
def inspect
|
73
|
-
|
111
|
+
inspection_filter = PARAMETER_FILTER.new(filter_attributes)
|
112
|
+
original_attributes = attributes
|
113
|
+
filtered_attributes = inspection_filter.filter(original_attributes)
|
114
|
+
|
115
|
+
attribute_descriptions = filtered_attributes.sort.map { |key, value|
|
116
|
+
inspect_value = case
|
117
|
+
when original_attributes[key].nil? then nil.inspect
|
118
|
+
when value == FILTERED then FILTERED
|
119
|
+
else value.inspect
|
120
|
+
end
|
121
|
+
|
122
|
+
"#{key}: #{inspect_value}"
|
123
|
+
}.join(", ")
|
124
|
+
|
74
125
|
separator = " " unless attribute_descriptions.empty?
|
75
126
|
"#<#{self.class.name}#{separator}#{attribute_descriptions}>"
|
76
127
|
end
|
@@ -150,7 +201,9 @@ module ActiveAttr
|
|
150
201
|
#
|
151
202
|
# @since 0.7.0
|
152
203
|
def attributes_map
|
153
|
-
|
204
|
+
self.class.attribute_names.each_with_object({}) do |name, hash|
|
205
|
+
hash[name] = yield(name)
|
206
|
+
end
|
154
207
|
end
|
155
208
|
|
156
209
|
module ClassMethods
|
@@ -202,6 +255,7 @@ module ActiveAttr
|
|
202
255
|
# Force active model to generate attribute methods
|
203
256
|
remove_instance_variable("@attribute_methods_generated") if instance_variable_defined?("@attribute_methods_generated")
|
204
257
|
define_attribute_methods([attribute_definition.name]) unless attribute_names.include? attribute_name
|
258
|
+
remove_instance_variable("@attribute_names") if instance_variable_defined?("@attribute_names")
|
205
259
|
attributes[attribute_name] = attribute_definition
|
206
260
|
end
|
207
261
|
end
|
@@ -215,7 +269,7 @@ module ActiveAttr
|
|
215
269
|
#
|
216
270
|
# @since 0.5.0
|
217
271
|
def attribute_names
|
218
|
-
attributes.keys
|
272
|
+
@attribute_names ||= attributes.keys
|
219
273
|
end
|
220
274
|
|
221
275
|
# Returns a Hash of AttributeDefinition instances
|
@@ -251,7 +305,7 @@ module ActiveAttr
|
|
251
305
|
# @since 0.6.0
|
252
306
|
def dangerous_attribute?(name)
|
253
307
|
attribute_methods(name).detect do |method_name|
|
254
|
-
|
308
|
+
allocate.respond_to?(method_name, true)
|
255
309
|
end unless attribute_names.include? name.to_s
|
256
310
|
end
|
257
311
|
|
@@ -273,8 +327,8 @@ module ActiveAttr
|
|
273
327
|
|
274
328
|
# Assign a set of attribute definitions, used when subclassing models
|
275
329
|
#
|
276
|
-
# @param [Array<ActiveAttr::AttributeDefinition>] The
|
277
|
-
# AttributeDefinition instances
|
330
|
+
# @param [Array<ActiveAttr::AttributeDefinition>] attributes The
|
331
|
+
# Array of AttributeDefinition instances
|
278
332
|
#
|
279
333
|
# @since 0.2.2
|
280
334
|
def attributes=(attributes)
|
@@ -18,14 +18,10 @@ module ActiveAttr
|
|
18
18
|
module ChainableInitialization
|
19
19
|
class << self
|
20
20
|
# A collection of Ruby base objects
|
21
|
-
# [Object]
|
22
|
-
# [Object, BasicObject] on Ruby 1.9
|
21
|
+
# [Object, BasicObject]
|
23
22
|
#
|
24
23
|
# @private
|
25
|
-
BASE_OBJECTS = []
|
26
|
-
superclass = Class.new
|
27
|
-
base_objects << superclass while superclass = superclass.superclass
|
28
|
-
end
|
24
|
+
BASE_OBJECTS = [Object, BasicObject]
|
29
25
|
|
30
26
|
# Only append the features of this module to the class that inherits
|
31
27
|
# directly from one of the BASE_OBJECTS
|
data/lib/active_attr/logger.rb
CHANGED
@@ -24,8 +24,8 @@ module ActiveAttr
|
|
24
24
|
# person.first_name #=> "Chris"
|
25
25
|
# person.last_name #=> "Griego"
|
26
26
|
#
|
27
|
-
# @param [Hash{#to_s => Object}, #each]
|
28
|
-
# populate the model
|
27
|
+
# @param [Hash{#to_s => Object}, #each] new_attributes Attributes
|
28
|
+
# used to populate the model
|
29
29
|
# @param [Hash, #[]] options Options that affect mass assignment
|
30
30
|
#
|
31
31
|
# @option options [Symbol] :as (:default) Mass assignment role
|
@@ -76,7 +76,7 @@ module ActiveAttr
|
|
76
76
|
@attribute_options[:default] = default_value
|
77
77
|
@description << " with a default value of #{default_value.inspect}"
|
78
78
|
@expected_ancestors << "ActiveAttr::AttributeDefaults"
|
79
|
-
@attribute_expectations << lambda {
|
79
|
+
@attribute_expectations << lambda { @model_class.allocate.send(:_attribute_default, @attribute_name) == default_value }
|
80
80
|
self
|
81
81
|
end
|
82
82
|
|
data/lib/active_attr/model.rb
CHANGED
data/lib/active_attr/railtie.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "active_attr/attributes"
|
1
2
|
require "active_attr/logger"
|
2
3
|
|
3
4
|
module ActiveAttr
|
@@ -6,5 +7,9 @@ module ActiveAttr
|
|
6
7
|
initializer "active_attr.logger" do
|
7
8
|
Logger.logger ||= ::Rails.logger
|
8
9
|
end
|
10
|
+
|
11
|
+
initializer "active_attr.attributes" do
|
12
|
+
Attributes.filter_attributes += Rails.application.config.filter_parameters
|
13
|
+
end
|
9
14
|
end
|
10
15
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "bigdecimal"
|
2
2
|
require "bigdecimal/util"
|
3
3
|
require "active_support/core_ext/big_decimal/conversions"
|
4
|
+
require "active_support/core_ext/object/blank"
|
4
5
|
|
5
6
|
module ActiveAttr
|
6
7
|
module Typecasting
|
@@ -29,6 +30,8 @@ module ActiveAttr
|
|
29
30
|
value
|
30
31
|
elsif value.is_a? Rational
|
31
32
|
value.to_f.to_d
|
33
|
+
elsif value.blank?
|
34
|
+
nil
|
32
35
|
elsif value.respond_to? :to_d
|
33
36
|
value.to_d
|
34
37
|
else
|
@@ -17,6 +17,13 @@ module ActiveAttr
|
|
17
17
|
# @since 0.5.0
|
18
18
|
FALSE_VALUES = ["n", "N", "no", "No", "NO", "false", "False", "FALSE", "off", "Off", "OFF", "f", "F"]
|
19
19
|
|
20
|
+
# Values which force a nil result for typecasting
|
21
|
+
#
|
22
|
+
# These values are based on the behavior of ActiveRecord
|
23
|
+
#
|
24
|
+
# @since 0.14.0
|
25
|
+
NIL_VALUES = ["", nil]
|
26
|
+
|
20
27
|
# Typecasts an object to true or false
|
21
28
|
#
|
22
29
|
# Similar to ActiveRecord, when the attribute is a zero value or
|
@@ -34,6 +41,7 @@ module ActiveAttr
|
|
34
41
|
def call(value)
|
35
42
|
case value
|
36
43
|
when *FALSE_VALUES then false
|
44
|
+
when *NIL_VALUES then nil
|
37
45
|
when Numeric, /\A[-+]?(0+\.?0*|0*\.?0+)\z/ then !value.to_f.zero?
|
38
46
|
else value.present?
|
39
47
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "active_support/core_ext/object/blank"
|
2
|
+
|
1
3
|
module ActiveAttr
|
2
4
|
module Typecasting
|
3
5
|
# Typecasts an Object to a Float
|
@@ -20,7 +22,7 @@ module ActiveAttr
|
|
20
22
|
#
|
21
23
|
# @since 0.5.0
|
22
24
|
def call(value)
|
23
|
-
value.to_f if value.respond_to?
|
25
|
+
value.to_f if value.present? && value.respond_to?(:to_f)
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|