striuct 0.7.0 → 0.8.0

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: c59316edafe027980857f258404996caaee0be26a0ad3265acee3cb067477db6
4
- data.tar.gz: '086afe2f12bb06050cd7964a774fd087e6a7a710f0d54fe6bb3c4e647490e2d7'
3
+ metadata.gz: d820670e757190ed2db502b8d6e0c53a7689f299262695f3ca18cec69dd5270b
4
+ data.tar.gz: 8a27cca712c9a63c2a5207090a6a8d0d8dcecd24a13bf07fa16c243a3b24c366
5
5
  SHA512:
6
- metadata.gz: 86c436676285e90dbafd4e1f9293b5cccfda99ce060e07a38893f4f0979c4c9f0b7c1c41da63e10ee479ff1323fa0f585c92113929bce766b072e577dc95b8cb
7
- data.tar.gz: 0fca1e67d31013254edeb00043cf42699a3845b83bd4979db8623d0ef2786daff07db0ced0dcda068f297e1d577fca063703592f65242c26d793a3e17e9fb786
6
+ metadata.gz: c90d1e6cc1ac20015660134d88d863dc935d6db44128e0f49f7c807b6b357d4821055d989e9e9e3a8bb4c49382acbab04509bf0445389a454c72c3fb729cbd85
7
+ data.tar.gz: a7154a914174099a8b5d32fe4b534811c14187f3fb9e8735cba701764b7d9aee640de1c276711dcedb85915f33efc9fecac87dde0ae8a09d704d0bbf84f3f11b
data/README.md CHANGED
@@ -1,49 +1,29 @@
1
- striuct
2
- =======
1
+ # striuct
3
2
 
4
3
  ![Build Status](https://github.com/kachick/striuct/actions/workflows/test_behaviors.yml/badge.svg?branch=main)
5
4
  [![Gem Version](https://badge.fury.io/rb/striuct.png)](http://badge.fury.io/rb/striuct)
6
5
 
7
- Description
8
- -----------
9
-
10
6
  Struct++
11
7
 
12
- Features
13
- --------
14
-
15
- ### Strict
16
-
17
- * Easy and Flexible Validations
18
- * Prevent to conflict member names
19
- * Lock setters for each member
20
-
21
- ### Useful
22
-
23
- * Hook just before setters
24
- * Default value
25
- * Member aliasing
26
- * Inheritable
27
- * Handling between nil <-> unassigned
28
- * Similar API for Hash
29
-
30
- ### Onepoint
31
-
32
- * Base API looks like Struct
33
- * Pure Ruby :)
34
-
35
- Usage
36
- -----
8
+ ## Usage
37
9
 
38
10
  Require Ruby 2.6 or later
39
11
 
40
12
  Add this line to your `Gemfile`
41
13
 
42
14
  ```ruby
43
- gem 'striuct', '>= 0.7.0', '< 0.8.0'
15
+ gem 'striuct', '>= 0.8.0', '< 0.9.0'
44
16
  ```
45
17
 
46
- ### Overview - Case 1
18
+ Then add below code into your Ruby code
19
+
20
+ ```ruby
21
+ require 'striuct'
22
+ ```
23
+
24
+ ### Overview
25
+
26
+ #### Case 1
47
27
 
48
28
  ```ruby
49
29
  require 'striuct'
@@ -72,7 +52,7 @@ ken = User[name: 'ken'] # Construct from hash
72
52
  ken.id #=> 2
73
53
  ```
74
54
 
75
- ### Overview - Case 2
55
+ #### Case 2
76
56
 
77
57
  ```ruby
78
58
  class Foo < Striuct
@@ -102,7 +82,7 @@ foo.with_adjuster = '5'
102
82
  foo.with_adjuster #=> 5 # Casted via adjuster
103
83
  ```
104
84
 
105
- ### Overview - Case 3
85
+ #### Case 3
106
86
 
107
87
  ```ruby
108
88
  class UseMustOption < Striuct
@@ -112,8 +92,32 @@ end
112
92
  UseMustOption.new #=> InvalidOperationError "`foo` require a value under `must` option "
113
93
  ```
114
94
 
115
- Link
116
- ----
95
+ ## Features
96
+
97
+ ### Strict
98
+
99
+ * Easy and Flexible Validations
100
+ * Basically use `#===` for the validation
101
+ * The pattern builder DSL is just using [eqq](https://github.com/kachick/eqq)
102
+ * When passed the Proc, it will be evaluated in the instance context
103
+ * Prevent to conflict member names
104
+ * Lock setters for each member
105
+
106
+ ### Useful
107
+
108
+ * Hook just before setters
109
+ * Default value
110
+ * Member aliasing
111
+ * Inheritable
112
+ * Handling between nil <-> unassigned
113
+ * Similar API for Hash
114
+
115
+ ### Finally
116
+
117
+ * Base API looks like Struct
118
+ * Pure Ruby :)
119
+
120
+ ## Link
117
121
 
118
122
  * [Repository](https://github.com/kachick/striuct)
119
123
  * [API documents](https://kachick.github.io/striuct/)
data/lib/striuct.rb CHANGED
@@ -7,6 +7,10 @@
7
7
  class Striuct
8
8
  class Error < StandardError; end
9
9
  class InvalidOperationError < Error; end
10
+ class InvalidValueError < Error; end
11
+ class InvalidWritingError < InvalidValueError; end
12
+ class InvalidReadingError < InvalidValueError; end
13
+ class InvalidAdjustingError < InvalidValueError; end
10
14
  end
11
15
 
12
- require_relative 'striuct/requirements'
16
+ require_relative 'striuct/bootstrap'
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'validation'
3
+ require 'forwardable'
4
+ require 'eqq'
5
+
4
6
  require_relative 'structs'
5
7
  require_relative 'classmethods/requirements'
6
8
  require_relative 'instancemethods/requirements'
@@ -4,6 +4,68 @@ class Striuct
4
4
  module ClassMethods
5
5
  # @group Adjuster
6
6
 
7
+ # Adjuster Builders
8
+ # Apply adjuster when passed pattern.
9
+ # @param pattern [Proc, Method, #===]
10
+ # @param adjuster [Proc, #to_proc]
11
+ # @return [Proc]
12
+ def WHEN(pattern, adjuster)
13
+ unless Eqq.valid?(pattern)
14
+ raise ArgumentError, 'wrong object for pattern'
15
+ end
16
+
17
+ unless Striuct.adjustable?(adjuster)
18
+ raise ArgumentError, 'wrong object for adjuster'
19
+ end
20
+
21
+ ->v { _valid?(pattern, v) ? adjuster.call(v) : v }
22
+ end
23
+
24
+ # Sequential apply all adjusters.
25
+ # @param adjuster1 [Proc, #to_proc]
26
+ # @param adjuster2 [Proc, #to_proc]
27
+ # @param adjusters [Proc, #to_proc]
28
+ # @return [Proc]
29
+ def INJECT(adjuster1, adjuster2, *adjusters)
30
+ adjusters = [adjuster1, adjuster2, *adjusters]
31
+
32
+ unless adjusters.all? { |f| adjustable?(f) }
33
+ raise ArgumentError, 'wrong object for adjuster'
34
+ end
35
+
36
+ ->v {
37
+ adjusters.reduce(v) { |ret, adjuster| adjuster.call(ret) }
38
+ }
39
+ end
40
+
41
+ # Accept any parser when that respond to parse method.
42
+ # @param parser [#parse]
43
+ # @return [Proc]
44
+ def PARSE(parser)
45
+ if !::Integer.equal?(parser) && !parser.respond_to?(:parse)
46
+ raise ArgumentError, 'wrong object for parser'
47
+ end
48
+
49
+ ->v {
50
+ if ::Integer.equal?(parser)
51
+ ::Kernel.Integer(v)
52
+ else
53
+ parser.parse(
54
+ case v
55
+ when String
56
+ v
57
+ when ->_ { v.respond_to?(:to_str) }
58
+ v.to_str
59
+ when ->_ { v.respond_to?(:read) }
60
+ v.read
61
+ else
62
+ raise TypeError, 'wrong object for parsing source'
63
+ end
64
+ )
65
+ end
66
+ }
67
+ end
68
+
7
69
  # @param [Symbol, String, #to_sym, Integer, #to_int] key - name / index
8
70
  def adjuster_for(key)
9
71
  autonym = autonym_for_key(key)
@@ -32,7 +32,7 @@ class Striuct
32
32
  end
33
33
 
34
34
  def condition=(condition)
35
- unless ::Validation.conditionable?(condition)
35
+ unless Eqq.valid?(condition)
36
36
  raise TypeError, 'wrong object for condition'
37
37
  end
38
38
 
@@ -40,7 +40,7 @@ class Striuct
40
40
  end
41
41
 
42
42
  def adjuster=(adjuster)
43
- unless ::Validation.adjustable?(adjuster)
43
+ unless Striuct.adjustable?(adjuster)
44
44
  raise ArgumentError, 'wrong object for adjuster'
45
45
  end
46
46
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'keyvalidatable'
4
-
5
3
  class Striuct
6
4
  module ClassMethods
7
5
  # @group Constructor
@@ -16,9 +14,8 @@ class Striuct
16
14
  # @param [Hash, Struct, Striuct, #each_pair] pairs
17
15
  # @return [Striuct]
18
16
  def for_pairs(pairs)
19
- raise TypeError, 'no pairs object' unless pairs.respond_to?(:each_pair)
20
-
21
- KeyValidatable.validate_array(KeyValidatable.keys_for(pairs).map(&:to_sym), let: all_members)
17
+ raise ArgumentError, 'no pairs object' unless pairs.respond_to?(:each_pair)
18
+ raise ArgumentError unless pairs.each_pair { |key, _value| all_members.include?(key.to_sym) }
22
19
 
23
20
  instance = allocate
24
21
  instance.__send__(:initialize_for_pairs, pairs)
@@ -46,7 +43,7 @@ class Striuct
46
43
 
47
44
  invalids = autonyms.select { |autonym| !instance.valid?(autonym) }
48
45
  if strict && !invalids.empty?
49
- raise Validation::InvalidWritingError,
46
+ raise InvalidWritingError,
50
47
  "invalids members are, yet '#{invalids.inspect} in #{self}'"
51
48
  end
52
49
 
@@ -4,36 +4,25 @@ class Striuct
4
4
  module ClassMethods
5
5
  # @group Macro for Member Definition
6
6
 
7
- ANYTHING = ::Validation::Condition.anything
7
+ ANYTHING = Eqq.ANYTHING()
8
8
 
9
9
  # @return [Class]
10
- ADD_MEMBER_OptArg = OptionalArgument.define {
11
- opt(:default_value, aliases: [:default])
12
- opt(:default_proc, aliases: [:lazy_default])
13
- conflict(:default_value, :default_proc)
14
- opt(:must, default: false)
15
- opt(:setter_validation, aliases: [:writer_validation], default: true)
16
- opt(:getter_validation, aliases: [:reader_validation], default: false)
17
- }
18
10
 
19
11
  private
20
12
 
21
13
  # @param [Symbol, String, #to_sym] autonym
22
- # @param [#===, Proc, Method] condition
23
- # @param [Hash] options
24
- # @option options [BasicObject] :default
25
- # @option options [Proc] :default_proc
26
- # @option options [Boolean] :must
27
- # @option options [Boolean] :reader_validation
28
- # @option options [Boolean] :getter_validation
29
- # @option options [Boolean] :writer_validation
30
- # @option options [Boolean] :setter_validation
31
- # @return [nil]
32
- def add_member(autonym, condition=anything, options={}, &adjuster)
14
+ # @param [#===, Proc, Method] pattern
15
+ # @param [Proc] default_proc
16
+ # @param [Boolean] must
17
+ # @param [Boolean] writer_validation
18
+ # @param [Boolean] reader_validation
19
+ # @return [void]
20
+ def add_member(autonym, pattern=ANYTHING, default_value: nil, default_proc: nil, must: false, writer_validation: true, reader_validation: false, &adjuster)
33
21
  _check_frozen
34
22
  _check_closed
35
23
 
36
- options = ADD_MEMBER_OptArg.parse(options)
24
+ raise ArgumentError if !default_value.nil? && default_proc
25
+
37
26
  autonym = autonym.to_sym # First definition for an autonym
38
27
 
39
28
  raise ArgumentError, %Q!already exist name "#{autonym}"! if member?(autonym)
@@ -41,21 +30,21 @@ class Striuct
41
30
  _check_safety_naming(autonym)
42
31
  _add_autonym(autonym)
43
32
 
44
- _attributes_for(autonym).safety_setter = !!options.setter_validation
45
- _attributes_for(autonym).safety_getter = !!options.getter_validation
33
+ _attributes_for(autonym).safety_setter = writer_validation
34
+ _attributes_for(autonym).safety_getter = reader_validation
46
35
 
47
- if options.must
36
+ if must
48
37
  _attributes_for(autonym).must = true
49
38
  end
50
39
 
51
40
  _def_getter(autonym)
52
- _def_setter(autonym, condition, &adjuster)
41
+ _def_setter(autonym, pattern, &adjuster)
53
42
 
54
43
  case
55
- when options.default_value?
56
- set_default_value(autonym, options.default_value)
57
- when options.default_proc?
58
- set_default_value(autonym, &options.default_proc)
44
+ when !default_value.nil?
45
+ set_default_value(autonym, default_value)
46
+ when default_proc
47
+ set_default_value(autonym, &default_proc)
59
48
  end
60
49
 
61
50
  nil
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'optionalargument'
4
-
5
3
  require_relative 'hashdeepdupulicatable'
6
4
  require_relative 'attributes'
7
5
  require_relative 'inner'
@@ -37,7 +37,7 @@ class Striuct
37
37
  value = @db[autonym]
38
38
 
39
39
  if with_safety_getter?(autonym) && !accept?(autonym, value)
40
- raise ::Validation::InvalidReadingError,
40
+ raise InvalidReadingError,
41
41
  "#{value.inspect} is deficient for #{autonym} in #{self.class}"
42
42
  end
43
43
 
@@ -1,21 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
4
- require 'keyvalidatable'
5
-
6
3
  class Striuct
7
4
  module InstanceMethods
8
5
  extend Forwardable
9
6
 
10
7
  # hide Forwardable's public/protected class_macro
11
8
  private_class_method(*Forwardable.instance_methods)
12
-
13
- include KeyValidatable
14
9
  end
15
10
  end
16
11
 
17
12
  require_relative 'delegate_class_methods'
18
- require_relative 'keyvalidatable'
19
13
  require_relative 'object'
20
14
  require_relative 'compare'
21
15
  require_relative 'to_s'
@@ -9,7 +9,7 @@ class Striuct
9
9
  def []=(key, value)
10
10
  autonym = autonym_for_key(key)
11
11
  _set(autonym, value)
12
- rescue Validation::InvalidWritingError
12
+ rescue InvalidWritingError
13
13
  $!.set_backtrace(
14
14
  ["#{$!.backtrace[-1].sub(/[^:]+\z/) { '' }}in `[#{key.inspect}(#{autonym})]=': #{$!.message}", $!.backtrace[-1]]
15
15
  )
@@ -31,17 +31,17 @@ class Striuct
31
31
  begin
32
32
  value = instance_exec(value, &adjuster_for(autonym))
33
33
  rescue Exception
34
- raise ::Validation::InvalidAdjustingError
34
+ raise InvalidAdjustingError
35
35
  end
36
36
  end
37
37
 
38
38
  if with_safety_setter?(autonym) && !accept?(autonym, value)
39
- raise ::Validation::InvalidWritingError,
39
+ raise InvalidWritingError,
40
40
  "#{value.inspect} is deficient for #{autonym} in #{self.class}"
41
41
  end
42
42
 
43
43
  @db[autonym] = value
44
- rescue ::Validation::InvalidError
44
+ rescue InvalidValueError
45
45
  unless /in \[\]=/.match?(caller(2..2).first.slice(/([^:]+)\z/))
46
46
  $!.backtrace.delete_if { |s| /#{Regexp.escape(File.dirname(__FILE__))}/ =~ s }
47
47
  $!.backtrace.first.sub!(/([^:]+)\z/) { "in `#{autonym}='" }
@@ -4,6 +4,21 @@ class Striuct
4
4
  module InstanceMethods
5
5
  # @group Validation
6
6
 
7
+ # @param [Proc, Method, #===] pattern
8
+ # @param [Object] value
9
+ def _valid?(pattern, value)
10
+ !!(
11
+ case pattern
12
+ when Proc
13
+ instance_exec(value, &pattern)
14
+ when Method
15
+ pattern.call(value)
16
+ else
17
+ pattern === value
18
+ end
19
+ )
20
+ end
21
+
7
22
  # @param [Symbol, String, #to_sym, Integer, #to_int] key - name / index
8
23
  # @param value
9
24
  # true if passed under any condition
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'validation'
4
-
5
3
  class Striuct
6
4
  class << self
7
5
  alias_method :new_instance, :new
@@ -40,6 +38,20 @@ class Striuct
40
38
  }
41
39
  end
42
40
 
41
+ # Return `true` if given object is sufficient as an adjuster role
42
+ def adjustable?(object)
43
+ case object
44
+ when Proc
45
+ object.arity == 1
46
+ else
47
+ if object.respond_to?(:to_proc)
48
+ object.to_proc.arity == 1
49
+ else
50
+ false
51
+ end
52
+ end
53
+ end
54
+
43
55
  private
44
56
 
45
57
  def inherited(subclass)
@@ -48,7 +60,7 @@ class Striuct
48
60
  subclass.class_eval {
49
61
  extend ClassMethods
50
62
  include Enumerable
51
- include Validation
63
+ extend Eqq::Buildable
52
64
  include InstanceMethods
53
65
 
54
66
  _init
metadata CHANGED
@@ -1,75 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: striuct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenichi Kamiya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-03 00:00:00.000000000 Z
11
+ date: 2021-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: validation
14
+ name: eqq
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.2
19
+ version: 0.0.5
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 0.3.0
22
+ version: 0.1.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 0.2.2
29
+ version: 0.0.5
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.3.0
33
- - !ruby/object:Gem::Dependency
34
- name: optionalargument
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: 0.5.1
40
- - - "<"
41
- - !ruby/object:Gem::Version
42
- version: 0.6.0
43
- type: :runtime
44
- prerelease: false
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 0.5.1
50
- - - "<"
51
- - !ruby/object:Gem::Version
52
- version: 0.6.0
53
- - !ruby/object:Gem::Dependency
54
- name: keyvalidatable
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - ">="
58
- - !ruby/object:Gem::Version
59
- version: 0.2.0
60
- - - "<"
61
- - !ruby/object:Gem::Version
62
- version: 0.3.0
63
- type: :runtime
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - ">="
68
- - !ruby/object:Gem::Version
69
- version: 0.2.0
70
- - - "<"
71
- - !ruby/object:Gem::Version
72
- version: 0.3.0
32
+ version: 0.1.0
73
33
  description: " Struct + validation + inheritable + default_value + etc...\n"
74
34
  email:
75
35
  - kachick1+ruby@gmail.com
@@ -80,6 +40,7 @@ files:
80
40
  - MIT-LICENSE.txt
81
41
  - README.md
82
42
  - lib/striuct.rb
43
+ - lib/striuct/bootstrap.rb
83
44
  - lib/striuct/classmethods/README.md
84
45
  - lib/striuct/classmethods/adjustment.rb
85
46
  - lib/striuct/classmethods/attributes.rb
@@ -107,7 +68,6 @@ files:
107
68
  - lib/striuct/instancemethods/enum.rb
108
69
  - lib/striuct/instancemethods/getter.rb
109
70
  - lib/striuct/instancemethods/hashy.rb
110
- - lib/striuct/instancemethods/keyvalidatable.rb
111
71
  - lib/striuct/instancemethods/lock.rb
112
72
  - lib/striuct/instancemethods/object.rb
113
73
  - lib/striuct/instancemethods/requirements.rb
@@ -116,7 +76,6 @@ files:
116
76
  - lib/striuct/instancemethods/to_s.rb
117
77
  - lib/striuct/instancemethods/validation.rb
118
78
  - lib/striuct/instancemethods/values.rb
119
- - lib/striuct/requirements.rb
120
79
  - lib/striuct/singleton_class.rb
121
80
  - lib/striuct/structs.rb
122
81
  homepage: https://github.com/kachick/striuct
@@ -142,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
101
  - !ruby/object:Gem::Version
143
102
  version: '0'
144
103
  requirements: []
145
- rubygems_version: 3.1.4
104
+ rubygems_version: 3.2.15
146
105
  signing_key:
147
106
  specification_version: 4
148
107
  summary: Struct++
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Striuct
4
- module InstanceMethods
5
- KeyValidatable.instance_methods.each do |feature|
6
- if specific_feature = feature.to_s.sub!('members') { 'autonyms' }
7
- def_delegator :self, feature, specific_feature.to_sym
8
- end
9
- end
10
- end
11
- end