statinize 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1df88422c35ca62b3fe9b3efab22633e9f72a0e59690db7a005ae2cb9ad8cb4f
4
- data.tar.gz: d72c1c0fdae71d168d082ee6e368970bdc81748cfa7ea293ec970065cd6232ef
3
+ metadata.gz: c23a5d1a081bed6fc734ac7e51c46ce597f053dafd0387af225e6a0ac03011c8
4
+ data.tar.gz: 10e6ebd5e049349848ed66bde67e14427306fc753161653b4fbd2e3825733614
5
5
  SHA512:
6
- metadata.gz: 21b6c73e849260241b4a2301bdbdf1663ceff7279b666564761818618728058be4e5e67dd9d6d11a1f7adc382468d8b5e7fdfcfaf67acbb3b294879a415d7a28
7
- data.tar.gz: c984be3998b0e6a4ee7e0c4c57263a88f9c1c9698fc91487a499980353c5be9b6a72c2f94ba87cf95d543b9ef5418303e32b2b3edd8299163660cd4c629bae33
6
+ metadata.gz: 077e8784ea1ab74e799bc8cc30d2ac59d543d17e34db83ea7b88cbe49d143b7cb126020ab4978f1ecc6b46f336100d0c6e1aa4952072a47a722673b468367589
7
+ data.tar.gz: 119d5c987fc543835726d56e6e578f82b3c2dc8c4571b65d0eb59aec21fc92df8e6b1d7200f9ff37daad17e7ff13b40a0bf38a3372f1018a59702699383ead34
@@ -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,49 +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
- attrs.each do |attr|
12
- Attribute.create(klass, attr, options)
13
- end
14
- end
15
-
16
- def validate(*attrs, **options)
17
- attrs.each do |attr|
18
- attribute = attributes.find { _1.name == attr }
19
- attribute&.add_options(options)
20
- end
21
- end
22
-
23
- def with(**options, &block)
24
- trace = TracePoint.trace(:call) do |tp|
25
- tp.disable
26
-
27
- if %i[attribute validate].include? tp.method_id
28
- tp.binding.local_variable_get(:options).merge!(options)
29
- end
30
-
31
- tp.enable
32
- end
33
-
34
- trace.enable
35
- instance_exec(&block)
36
- trace.disable
37
- end
38
-
39
- def force(force = nil)
40
- force.nil? ? @force : @force = force
41
- end
5
+ attr_reader :klass, :before_callbacks
42
6
 
43
7
  def self.configure(&block)
44
8
  Configuration.configure(&block)
45
9
  end
46
10
 
11
+ def initialize(klass)
12
+ @klass = klass
13
+ @force = config.force
14
+ @before_callbacks = []
15
+ end
16
+
47
17
  def config
48
18
  @config ||= Configuration.instance
49
19
  end
@@ -53,22 +23,28 @@ module Statinize
53
23
  end
54
24
 
55
25
  def add_attribute(attribute)
56
- attributes.add(attribute)
26
+ attributes.add(attribute) unless attribute? attribute
57
27
  end
58
28
 
59
29
  def attributes
60
30
  @attributes ||= Set.new
61
31
  end
62
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
+
63
39
  def attribute?(attribute)
64
- attributes.include? attribute
40
+ attributes.map(&:name).include? attribute.name
65
41
  end
66
42
 
67
43
  def check_validators_exist!
68
44
  raise NoSuchValidatorError unless all_validators_defined?
69
45
  end
70
46
 
71
- private
47
+ protected
72
48
 
73
49
  def all_validators_defined?
74
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,25 +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
- if erroneous_attributes[attr.name].add? option
55
- @errors << { attr.name => validator_instance.error }
58
+ erroneous_attributes[attr.name].add? option
59
+
60
+ unless @errors[attr.name].include?(validator_instance.error)
61
+ @errors[attr.name] << validator_instance.error
56
62
  end
63
+
57
64
  erroneous_forced_attributes[attr.name].add option if force
58
65
  end
59
66
  end
60
67
  end
61
68
  end
62
69
 
70
+ def cast?(attr, option)
71
+ option.should_cast? && cast(attr, option)
72
+ end
73
+
63
74
  def cast(attr, option)
64
- caster = Caster.new(instance, attr, option)
75
+ caster(attr, option).cast
76
+ end
65
77
 
66
- option.should_cast? && caster.cast
78
+ def caster(attr, option)
79
+ Caster.new(instance, attr, option)
67
80
  end
68
81
 
69
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.2
4
+ version: 0.2.3
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-10 00:00:00.000000000 Z
11
+ date: 2022-09-02 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: