statinize 0.2.1 → 0.2.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7814eb5a73fe5fb67c846398c6d22573b183cafd88c243175ef4fb39c5f71fbe
4
- data.tar.gz: b7eec7d141ae6a0deda224802f67dae791ea7b9c96957922c9a7fa9c1b052e6a
3
+ metadata.gz: b3dda46ee65052ce2579b2b223c659c3c76d68d85df008400d14432aeaf53fb1
4
+ data.tar.gz: bd60810a6e386bdad9d9628dc9f1cb2f0cf2b1e04df41f6fc1762109c7909081
5
5
  SHA512:
6
- metadata.gz: 8bea982ae518d67bb7f9c0a9cab47dd081d869dabbdf01874e14de5c2004217bd6f395e5e040f93499cbe5de413e1d3ed6b59222e9d8089cb6b01289748d1be9
7
- data.tar.gz: '08111b888a705bb74fe044f9de93ebcfd6863646df65510bf62e0566b23af1e4ef410609a22b0fc1afb1b15ffac62edbd9b43264a02191504e25296a99eab1e8'
6
+ metadata.gz: d3ca8f71c4efa6b8298fffc4ff94fa45193d7aa0ef60bfb6128ca539683c8500086362e520c6e8937dfd82d7896475d90854b01a947a38519d08105a4c048cb3
7
+ data.tar.gz: d2d6b696b3195cd9b75cfe8b35ce7eb149965ed89c3d79c2f3737e575cb5bcd2a2be80e6e5061c712e4f68a57aa9d71fcdf90a4c5c36a2e7d7f4069d07a2826b
@@ -24,7 +24,7 @@ module Statinize
24
24
  end
25
25
 
26
26
  def should_cast?
27
- key?(:type) && key?(:cast)
27
+ key?(:type) && public_send(:[], :cast)
28
28
  end
29
29
 
30
30
  def should_validate?(instance)
@@ -2,7 +2,8 @@ module Statinize
2
2
  class Attribute
3
3
  include Comparable
4
4
 
5
- attr_reader :klass, :name, :options
5
+ attr_reader :klass, :name
6
+ attr_accessor :options
6
7
 
7
8
  def initialize(klass, name, opts)
8
9
  @klass = klass
@@ -11,7 +12,7 @@ module Statinize
11
12
  @options << opts.clone.extend(Options) unless opts.empty?
12
13
  end
13
14
 
14
- def self.create(klass, name, opts)
15
+ def self.create(klass, name, opts = {})
15
16
  new(klass, name, opts).create
16
17
  end
17
18
 
@@ -9,6 +9,8 @@ module Statinize
9
9
  Symbol => :to_sym,
10
10
  Enumerator => :to_enum,
11
11
  Proc => :to_proc,
12
+ Array => :to_a,
13
+ BigDecimal => :to_d,
12
14
  }.freeze
13
15
 
14
16
  def initialize(instance, attr, option)
@@ -30,7 +32,9 @@ module Statinize
30
32
  attr_reader :instance, :attr_name, :attr_value, :validator_value
31
33
 
32
34
  def castable?
33
- attr_value.respond_to? casting
35
+ return attr_value.respond_to?(casting) if casting.is_a?(String) || casting.is_a?(Symbol)
36
+
37
+ false
34
38
  end
35
39
 
36
40
  def casting
@@ -0,0 +1,60 @@
1
+ # Defines DSL for statinize block
2
+ module Statinize
3
+ module DSL
4
+ def attribute(*attrs, **options)
5
+ attrs.each do |attr|
6
+ Attribute.create(klass, attr, options) unless attribute? attr
7
+ end
8
+ end
9
+
10
+ def validate(*attrs, **options)
11
+ attrs.each do |attr|
12
+ attribute = attributes.find { _1.name == attr }
13
+ attribute = Attribute.create(klass, attr) unless attribute
14
+ attribute.add_options(options)
15
+ end
16
+ end
17
+
18
+ def with(**options, &block)
19
+ instance = self.class.new(klass)
20
+ instance.force(force)
21
+
22
+ klass.instance_variable_set(:@statinizer, instance)
23
+ instance.instance_exec(&block)
24
+ klass.instance_variable_set(:@statinizer, self)
25
+
26
+ instance.merge_options(**options)
27
+
28
+ populate(instance.attributes)
29
+ end
30
+
31
+ def before(&block)
32
+ return unless block_given?
33
+
34
+ before_callbacks << block
35
+ end
36
+
37
+ def force(force = nil)
38
+ force.nil? ? @force : @force = force
39
+ end
40
+
41
+ protected
42
+
43
+ def merge_options(**options)
44
+ attributes.each do |attribute|
45
+ attribute.options.each do |option|
46
+ option.merge!(options)
47
+ end
48
+ end
49
+ end
50
+
51
+ def populate(attrs)
52
+ attrs.each do |attr|
53
+ attribute attr.name
54
+ attributes
55
+ .find { _1.name == attr.name }
56
+ .options = attr.options.clone
57
+ end
58
+ end
59
+ end
60
+ end
@@ -7,10 +7,12 @@ module Statinize
7
7
 
8
8
  class UndefinedAttribute < StandardError; end
9
9
 
10
- class Errors < Array
11
- def to_s
12
- nice_errors = map do |i|
13
- "#{i.keys.first.to_s.split("_").tap { |attr| attr.first.capitalize! }.join(" ")} #{i.values.first}"
10
+ class Errors < Hash
11
+ def nice
12
+ nice_errors = map do |attr_name, errors|
13
+ errors.map do |error|
14
+ "#{attr_name.to_s.split("_").tap { |attr| attr.first.capitalize! }.join(" ")} #{error}"
15
+ end.join("; ")
14
16
  end.join("; ")
15
17
 
16
18
  "ValidationError: #{nice_errors}"
@@ -6,16 +6,21 @@ module Statinize
6
6
  end
7
7
 
8
8
  module PrependedMethods
9
- def initialize(*args, **kwargs, &block)
9
+ def initialize(options = {}, *args, **kwargs, &block)
10
+ symbolized = kwargs.transform_keys(&:to_sym)
11
+ .merge(options.transform_keys(&:to_sym))
12
+
10
13
  if private_methods(false).include? :initialize
11
14
  super(*args, **kwargs, &block)
12
- check_defined!(kwargs)
15
+ check_defined!(symbolized)
13
16
  else
14
17
  statinizer.attributes.map(&:name).each do |attr|
15
- instance_variable_set("@#{attr}", kwargs[attr]) if kwargs.key?(attr)
18
+ instance_variable_set("@#{attr}", symbolized[attr]) if symbolized.key?(attr)
16
19
  end
17
20
  end
18
21
 
22
+ run_before_callbacks
23
+
19
24
  define_validation
20
25
  validate!
21
26
  end
@@ -24,6 +29,10 @@ module Statinize
24
29
  @validation ||= Validation.new(statinizer, self)
25
30
  end
26
31
 
32
+ def run_before_callbacks
33
+ statinizer.run_before_callbacks(self)
34
+ end
35
+
27
36
  def attributes
28
37
  @attributes = Hash[
29
38
  statinizer.attributes.map { |a| [a.name, public_send(a.name)] }
@@ -1,44 +1,19 @@
1
1
  module Statinize
2
2
  class Statinizer
3
- attr_reader :klass
3
+ include DSL
4
4
 
5
- def initialize(klass)
6
- @klass = klass
7
- @force = config.force
8
- end
9
-
10
- def attribute(*attrs, **options)
11
- options.merge!(@with) if @with
12
-
13
- attrs.each do |attr|
14
- Attribute.create(klass, attr, options)
15
- end
16
- end
17
-
18
- def validate(*attrs, **options)
19
- options.merge!(@with) if @with
20
-
21
- attrs.each do |attr|
22
- attribute = attributes.find { _1.name == attr }
23
- attribute&.add_options(options)
24
- end
25
- end
26
-
27
- def with(**kwargs, &block)
28
- @with = kwargs
29
- instance_exec(&block)
30
-
31
- remove_instance_variable(:@with) if @with
32
- end
33
-
34
- def force(force = nil)
35
- force.nil? ? @force : @force = force
36
- end
5
+ attr_reader :klass, :before_callbacks
37
6
 
38
7
  def self.configure(&block)
39
8
  Configuration.configure(&block)
40
9
  end
41
10
 
11
+ def initialize(klass)
12
+ @klass = klass
13
+ @force = config.force
14
+ @before_callbacks = []
15
+ end
16
+
42
17
  def config
43
18
  @config ||= Configuration.instance
44
19
  end
@@ -48,22 +23,28 @@ module Statinize
48
23
  end
49
24
 
50
25
  def add_attribute(attribute)
51
- attributes.add(attribute)
26
+ attributes.add(attribute) unless attribute? attribute
52
27
  end
53
28
 
54
29
  def attributes
55
30
  @attributes ||= Set.new
56
31
  end
57
32
 
33
+ def run_before_callbacks(instance)
34
+ before_callbacks.each do |callback|
35
+ instance.instance_exec(&callback) if callback.is_a? Proc
36
+ end
37
+ end
38
+
58
39
  def attribute?(attribute)
59
- attributes.include? attribute
40
+ attributes.map(&:name).include? attribute.name
60
41
  end
61
42
 
62
43
  def check_validators_exist!
63
44
  raise NoSuchValidatorError unless all_validators_defined?
64
45
  end
65
46
 
66
- private
47
+ protected
67
48
 
68
49
  def all_validators_defined?
69
50
  attributes.map { |attr| attr.options.all_validators_defined? }.all? { !!_1 }
@@ -12,7 +12,7 @@ module Statinize
12
12
  end
13
13
 
14
14
  def validate
15
- @errors = Errors.new
15
+ @errors = Errors.new { |h, k| h[k] = [] }
16
16
  @erroneous_attributes = Hash.new { |h, k| h[k] = Set.new }
17
17
  @erroneous_forced_attributes = Hash.new { |h, k| h[k] = Set.new }
18
18
 
@@ -22,7 +22,7 @@ module Statinize
22
22
  def validate!
23
23
  validate
24
24
 
25
- raise ValidationError, errors.to_s if should_raise?
25
+ raise ValidationError, errors.nice if should_raise?
26
26
  end
27
27
 
28
28
  def valid?
@@ -45,24 +45,38 @@ module Statinize
45
45
  option.validators.each do |validator_class, validator_value|
46
46
  validator_instance = validator_class.new(attr_value, validator_value)
47
47
 
48
+ if option[:type] && option.should_cast? && attr_value.nil? && (option[:presence] || option[:nil] == false)
49
+ cast(attr, option)
50
+ end
51
+
48
52
  next if validator_instance.valid?
49
- next if validator_class == TypeValidator && cast(attr, option)
53
+ next if validator_class == TypeValidator && cast?(attr, option)
50
54
 
51
55
  force = option[:force] ||
52
56
  (statinizer.force? && option[:force].nil?)
53
57
 
54
- erroneous_attributes[attr.name].add option
58
+ erroneous_attributes[attr.name].add? option
59
+
60
+ unless @errors[attr.name].include?(validator_instance.error)
61
+ @errors[attr.name] << validator_instance.error
62
+ end
63
+
55
64
  erroneous_forced_attributes[attr.name].add option if force
56
- @errors << { attr.name => validator_instance.error }
57
65
  end
58
66
  end
59
67
  end
60
68
  end
61
69
 
70
+ def cast?(attr, option)
71
+ option.should_cast? && cast(attr, option)
72
+ end
73
+
62
74
  def cast(attr, option)
63
- caster = Caster.new(instance, attr, option)
75
+ caster(attr, option).cast
76
+ end
64
77
 
65
- option.should_cast? && caster.cast
78
+ def caster(attr, option)
79
+ Caster.new(instance, attr, option)
66
80
  end
67
81
 
68
82
  def should_raise?
@@ -0,0 +1,13 @@
1
+ module Statinize
2
+ class NilValidator < Validator
3
+ def valid?
4
+ return true if validator_value
5
+
6
+ !attr_value.nil?
7
+ end
8
+
9
+ def error
10
+ "is nil"
11
+ end
12
+ end
13
+ end
@@ -1,8 +1,9 @@
1
1
  module Statinize
2
2
  class PresenceValidator < Validator
3
3
  def valid?
4
- validator_value &&
5
- !empty_array? &&
4
+ return true unless validator_value
5
+
6
+ !empty_array? &&
6
7
  !empty_hash? &&
7
8
  !empty_string? &&
8
9
  !attr_value.nil?
@@ -1,7 +1,7 @@
1
1
  module Statinize
2
2
  class TypeValidator < Validator
3
3
  def valid?
4
- attr_value.is_a?(validator_value)
4
+ attr_value.is_a?(validator_value) || attr_value.nil?
5
5
  end
6
6
 
7
7
  def error
data/lib/statinize.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  require "set"
2
2
  require "pry"
3
3
  require "singleton"
4
+ require "bigdecimal/util"
4
5
  require_relative "statinize/statinizable"
6
+ require_relative "statinize/dsl"
5
7
  require_relative "statinize/statinizer"
6
8
  require_relative "statinize/configuration"
7
9
  require_relative "statinize/attribute"
@@ -13,5 +15,6 @@ require_relative "statinize/validation"
13
15
  require_relative "statinize/validators/type_validator"
14
16
  require_relative "statinize/validators/presence_validator"
15
17
  require_relative "statinize/validators/inclusion_validator"
18
+ require_relative "statinize/validators/nil_validator"
16
19
  require_relative "statinize/caster"
17
20
  require_relative "statinize/errors"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statinize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Barseek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-08 00:00:00.000000000 Z
11
+ date: 2022-09-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Statinization gem. Allows for creation of attributes for a class with
14
14
  a given type.
@@ -24,12 +24,14 @@ files:
24
24
  - lib/statinize/attribute/options_collection.rb
25
25
  - lib/statinize/caster.rb
26
26
  - lib/statinize/configuration.rb
27
+ - lib/statinize/dsl.rb
27
28
  - lib/statinize/errors.rb
28
29
  - lib/statinize/statinizable.rb
29
30
  - lib/statinize/statinizer.rb
30
31
  - lib/statinize/validation.rb
31
32
  - lib/statinize/validator.rb
32
33
  - lib/statinize/validators/inclusion_validator.rb
34
+ - lib/statinize/validators/nil_validator.rb
33
35
  - lib/statinize/validators/presence_validator.rb
34
36
  - lib/statinize/validators/type_validator.rb
35
37
  homepage: