modeling 0.0.5 → 0.1.1

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: e3cc5b79ca0d36340e35381ab51d1b4d09486812bb8479267128a557e0130c01
4
- data.tar.gz: b8ff810f7317108cbf1b8ef7290355041a8d29d20ecb3a57ad47f66fd3edc2f2
3
+ metadata.gz: b86aef2212da331d45efd4c2d32352647c876f25f4379772496398c3880c2af6
4
+ data.tar.gz: 8def3789e08b6f41a3a7c72df81f4e967f95e8e37eb4412d6578ba66a943b654
5
5
  SHA512:
6
- metadata.gz: 6044d7ac29c9b23834aa7a848dc10c11430be05262bcaab38ad5417ee7a605d515a1d66bce01f6ff639750e566826856e39ed4aa46a33ffb26f36b71011970bb
7
- data.tar.gz: 3a94d368fc0e022e2aaffccfb10247cfab48a7df9da53150a7a618b21cac7c529dbe906cd8c36169831dd499a9db93e586947147528ec4d17aba67260eb15341
6
+ metadata.gz: d6787537af7b26e954b46fca5ab1bdb3787bf6d0b411462a3dc866eb604328dc881ccb65b1b177957d47be721a53ec63cf5a598a64293c665a228e5dcf6acdc6
7
+ data.tar.gz: 1648de4591f2f127ad829e8e0a490ef6600f1fae0467534d9104286978b50c04cc3a4ff1be382fc2ffc7390e9822e026c2987f16704a047a14778aaa75f16545
@@ -1,23 +1,27 @@
1
1
  module Modeling
2
+ class Exception < ::Exception
3
+ end
4
+
2
5
  class ModelField
3
- def initialize name, filter, create_attr, writer, reader, tester
6
+ def initialize name, initialize_argument, instance_variable, writer, reader, tester
4
7
  @name = name
5
- @filter = filter
6
- @create_attr = create_attr
8
+ @initialize_argument = initialize_argument
9
+ @instance_variable = instance_variable
7
10
  @writer = writer
8
11
  @reader = reader
9
12
  @tester = tester
13
+ @instance_variable_name = "@#{name}".to_sym
10
14
  end
11
15
 
12
16
  attr :name
13
- attr :filter
17
+ attr :instance_variable_name
14
18
 
15
- def attribute_name
16
- "@#{name}"
19
+ def initialize_argument?
20
+ @initialize_argument
17
21
  end
18
22
 
19
- def create_attr?
20
- @create_attr
23
+ def instance_variable?
24
+ @instance_variable
21
25
  end
22
26
 
23
27
  def writer?
@@ -37,52 +41,43 @@ module Modeling
37
41
  case argument
38
42
  when ModelField
39
43
  argument
40
- when Symbol
41
- from_symbol argument, filter
42
- when String
43
- from_string argument, filter
44
- when Array
45
- from_array argument, filter
46
- when Hash
47
- from_hash argument
44
+ when Symbol, String
45
+ parse_model_field argument
48
46
  else
49
- raise "Unsupported argument #{argument}"
47
+ raise Exception.new "Unsupported argument #{argument} of #{argument.class} class."
50
48
  end
51
49
  end
52
50
 
53
- def from_symbol argument, filter
54
- at = argument.start_with? "@"
55
- bang = argument.end_with? "!"
56
- hook = argument.end_with? "?"
57
- rail = argument.end_with? "="
58
- bald = !(at || bang || hook || rail)
59
- name = argument.to_s[/\w+/].to_sym
60
- ModelField.new name, filter, bald || hook || at || rail, bald || rail, bald || hook, false
61
- end
62
-
63
- def from_string argument, filter
64
- if argument =~ /(\w+)\s*(:?\/([traw\s]*))/
65
- ModelField.new $1.to_sym, filter, $2.include?("a"), $2.include?("w"), $2.include?("r"), $2.include?("t")
66
- else
67
- raise "Invalid argument string format '#{argument}'"
51
+ def parse_model_field argument
52
+ initialize_argument = instance_variable = reader = writer = tester = false
53
+ name_start = (0...argument.length).each do |i|
54
+ case a = argument[i]
55
+ when "R" then reader = true
56
+ when "W" then writer = true
57
+ when "T" then tester = true
58
+ when "V" then instance_variable = true
59
+ when "A" then initialize_argument = true
60
+ when "@" then instance_variable = initialize_argument = true
61
+ when "_" then break i + 1
62
+ else
63
+ if a.upcase != a
64
+ break i
65
+ else raise Exception.new "Invalid model field '#{argument}' - unknown option '#{a}'"
66
+ end
67
+ end
68
+ end
69
+ case name_start
70
+ when 0
71
+ initialize_argument = instance_variable = reader = writer = true
72
+ name = argument
73
+ when Integer
74
+ name = argument[name_start..]
75
+ else raise Exception.new "Invalid model field '#{argument}' - field name is missing"
68
76
  end
69
- end
70
-
71
- def from_array argument, filter
72
- name = argument.shift.to_sym
73
- ModelField.new name, filter, argument.include?(:attr), argument.include?(:writer),
74
- argument.include?(:reader), argument.include?(:tester)
75
- end
76
77
 
77
- def from_hash argument
78
- name = argument[:name] || argument.keys.first
79
- filter = argument[:filter] || argument[name]
80
- parsed = parse name, filter
81
- ModelField.new parsed.name, parsed.filter, argument[:attr] || parsed.create_attr?,
82
- argument[:writer] || parsed.writer?, argument[:reader] || parsed.reader?,
83
- argument[:tester] || parsed.tester?
78
+ raise Exception.new "Invalid model field #{argument} - field name '#{name}' is invalid" unless name =~ /\w+/
79
+ ModelField.new name.to_sym, initialize_argument, instance_variable, writer, reader, tester
84
80
  end
85
-
86
81
  end
87
82
  end
88
83
  end
@@ -4,59 +4,53 @@ module Modeling
4
4
 
5
5
  attr_accessor :model_fields
6
6
 
7
- def model *fields, **filtered_fields, &initializer
8
- self.model_fields = model_fields = fields.map{ ModelField.parse _1 } +
9
- filtered_fields.map{ ModelField.parse _1, _2 }
7
+ def model *fields, &initializer
8
+ self.model_fields = model_fields = fields.map{ ModelField.parse _1 }
10
9
  define_initialize self, &initializer
11
- model_fields.each do |f|
12
- attr_writer f.name if f.writer?
13
- attr_reader f.name if f.reader?
14
- attr_tester f.name if f.tester?
10
+ model_fields.each do |field|
11
+ attr_writer field.name if field.writer?
12
+ attr_reader field.name if field.reader?
13
+ attr_tester "#{field.name}?".to_sym, field.instance_variable_name if field.tester?
15
14
  end
16
15
  end
16
+
17
+ private
17
18
 
18
- def attr_tester symbol
19
- define_method "#{symbol}?" do
20
- !!instance_variable_get(symbol)
19
+ def attr_tester tester, instance_variable
20
+ define_method tester do
21
+ instance_variable_get(instance_variable) ? true : false
21
22
  end
22
23
  end
23
-
24
- private
25
24
 
26
- def self.model_arguments fields, *a, **na
27
- fields.zip(a).map do |f, arg|
28
- value = na.key?(f.name) ? na[f.name] : arg
29
- if !f.filter.nil? && !(f.filter === value)
30
- if f.filter.respond_to? :from
31
- value = f.filter.from value
32
- else
33
- raise ArgumentError.new "#{value}(#{value.class}) does not match #{f.filter}"
34
- end
35
- end
36
- [f.name, value]
25
+ def self.initialize_arguments fields, *a, **na
26
+ fields.filter(&:initialize_argument?).zip(a).map do |field, arg|
27
+ name = field.name
28
+ value = na.key?(name) ? na[name] : arg
29
+ [name, value]
37
30
  end.to_h
38
31
  end
39
32
 
40
33
  def define_initialize initializer_class, &initializer
41
34
  define_method :initialize do |*a, **na, &b|
42
35
  model_fields = initializer_class.model_fields
43
- model_arguments = Modeling.model_arguments model_fields, *a, **na
44
- super_call = proc do |*asc, **nasc, &bsc|
45
- if asc.empty? && nasc.empty? && !bsc
46
- super(*(a[model_arguments.size..] || []), **na.except(*model_arguments.keys), &b)
36
+ initialize_arguments = Modeling.initialize_arguments model_fields, *a, **na
37
+ super_initialize = proc do |*as, **nas, &bs|
38
+ if as.empty? && nas.empty? && !bs
39
+ super(*(a[initialize_arguments.size..] || []), **na.except(*initialize_arguments.keys), &b)
47
40
  else
48
- super(*asc, **nasc, &bsc)
41
+ super(*as, **nas, &bs)
49
42
  end
50
43
  end
51
- model_fields.each do |f|
52
- instance_variable_set f.attribute_name, model_arguments[f.name] if f.create_attr?
44
+ model_fields.each do |field|
45
+ if field.instance_variable?
46
+ instance_variable_set field.instance_variable_name, initialize_arguments[field.name]
47
+ end
53
48
  end
54
49
  if initializer
55
- instance_exec super_call, **model_arguments, &initializer
50
+ instance_exec super_initialize, **initialize_arguments, &initializer
56
51
  else
57
- super_call.call
52
+ super(*(a[initialize_arguments.size..] || []), **na.except(*initialize_arguments.keys), &b)
58
53
  end
59
54
  end
60
55
  end
61
-
62
56
  end
@@ -1,3 +1,3 @@
1
1
  module Modeling
2
- VERSION = "0.0.5"
2
+ VERSION = "0.1.1"
3
3
  end
metadata CHANGED
@@ -1,18 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: modeling
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Łukasz Pomietło
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-20 00:00:00.000000000 Z
11
+ date: 2024-12-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: " Enables writting class initializers and attribute accessors in one
14
- line. \n Struct class alternative. Keyword & positional arguments mixing. Optional
15
- initializer arguments filtering.\n"
13
+ description: "Adds the ability to quickly model classes. Definitions of instance variables
14
+ and access methods are reduced to one line. \nCreating an instance of the modeled
15
+ class is significantly slower (~20x), so its use for classes whose instances are
16
+ created frequently is not recommended.\n"
16
17
  email: oficjalnyadreslukasza@gmail.com
17
18
  executables: []
18
19
  extensions: []
@@ -43,7 +44,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
44
  - !ruby/object:Gem::Version
44
45
  version: '0'
45
46
  requirements: []
46
- rubygems_version: 3.5.6
47
+ rubygems_version: 3.5.23
47
48
  signing_key:
48
49
  specification_version: 4
49
50
  summary: A concise way to define the class shape