attributor 7.1 → 8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -3
- data/CHANGELOG.md +6 -2
- data/attributor.gemspec +3 -2
- data/lib/attributor/attribute.rb +13 -12
- data/lib/attributor/extras/field_selector.rb +1 -1
- data/lib/attributor/types/bigdecimal.rb +1 -1
- data/lib/attributor/types/date.rb +2 -2
- data/lib/attributor/types/date_time.rb +3 -2
- data/lib/attributor/types/polymorphic.rb +1 -1
- data/lib/attributor/types/string.rb +1 -10
- data/lib/attributor/types/tempfile.rb +1 -1
- data/lib/attributor/types/time.rb +3 -3
- data/lib/attributor/types/uri.rb +1 -1
- data/lib/attributor/version.rb +1 -1
- data/lib/attributor.rb +4 -5
- data/spec/attribute_spec.rb +1 -25
- data/spec/support/hashes.rb +1 -1
- data/spec/support/models.rb +16 -16
- data/spec/types/csv_spec.rb +1 -1
- data/spec/types/date_spec.rb +6 -6
- data/spec/types/model_spec.rb +1 -1
- data/spec/types/string_spec.rb +0 -8
- metadata +9 -10
- data/lib/attributor/extensions/randexp.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bec1eaa11a8711121f24b64eb86dcedc3779012f3ccc2239882bfa38527a0db
|
4
|
+
data.tar.gz: 15e6274f319f78d5c7801015ed5a97fd3858727ce98956a2e3b0229c89bdf25c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1055363cc837a07b3c319f0cfec62293797361a713354c146e3c1bead0b2fa0cbb2313dfcf092400abc57f5101a6fc76b782ba51bb9876c09720c2a382bb09de
|
7
|
+
data.tar.gz: 0aea79491d61b6ab866aec643c93d18bd372b8afc63428ba69d4a9723d0fd55a24589ea182a4ed2a0029e30a55f522981010f5637a54ea98af68ec0f41b48ec7
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# Attributor Changelog
|
2
2
|
|
3
|
-
##
|
3
|
+
## 8.0
|
4
|
+
|
5
|
+
- Add support for Ruby 3.2.
|
6
|
+
- Remove usage of Randexp for examples and replace with Faker.
|
7
|
+
- The above means this also removes support for generating examples using regular expressions.
|
4
8
|
|
5
9
|
## 7.1 (6/9/2023)
|
6
10
|
- Enhance custom_option handling. The values provided for custom options are now loaded (and definition will fail if they aren't compatible). This was specially
|
@@ -37,7 +41,7 @@
|
|
37
41
|
- added support for enum's out of values in json_schema generation
|
38
42
|
|
39
43
|
## 6.0 (22/11/2021)
|
40
|
-
- removed `required_if` support and all of the necessary code.
|
44
|
+
- removed `required_if` support and all of the necessary code.
|
41
45
|
- changed the semantics of the `required:` option in attributes, to really mean if the "key" is required to be passed in or not (i.e., check if the key is null, not if its value is null)
|
42
46
|
- Introduced a new option`null: true|false` to allow for the value of an attribute to be nullable or not when the attribute is passed in.
|
43
47
|
* The default behavior for an attribute nullability currently `null: false` (but it can be easily changed by overriding the `Attributor::Attribute.default_for_null` function to return `true`)
|
data/attributor.gemspec
CHANGED
@@ -13,14 +13,14 @@ Gem::Specification.new do |spec|
|
|
13
13
|
|
14
14
|
spec.homepage = 'https://github.com/rightscale/attributor'
|
15
15
|
spec.license = 'MIT'
|
16
|
-
spec.required_ruby_version = '>=2.
|
16
|
+
spec.required_ruby_version = '>=2.7'
|
17
17
|
|
18
18
|
spec.require_paths = ['lib']
|
19
19
|
spec.files = `git ls-files -z`.split("\x0")
|
20
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
21
|
|
22
22
|
spec.add_runtime_dependency('hashie', ['~> 3'])
|
23
|
-
spec.add_runtime_dependency('
|
23
|
+
spec.add_runtime_dependency('faker', [' >= 3.2'])
|
24
24
|
spec.add_runtime_dependency('activesupport', ['>= 3'])
|
25
25
|
|
26
26
|
spec.add_development_dependency 'rspec', '~> 3'
|
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency('guard', ['~> 2'])
|
35
35
|
spec.add_development_dependency('guard-rspec', ['~> 4'])
|
36
36
|
spec.add_development_dependency('pry')
|
37
|
+
|
37
38
|
if RUBY_PLATFORM !~ /java/
|
38
39
|
spec.add_development_dependency('pry-byebug')
|
39
40
|
spec.add_development_dependency('pry-stack_explorer')
|
data/lib/attributor/attribute.rb
CHANGED
@@ -27,7 +27,7 @@ module Attributor
|
|
27
27
|
|
28
28
|
class << self
|
29
29
|
attr_accessor :custom_options
|
30
|
-
end
|
30
|
+
end
|
31
31
|
|
32
32
|
def self.custom_option(name, attr_type, options = {}, &block)
|
33
33
|
if TOP_LEVEL_OPTIONS.include?(name) || INTERNAL_OPTIONS.include?(name)
|
@@ -47,7 +47,7 @@ module Attributor
|
|
47
47
|
current_option_name = nil # Use this to avoid having to wrap each loop with a begin/rescue block
|
48
48
|
(self.class.custom_options.keys & @options.keys).each do |custom_key|
|
49
49
|
current_option_name = custom_key
|
50
|
-
@options[custom_key] = self.class.custom_options[custom_key].load(@options[custom_key])
|
50
|
+
@options[custom_key] = self.class.custom_options[custom_key].load(@options[custom_key])
|
51
51
|
end
|
52
52
|
rescue => e
|
53
53
|
raise AttributorException, "Error while loading value #{@options[current_option_name]} for custom option '#{current_option_name}': #{e.message}"
|
@@ -156,8 +156,6 @@ module Attributor
|
|
156
156
|
def example_from_options(parent, context)
|
157
157
|
val = options[:example]
|
158
158
|
generated = case val
|
159
|
-
when ::Regexp
|
160
|
-
val.gen
|
161
159
|
when ::Proc
|
162
160
|
if val.arity == 2
|
163
161
|
val.call(parent, context)
|
@@ -211,8 +209,10 @@ module Attributor
|
|
211
209
|
description
|
212
210
|
end
|
213
211
|
|
214
|
-
def example(context=nil, parent: nil, values:{})
|
215
|
-
|
212
|
+
def example(context = nil, parent: nil, values: {})
|
213
|
+
require 'faker'
|
214
|
+
raise ArgumentError, 'attribute example cannot take a context of type String' if context.is_a? ::String
|
215
|
+
|
216
216
|
if context
|
217
217
|
ctx = Attributor.humanize_context(context)
|
218
218
|
seed, = Digest::SHA1.digest(ctx).unpack('QQ')
|
@@ -226,10 +226,11 @@ module Attributor
|
|
226
226
|
# Only validate the type, if the proc-generated example is "complex" (has attributes)
|
227
227
|
errors = loaded.class.respond_to?(:attributes) ? validate_type(loaded, context) : validate(loaded, context)
|
228
228
|
raise AttributorException, "Error generating example for #{Attributor.humanize_context(context)}. Errors: #{errors.inspect}" if errors.any?
|
229
|
+
|
229
230
|
return loaded
|
230
231
|
end
|
231
232
|
|
232
|
-
return options[:values].
|
233
|
+
return options[:values].sample if options.key? :values
|
233
234
|
|
234
235
|
if type.respond_to?(:attributes)
|
235
236
|
type.example(context, **values)
|
@@ -242,7 +243,7 @@ module Attributor
|
|
242
243
|
type.attributes if @type_has_attributes ||= type.respond_to?(:attributes)
|
243
244
|
end
|
244
245
|
|
245
|
-
# Default value for a non-specified null: option
|
246
|
+
# Default value for a non-specified null: option
|
246
247
|
def self.default_for_null
|
247
248
|
false
|
248
249
|
end
|
@@ -272,7 +273,7 @@ module Attributor
|
|
272
273
|
end
|
273
274
|
|
274
275
|
return errors if errors.any?
|
275
|
-
|
276
|
+
|
276
277
|
object.nil? ? errors : errors + type.validate(object, context, self)
|
277
278
|
end
|
278
279
|
|
@@ -303,7 +304,7 @@ module Attributor
|
|
303
304
|
raise AttributorException, 'Required must be a boolean' unless definition == true || definition == false
|
304
305
|
raise AttributorException, 'Required cannot be enabled in combination with :default' if definition == true && options.key?(:default)
|
305
306
|
when :null
|
306
|
-
raise AttributorException, 'Null must be a boolean' unless definition == true || definition == false
|
307
|
+
raise AttributorException, 'Null must be a boolean' unless definition == true || definition == false
|
307
308
|
when :example
|
308
309
|
unless definition.is_a?(::Regexp) || definition.is_a?(::String) || definition.is_a?(::Array) || definition.is_a?(::Proc) || definition.nil? || type.valid_type?(definition)
|
309
310
|
raise AttributorException, "Invalid example type (got: #{definition.class.name}). It must always match the type of the attribute (except if passing Regex that is allowed for some types)"
|
@@ -317,8 +318,8 @@ module Attributor
|
|
317
318
|
:ok # passes
|
318
319
|
end
|
319
320
|
|
320
|
-
def check_custom_option(name, definition)
|
321
|
-
attribute = self.class.custom_options.fetch(name)
|
321
|
+
def check_custom_option(name, definition)
|
322
|
+
attribute = self.class.custom_options.fetch(name)
|
322
323
|
|
323
324
|
errors = attribute.validate(definition)
|
324
325
|
raise AttributorException, "Custom option #{name.inspect} is invalid: #{errors.inspect}" if errors.any?
|
@@ -9,7 +9,7 @@ module Attributor
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.example(_context = nil, options: {})
|
12
|
-
BigDecimal("#{
|
12
|
+
BigDecimal("#{Faker::Number.decimal(l_digits: 3, r_digits: 3)}")
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.load(value, _context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
|
@@ -9,7 +9,7 @@ module Attributor
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.example(context = nil, options: {})
|
12
|
-
load(
|
12
|
+
load(Faker::Date.in_date_period, context)
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
|
@@ -21,7 +21,7 @@ module Attributor
|
|
21
21
|
case value
|
22
22
|
when ::String
|
23
23
|
begin
|
24
|
-
|
24
|
+
::Date.parse(value)
|
25
25
|
rescue ArgumentError
|
26
26
|
raise Attributor::DeserializationError.new(context: context, from: value.class, encoding: 'Date', value: value)
|
27
27
|
end
|
@@ -13,7 +13,7 @@ module Attributor
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.example(context = nil, options: {})
|
16
|
-
load(
|
16
|
+
load(Faker::Date.in_date_period, context)
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
|
@@ -21,10 +21,11 @@ module Attributor
|
|
21
21
|
return value if value.is_a?(native_type)
|
22
22
|
return value.to_datetime if value.respond_to?(:to_datetime)
|
23
23
|
return nil unless value.is_a?(::String)
|
24
|
+
|
24
25
|
# TODO: we should be able to convert not only from String but Time...etc
|
25
26
|
# Else, we'll decode it from String.
|
26
27
|
begin
|
27
|
-
|
28
|
+
::DateTime.parse(value)
|
28
29
|
rescue ArgumentError
|
29
30
|
raise Attributor::DeserializationError.new(context: context, from: value.class, encoding: 'DateTime', value: value)
|
30
31
|
end
|
@@ -17,16 +17,7 @@ module Attributor
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.example(_context = nil, options: {})
|
20
|
-
|
21
|
-
begin
|
22
|
-
# It may fail to generate an example, see bug #72.
|
23
|
-
options[:regexp].gen
|
24
|
-
rescue => e
|
25
|
-
format('Failed to generate example for %s : %s', options[:regexp].inspect, e.message)
|
26
|
-
end
|
27
|
-
else
|
28
|
-
/\w+/.gen
|
29
|
-
end
|
20
|
+
Faker::Lorem.word
|
30
21
|
end
|
31
22
|
|
32
23
|
def self.family
|
@@ -10,7 +10,7 @@ module Attributor
|
|
10
10
|
|
11
11
|
def self.example(context = Attributor::DEFAULT_ROOT_CONTEXT, options: {})
|
12
12
|
file = ::Tempfile.new(Attributor.humanize_context(context))
|
13
|
-
file.write
|
13
|
+
file.write Faker::Lorem.paragraph
|
14
14
|
file.write '.'
|
15
15
|
file.rewind
|
16
16
|
file
|
@@ -9,7 +9,7 @@ module Attributor
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.example(context = nil, options: {})
|
12
|
-
load(
|
12
|
+
load(Faker::Time.between(from: ::DateTime.now - 1, to: ::DateTime.now), context)
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
|
@@ -24,10 +24,10 @@ module Attributor
|
|
24
24
|
def self.parse(value, context)
|
25
25
|
case value
|
26
26
|
when ::Integer
|
27
|
-
|
27
|
+
::Time.at(value)
|
28
28
|
when ::String
|
29
29
|
begin
|
30
|
-
|
30
|
+
::Time.parse(value)
|
31
31
|
rescue ArgumentError
|
32
32
|
raise Attributor::DeserializationError.new(context: context, from: value.class, encoding: 'Time', value: value)
|
33
33
|
end
|
data/lib/attributor/types/uri.rb
CHANGED
data/lib/attributor/version.rb
CHANGED
data/lib/attributor.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'json'
|
2
|
-
require 'randexp'
|
3
2
|
|
4
3
|
require 'hashie'
|
5
4
|
require 'active_support/concern'
|
@@ -17,8 +16,6 @@ module Attributor
|
|
17
16
|
|
18
17
|
require_relative 'attributor/example_mixin'
|
19
18
|
|
20
|
-
require_relative 'attributor/extensions/randexp'
|
21
|
-
|
22
19
|
# hierarchical separator string for composing human readable attributes
|
23
20
|
SEPARATOR = '.'.freeze
|
24
21
|
ROOT_PREFIX = '$'.freeze
|
@@ -37,11 +34,13 @@ module Attributor
|
|
37
34
|
|
38
35
|
def self.find_type(attr_type)
|
39
36
|
return attr_type if attr_type < Attributor::Type
|
37
|
+
|
40
38
|
name = attr_type.name.split('::').last # TOO EXPENSIVE?
|
41
39
|
|
42
40
|
klass = const_get(name) if const_defined?(name)
|
43
41
|
raise AttributorException, "Could not find class with name #{name}" unless klass
|
44
42
|
raise AttributorException, "Could not find attribute type for: #{name} [klass: #{klass.name}]" unless klass < Attributor::Type
|
43
|
+
|
45
44
|
klass
|
46
45
|
end
|
47
46
|
|
@@ -57,7 +56,7 @@ module Attributor
|
|
57
56
|
context = Array(context) if context.is_a? ::String
|
58
57
|
|
59
58
|
begin
|
60
|
-
|
59
|
+
context.join('.')
|
61
60
|
rescue e
|
62
61
|
raise "Error creating context string: #{e.message}"
|
63
62
|
end
|
@@ -81,7 +80,7 @@ module Attributor
|
|
81
80
|
else
|
82
81
|
val
|
83
82
|
end
|
84
|
-
end
|
83
|
+
end
|
85
84
|
|
86
85
|
MODULE_PREFIX = 'Attributor::'.freeze
|
87
86
|
MODULE_PREFIX_REGEX = ::Regexp.new(MODULE_PREFIX)
|
data/spec/attribute_spec.rb
CHANGED
@@ -273,7 +273,7 @@ describe Attributor::Attribute do
|
|
273
273
|
end
|
274
274
|
|
275
275
|
context 'deterministic examples' do
|
276
|
-
let(:example) {
|
276
|
+
let(:example) { proc { Faker::Lorem.word } }
|
277
277
|
let(:attribute_options) { { example: example } }
|
278
278
|
|
279
279
|
it 'can take a context to pre-seed the random number generator' do
|
@@ -332,30 +332,6 @@ describe Attributor::Attribute do
|
|
332
332
|
it { should be example }
|
333
333
|
end
|
334
334
|
|
335
|
-
context 'with a regexp' do
|
336
|
-
let(:example) { Regexp.new(/\w+/) }
|
337
|
-
let(:generated_example) { /\w+/.gen }
|
338
|
-
|
339
|
-
it 'calls #gen on the regexp' do
|
340
|
-
expect(example).to receive(:gen).and_return(generated_example)
|
341
|
-
|
342
|
-
expect(example_result).to match example
|
343
|
-
end
|
344
|
-
|
345
|
-
context 'for a type with a non-String native_type' do
|
346
|
-
let(:type) { Attributor::Integer }
|
347
|
-
let(:example) { Regexp.new(/\d{5}/) }
|
348
|
-
let(:generated_example) { /\d{5}/.gen }
|
349
|
-
|
350
|
-
it 'coerces the example value properly' do
|
351
|
-
expect(example).to receive(:gen).and_return(generated_example)
|
352
|
-
expect(type).to receive(:load).and_call_original
|
353
|
-
|
354
|
-
expect(example_result).to be_kind_of(type.native_type)
|
355
|
-
end
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
335
|
context 'with a proc' do
|
360
336
|
let(:parent) { Object.new }
|
361
337
|
|
data/spec/support/hashes.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class HashWithModel < Attributor::Hash
|
2
2
|
keys do
|
3
|
-
key :name, String, default: 'Turkey McDucken', description: 'Turducken name', example:
|
3
|
+
key :name, String, default: 'Turkey McDucken', description: 'Turducken name', example: proc { Faker::Name.first_name }
|
4
4
|
key :chicken, Chicken
|
5
5
|
end
|
6
6
|
end
|
data/spec/support/models.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
class Chicken < Attributor::Model
|
2
2
|
attributes(identity: :email) do
|
3
|
-
attribute :name, Attributor::String, example:
|
3
|
+
attribute :name, Attributor::String, example: proc { Faker::Name.first_name }
|
4
4
|
attribute :age, Attributor::Integer, default: 1, min: 0, max: 120, description: 'The age of the chicken'
|
5
|
-
attribute :email, Attributor::String, example:
|
5
|
+
attribute :email, Attributor::String, example: proc { "#{Faker::Name.first_name.downcase}@#{Faker::Lorem.word.downcase}.example.org" }, regexp: /@/, description: 'The email address of the chicken'
|
6
6
|
attribute :angry, Attributor::Boolean, example: 'true', description: 'Angry bird?'
|
7
|
-
attribute :weight, Attributor::Float, example:
|
7
|
+
attribute :weight, Attributor::Float, example: proc { Faker::Number.number(digits: 3) }, description: 'The weight of the chicken'
|
8
8
|
attribute :type, Attributor::Symbol, values: [:chicken]
|
9
9
|
end
|
10
10
|
end
|
@@ -14,8 +14,8 @@ class Duck < Attributor::Model
|
|
14
14
|
attribute :age, Attributor::Integer
|
15
15
|
attribute :name, Attributor::String
|
16
16
|
attribute :email, Attributor::String
|
17
|
-
attribute :angry, Attributor::Boolean, default: true, example:
|
18
|
-
attribute :weight, Attributor::Float, example:
|
17
|
+
attribute :angry, Attributor::Boolean, default: true, example: proc { [true, false].sample }, description: 'Angry bird?'
|
18
|
+
attribute :weight, Attributor::Float, example: proc { Faker::Number.number(digits: 3).to_f }, description: 'The weight of the duck'
|
19
19
|
attribute :type, Attributor::Symbol, values: [:duck]
|
20
20
|
end
|
21
21
|
end
|
@@ -23,16 +23,16 @@ end
|
|
23
23
|
class Turkey < Attributor::Model
|
24
24
|
attributes do
|
25
25
|
attribute :age, Integer, default: 1, min: 0, max: 120, description: 'The age of the turkey'
|
26
|
-
attribute :name, String, description: 'name of the turkey', example:
|
27
|
-
attribute :email, String, example:
|
28
|
-
attribute :weight, Attributor::Float, example:
|
26
|
+
attribute :name, String, description: 'name of the turkey', example: proc { Faker::Name.name } # , :default => "Providencia Zboncak"
|
27
|
+
attribute :email, String, example: proc { "#{Faker::Name.first_name.downcase}@example.org" }, regexp: /@/, description: 'The email address of the turkey'
|
28
|
+
attribute :weight, Attributor::Float, example: proc { Faker::Number.number(digits: 2).to_f }, max: 100.0, description: 'The weight of the turkey'
|
29
29
|
attribute :type, Attributor::Symbol, values: [:turkey]
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
class Turducken < Attributor::Model
|
34
34
|
attributes do
|
35
|
-
attribute :name, String, default: 'Turkey McDucken', description: 'Turducken name', example:
|
35
|
+
attribute :name, String, default: 'Turkey McDucken', description: 'Turducken name', example: proc { Faker::Name.first_name }
|
36
36
|
attribute :chicken, Chicken
|
37
37
|
attribute :duck, Duck
|
38
38
|
attribute :turkey, Turkey, description: 'The turkey'
|
@@ -43,7 +43,7 @@ end
|
|
43
43
|
|
44
44
|
class Cormorant < Attributor::Model
|
45
45
|
attributes do
|
46
|
-
attribute :name, String, description: 'Name of the Cormorant', example:
|
46
|
+
attribute :name, String, description: 'Name of the Cormorant', example: proc { Faker::Name.name }
|
47
47
|
attribute :timestamps do
|
48
48
|
attribute :born_at, DateTime
|
49
49
|
attribute :died_at, DateTime, example: proc { |timestamps| timestamps.born_at + 10 }
|
@@ -53,22 +53,22 @@ class Cormorant < Attributor::Model
|
|
53
53
|
attribute :all_the_fish, Attributor::Collection, description: 'All kinds of fish for feeding the babies'
|
54
54
|
|
55
55
|
# This will be a collection of Cormorants (note, this relationship is circular)
|
56
|
-
attribute :neighbors, Attributor::Collection.of(Cormorant), member_options: {null: false}, description: 'Neighbor cormorants', null: false
|
56
|
+
attribute :neighbors, Attributor::Collection.of(Cormorant), member_options: { null: false }, description: 'Neighbor cormorants', null: false
|
57
57
|
|
58
58
|
# This will be a collection of instances of an anonymous Struct class, each having two well-defined attributes
|
59
59
|
|
60
60
|
attribute :babies, Attributor::Collection.of(Attributor::Struct), description: 'All the babies', member_options: { identity: :name } do
|
61
|
-
attribute :name, Attributor::String, example:
|
61
|
+
attribute :name, Attributor::String, example: proc { Faker::Name.name }, description: 'The name of the baby cormorant', required: true
|
62
62
|
attribute :months, Attributor::Integer, default: 0, min: 0, description: 'The age in months of the baby cormorant'
|
63
|
-
attribute :weight, Attributor::Float, example:
|
63
|
+
attribute :weight, Attributor::Float, example: proc { Faker::Number.number(digits: 2) }, description: 'The weight in kg of the baby cormorant'
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
68
|
class Person < Attributor::Model
|
69
69
|
attributes do
|
70
|
-
attribute :name, String, example:
|
71
|
-
attribute :title, String, values: %w
|
70
|
+
attribute :name, String, example: proc { Faker::Name.first_name }
|
71
|
+
attribute :title, String, values: %w[Mr Mrs Ms Dr]
|
72
72
|
attribute :okay, Attributor::Boolean, values: [true]
|
73
73
|
attribute :address, Address, example: proc { |person, context| Address.example(context, person: person) }
|
74
74
|
end
|
@@ -77,7 +77,7 @@ end
|
|
77
77
|
class Address < Attributor::Model
|
78
78
|
attributes do
|
79
79
|
attribute :name, String, example: /\w+/, null: true
|
80
|
-
attribute :state, String, values: %w
|
80
|
+
attribute :state, String, values: %w[OR CA], null: false
|
81
81
|
attribute :person, Person, example: proc { |address, context| Person.example(context, address: address) }
|
82
82
|
attribute :substruct, reference: Address, null: false do
|
83
83
|
attribute :state, Struct do # redefine state as a Struct
|
data/spec/types/csv_spec.rb
CHANGED
@@ -29,7 +29,7 @@ describe Attributor::CSV do
|
|
29
29
|
|
30
30
|
context '.dump' do
|
31
31
|
let!(:int_vals) { [1, 2, 3] }
|
32
|
-
let!(:str_vals) { (0..2).collect {
|
32
|
+
let!(:str_vals) { (0..2).collect { Faker::Lorem.word } }
|
33
33
|
|
34
34
|
it 'dumps a String value' do
|
35
35
|
expect(csv.dump(int_vals)).to be_a(String)
|
data/spec/types/date_spec.rb
CHANGED
@@ -19,7 +19,7 @@ describe Attributor::Date do
|
|
19
19
|
let(:example) { type.example }
|
20
20
|
subject(:value) { type.dump(example) }
|
21
21
|
it 'is formatted correctly' do
|
22
|
-
expect(value).to match(/\d{4}-\d{2}-\d{2}
|
22
|
+
expect(value).to match(/\d{4}-\d{2}-\d{2}/)
|
23
23
|
end
|
24
24
|
context 'nil values' do
|
25
25
|
it 'should be nil' do
|
@@ -59,7 +59,7 @@ describe Attributor::Date do
|
|
59
59
|
'Sat, 3 Feb 2001 04:05:06 +0700',
|
60
60
|
'2013/08/23 00:39:55 +0000',
|
61
61
|
'2007-10-19T04:11:33Z',
|
62
|
-
'2001-02-03T04:05:06+07:00.123456'
|
62
|
+
'2001-02-03T04:05:06+07:00.123456' # custom format with microseconds
|
63
63
|
].each do |value|
|
64
64
|
it "returns correct Date for #{value.inspect}" do
|
65
65
|
expect(type.load(value)).to eq Date.parse(value)
|
@@ -70,7 +70,7 @@ describe Attributor::Date do
|
|
70
70
|
'Sat, 30 Feb 2001 04:05:06 GMT', # No such date exists
|
71
71
|
'2013/08/33 00:39:55 +0000',
|
72
72
|
'2007-10-33T04:11:33Z',
|
73
|
-
'2001-02-33T04:05:06+07:00.123456'
|
73
|
+
'2001-02-33T04:05:06+07:00.123456' # custom format with microseconds
|
74
74
|
].each do |value|
|
75
75
|
it "raises Attributor::AttributorException for #{value.inspect}" do
|
76
76
|
expect do
|
@@ -82,7 +82,7 @@ describe Attributor::Date do
|
|
82
82
|
[
|
83
83
|
'',
|
84
84
|
'foobar',
|
85
|
-
'Sat, 30 Feb 2001 04:05:06 FOOBAR'
|
85
|
+
'Sat, 30 Feb 2001 04:05:06 FOOBAR' # No such date format exists
|
86
86
|
].each do |value|
|
87
87
|
it "raises Attributor::AttributorException for #{value.inspect}" do
|
88
88
|
expect do
|
@@ -93,11 +93,11 @@ describe Attributor::Date do
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
context '.as_json_schema' do
|
96
|
-
subject(:js){ type.as_json_schema }
|
96
|
+
subject(:js) { type.as_json_schema }
|
97
97
|
it 'adds the right attributes' do
|
98
98
|
expect(js.keys).to include(:type, :'x-type_name')
|
99
99
|
expect(js[:type]).to eq(:string)
|
100
|
-
expect(js[:format]).to eq(:
|
100
|
+
expect(js[:format]).to eq(:date)
|
101
101
|
expect(js[:'x-type_name']).to eq('Date')
|
102
102
|
end
|
103
103
|
end
|
data/spec/types/model_spec.rb
CHANGED
@@ -80,7 +80,7 @@ describe Attributor::Model do
|
|
80
80
|
subject(:chicken) { Chicken.example }
|
81
81
|
|
82
82
|
let(:age_opts) { { options: Chicken.attributes[:age].options } }
|
83
|
-
let(:age) {
|
83
|
+
let(:age) { Faker::Number.number(digits: 2) }
|
84
84
|
|
85
85
|
context 'for a simple model' do
|
86
86
|
it { should be_kind_of(Chicken) }
|
data/spec/types/string_spec.rb
CHANGED
@@ -22,14 +22,6 @@ describe Attributor::String do
|
|
22
22
|
expect(type.example).to be_a(::String)
|
23
23
|
end
|
24
24
|
|
25
|
-
it 'handles regexps that Randexp can not (#72)' do
|
26
|
-
regex = /\w+(,\w+)*/
|
27
|
-
expect do
|
28
|
-
val = Attributor::String.example(options: { regexp: regex })
|
29
|
-
expect(val).to be_a(::String)
|
30
|
-
expect(val).to match(/Failed to generate.+is too vague/)
|
31
|
-
end.to_not raise_error
|
32
|
-
end
|
33
25
|
end
|
34
26
|
|
35
27
|
context '.load' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attributor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '
|
4
|
+
version: '8.0'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josep M. Blanquer
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-08-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: hashie
|
@@ -26,19 +26,19 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '3'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: faker
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - "
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '3.2'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - "
|
39
|
+
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '3.2'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: activesupport
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -316,7 +316,6 @@ files:
|
|
316
316
|
- lib/attributor/dumpable.rb
|
317
317
|
- lib/attributor/example_mixin.rb
|
318
318
|
- lib/attributor/exceptions.rb
|
319
|
-
- lib/attributor/extensions/randexp.rb
|
320
319
|
- lib/attributor/extras/field_selector.rb
|
321
320
|
- lib/attributor/extras/field_selector/parser.rb
|
322
321
|
- lib/attributor/extras/field_selector/transformer.rb
|
@@ -400,14 +399,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
400
399
|
requirements:
|
401
400
|
- - ">="
|
402
401
|
- !ruby/object:Gem::Version
|
403
|
-
version: '2.
|
402
|
+
version: '2.7'
|
404
403
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
405
404
|
requirements:
|
406
405
|
- - ">="
|
407
406
|
- !ruby/object:Gem::Version
|
408
407
|
version: '0'
|
409
408
|
requirements: []
|
410
|
-
rubygems_version: 3.
|
409
|
+
rubygems_version: 3.4.10
|
411
410
|
signing_key:
|
412
411
|
specification_version: 4
|
413
412
|
summary: A powerful attribute and type management library for Ruby
|