activefacts-api 1.9.10 → 1.9.13

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
- SHA1:
3
- metadata.gz: b2ae2f52c3b4809d9032158fab55e93634e6bb6f
4
- data.tar.gz: 9da905e8331bf238bc7d4aebd1dc556181cc24b8
2
+ SHA256:
3
+ metadata.gz: 8c3ae722ceb4f264e163be7c166507f6ab3ab328cea1513ff0599ea0c54a3270
4
+ data.tar.gz: '096701429372fe651503a58c4631c0f6090f21493555a3c2705ec2cbd71c1f04'
5
5
  SHA512:
6
- metadata.gz: 8c5ab2949f5a5767f9e3eaa1951bbbe0de21bcbd2bb5a3469f127f17cae9ddbbfe0f5d184bcb6fcd6bd0d8a68cb80b683bb7abacf4e1dac3d0d2f33a77d3e0b5
7
- data.tar.gz: d83db68561b25300a0ef71b753c0e983db8aacf35b6a7f0c48f5880772150801a4f7fcfc7e4ef1f90b4cbc361f3c9434c97cfa64bf72c621401961ce12c5c459
6
+ metadata.gz: cbb093b3faaa2c8f31e5c9f33c6afd076e3d72e803beb57272eb6769e6a44af9a98c909f9643c5d08da3f9fe0e0815ed76b90cecd9de524a6453497485d79346
7
+ data.tar.gz: 8f349dca05234d1b24c2408eb81ee5fbc3d0a3458021c099374cf4da6118c349d7dbc32c5e82a86c462da06acb878f6de8ab1f43a8de58cdcced608ec8b79979
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = ActiveFacts::API::VERSION
9
9
  spec.authors = ["Clifford Heath"]
10
10
  spec.email = ["clifford.heath@gmail.com"]
11
- spec.date = "2015-10-02"
11
+ spec.date = "2022-06-15"
12
12
 
13
13
  spec.summary = "A fact-based data model DSL and API"
14
14
  spec.description = %q{
@@ -35,7 +35,7 @@ over the fact population.
35
35
  spec.add_runtime_dependency 'tracing', ["~> 2", ">= 2.0.4"]
36
36
 
37
37
  spec.add_development_dependency "bundler", ">= 1.10"
38
- spec.add_development_dependency "rake", "~> 10.0"
38
+ spec.add_development_dependency "rake", ">= 10"
39
39
  spec.add_development_dependency "rspec", "~> 3.3"
40
40
  end
41
41
 
@@ -65,7 +65,7 @@ module ActiveFacts
65
65
  # With no parameters, return the collection of all instances of that object_type.
66
66
  # With parameters, assert an instance of the object_type identified by the values passed as args.
67
67
  def method_missing(m, *args, &b)
68
- klass = @vocabulary.const_get(m)
68
+ klass = @vocabulary.const_get(m) rescue nil # Catch missing lower-case names (wrong constant) and use super
69
69
  if invalid_object_type klass
70
70
  super
71
71
  else
@@ -75,7 +75,8 @@ module ActiveFacts
75
75
  end
76
76
 
77
77
  def define_class_accessor m, klass
78
- singleton_class.send(:define_method, m) do |*args|
78
+ singleton_class.
79
+ send(:define_method, m) do |*args|
79
80
  if args.size == 0
80
81
  # Return the collection of all instances of this class in the constellation:
81
82
  instances[klass]
@@ -32,9 +32,9 @@ module ActiveFacts
32
32
  end
33
33
 
34
34
  def initialize_existential_roles(klass, arg_hash)
35
- # If overrides_identification_of, assign those attributes too (recursively)
36
- if o = klass.overrides_identification_of
37
- initialize_existential_roles(o, arg_hash)
35
+ # Assign the identifying attributes of all superclasses first
36
+ klass.supertypes_transitive.each do |supertype|
37
+ initialize_existential_roles(supertype, arg_hash)
38
38
  end
39
39
 
40
40
  irns = klass.identifying_role_names
@@ -159,9 +159,9 @@ module ActiveFacts
159
159
  # identified by this entity. Save the current key and
160
160
  # class for each such instance.
161
161
  # This function is transitive!
162
- def analyse_impacts role
163
- impacts = []
164
- impacted_roles = []
162
+ def collect_instance_index_updates role
163
+ instance_index_updates = []
164
+ propagation_roles = []
165
165
 
166
166
  # Consider the object itself and all its supertypes
167
167
  ([self.class]+self.class.supertypes_transitive).map do |supertype|
@@ -169,7 +169,7 @@ module ActiveFacts
169
169
 
170
170
  old_key = identifying_role_values(supertype)
171
171
  # puts "Need to reindex #{self.class} as #{supertype} from #{old_key.inspect}"
172
- impacts << [constellation.instances[supertype], self, old_key]
172
+ instance_index_updates << [constellation.instances[supertype], self, old_key]
173
173
 
174
174
  supertype.
175
175
  all_role.
@@ -178,29 +178,29 @@ module ActiveFacts
178
178
  next unless counterpart = propagation_role.counterpart # And the role is not unary
179
179
  if counterpart.is_identifying # This object identifies another
180
180
  # puts "Changing #{propagation_role.inspect} affects #{counterpart.inspect}"
181
- impacted_roles << propagation_role
181
+ propagation_roles << propagation_role
182
182
  else
183
183
  next if counterpart.unique # But a one-to-many
184
184
  next unless value = send(propagation_role.getter) # A value is set
185
185
  role_values = value.send(counterpart.getter) # This is the index we have to change
186
186
  # puts "Changing #{role.inspect} of a #{self.class} requires updating #{propagation_role.counterpart.inspect}"
187
- impacts << [role_values, self, old_key]
187
+ instance_index_updates << [role_values, self, old_key]
188
188
  end
189
189
  end
190
190
  end
191
191
 
192
- impacted_roles.each do |role|
192
+ propagation_roles.each do |role|
193
193
  affected_instances = Array(send(role.getter))
194
194
  # puts "considering #{affected_instances.size} #{role.object_type.name} instances that include #{role.inspect}: #{affected_instances.map(&:identifying_role_values).inspect}"
195
195
  affected_instances.each do |counterpart|
196
- impacts.concat(counterpart.analyse_impacts(role.counterpart))
196
+ instance_index_updates.concat(counterpart.collect_instance_index_updates(role.counterpart))
197
197
  end
198
198
  end
199
- impacts
199
+ instance_index_updates
200
200
  end
201
201
 
202
- def apply_impacts impacts
203
- impacts.each do |index, entity, old_key|
202
+ def apply_instance_index_updates instance_index_updates
203
+ instance_index_updates.each do |index, entity, old_key|
204
204
  new_key = entity.identifying_role_values(index.object_type)
205
205
  # puts "Reindexing #{klass} from #{old_key.inspect} to #{new_key.inspect}"
206
206
 
@@ -390,6 +390,7 @@ module ActiveFacts
390
390
  unless role.is_identifying && role.object_type == self
391
391
  value =
392
392
  if v == nil
393
+ raise "nil value passed for mandatory #{role.name} of #{role.object_type.name}" if role.mandatory
393
394
  nil
394
395
  elsif role.unary?
395
396
  (v && true) # Preserve nil and false
@@ -465,7 +466,7 @@ module ActiveFacts
465
466
 
466
467
  def other.new_instance constellation, *args
467
468
  instance = allocate
468
- instance.instance_variable_set(@@constellation_variable_name ||= "@constellation", constellation)
469
+ instance.instance_variable_set(constellation_variable_name, constellation)
469
470
  instance.send(:initialize, *args)
470
471
  instance
471
472
  end
@@ -1,11 +1,13 @@
1
1
  require 'delegate'
2
2
  require 'securerandom'
3
3
 
4
- def SecureRandom.format_uuid hex32
5
- hex32.sub(
6
- @@format_pattern ||= /(........)(....)(....)(....)(............)/,
7
- @@format_string ||= '\1-\2-\3-\4-\5'
8
- )
4
+ module SecureRandom
5
+ def self.format_uuid hex32
6
+ hex32.sub(
7
+ @@format_pattern ||= /(........)(....)(....)(....)(............)/,
8
+ @@format_string ||= '\1-\2-\3-\4-\5'
9
+ )
10
+ end
9
11
  end
10
12
 
11
13
  unless defined? SecureRandom.uuid
@@ -26,6 +26,10 @@ module ActiveFacts
26
26
  end
27
27
  end
28
28
 
29
+ def constellation_variable_name
30
+ @@constellation_variable_name ||= "@constellation"
31
+ end
32
+
29
33
  def is_a? klass
30
34
  super || self.class.supertypes_transitive.include?(klass)
31
35
  end
@@ -77,14 +81,14 @@ module ActiveFacts
77
81
  # The counterpart roles get cleared automatically.
78
82
  klasses = [self.class]+self.class.supertypes_transitive
79
83
 
80
- irvrvs = {} # identifying_role_values by RoleValues
84
+ key_by_type = {}
81
85
  self.class.all_role_transitive.each do |_, role|
82
86
  next unless role.counterpart and
83
87
  role.unique and
84
88
  !role.counterpart.unique and
85
89
  counterpart = send(role.getter)
86
90
  role_values = counterpart.send(role.counterpart.getter)
87
- irvrvs[role_values] = role_values.index_values(self)
91
+ key_by_type[role.object_type] ||= identifying_role_values(role.object_type)
88
92
  end
89
93
 
90
94
  # Nullify the counterpart role of objects we identify first, before damaging our identifying_role_values:
@@ -124,7 +128,7 @@ module ActiveFacts
124
128
  counterpart_instance.send(counterpart.setter, nil, false)
125
129
  else
126
130
  rv = counterpart_instance.send(role.counterpart.getter)
127
- rv.delete_instance(self, irvrvs[rv])
131
+ rv.delete_instance(self, key_by_type[role.object_type])
128
132
 
129
133
  if (rv.empty? && !counterpart_instance.class.is_entity_type)
130
134
  counterpart_instance.retract if counterpart_instance.plays_no_role
@@ -158,6 +162,10 @@ module ActiveFacts
158
162
  module ClassMethods #:nodoc:
159
163
  include ObjectType
160
164
  # Add Instance class methods here
165
+
166
+ def constellation_variable_name
167
+ @@constellation_variable_name ||= "@constellation"
168
+ end
161
169
  end
162
170
  end
163
171
  end
@@ -62,7 +62,9 @@ class Decimal < SimpleDelegator #:nodoc:
62
62
  include ActiveFacts::API::SimpleDelegation
63
63
 
64
64
  def delegate_new(v)
65
- if v.is_a?(BigDecimal) || v.is_a?(Bignum)
65
+ if RUBY_VERSION >= "3"
66
+ BigDecimal(v)
67
+ elsif v.is_a?(BigDecimal) || v.is_a?(Integer)
66
68
  BigDecimal.new(v.to_s)
67
69
  else
68
70
  BigDecimal.new(v)
@@ -260,16 +260,16 @@ module ActiveFacts
260
260
 
261
261
  if role.is_identifying and (options&CHECKED_IDENTIFYING_ROLE) == 0
262
262
  check_identification_change_legality(role, value)
263
- impacts = analyse_impacts(role)
263
+ instance_index_updates = collect_instance_index_updates(role)
264
264
  end
265
265
 
266
266
  instance_variable_set(role.variable, value)
267
267
 
268
- if impacts
268
+ if instance_index_updates
269
269
  @constellation.when_admitted do
270
270
  # REVISIT: Consider whether we want to provide a way to find all instances
271
271
  # playing/not playing this boolean role, analogous to true.all_thing_as_role_name...
272
- apply_impacts(impacts) # Propagate dependent key changes
272
+ apply_instance_index_updates(instance_index_updates) # Propagate dependent key changes
273
273
  end
274
274
  end
275
275
 
@@ -314,7 +314,7 @@ module ActiveFacts
314
314
  check_identification_change_legality(role, value)
315
315
 
316
316
  # puts "Starting to analyse impact of changing 1-1 #{role.inspect} to #{value.inspect}"
317
- impacts = analyse_impacts(role)
317
+ instance_index_updates = collect_instance_index_updates(role)
318
318
  end
319
319
 
320
320
  instance_variable_set(role_var, value)
@@ -328,7 +328,7 @@ module ActiveFacts
328
328
  # Assign self to the new counterpart
329
329
  value.send(role.counterpart.setter, self, options) if value && (options&SKIP_MUTUAL_PROPAGATION) == 0
330
330
 
331
- apply_impacts(impacts) if impacts # Propagate dependent key changes
331
+ apply_instance_index_updates(instance_index_updates) if instance_index_updates # Propagate dependent key changes
332
332
  end
333
333
 
334
334
  unless @constellation.loggers.empty? or options != 0
@@ -363,12 +363,12 @@ module ActiveFacts
363
363
  check_identification_change_legality(role, value)
364
364
 
365
365
  # puts "Starting to analyse impact of changing 1-N #{role.inspect} to #{value.inspect}"
366
- impacts = analyse_impacts(role)
366
+ instance_index_updates = collect_instance_index_updates(role)
367
367
  end
368
368
 
369
369
  if old and (options&SKIP_MUTUAL_PROPAGATION) == 0
370
370
  old_role_values = old.send(getter = role.counterpart.getter)
371
- old_key = old_role_values.index_values(self)
371
+ old_key = identifying_role_values(role.object_type)
372
372
  end
373
373
 
374
374
  instance_variable_set(role_var, value)
@@ -388,7 +388,7 @@ module ActiveFacts
388
388
  rv.add_instance(self, identifying_role_values(role.object_type))
389
389
  end
390
390
 
391
- apply_impacts(impacts) if impacts # Propagate dependent key changes
391
+ apply_instance_index_updates(instance_index_updates) if instance_index_updates # Propagate dependent key changes
392
392
  end
393
393
 
394
394
  unless @constellation.loggers.empty? or options != 0
@@ -11,6 +11,7 @@ module ActiveFacts
11
11
  attr_accessor :role
12
12
  attr_accessor :sort
13
13
  attr_accessor :index_roles
14
+
14
15
  def object_type
15
16
  @role.object_type
16
17
  end
@@ -21,7 +22,11 @@ module ActiveFacts
21
22
  @sort = API::sorted
22
23
  @excluded_role = excluded_role
23
24
  @a = @sort ? RBTree.new : []
24
- (@index_roles = role.object_type.identifying_roles.dup).delete_at(@excluded_role) if @excluded_role
25
+ if @excluded_role
26
+ @index_roles = role.object_type.identifying_roles.dup
27
+ @index_roles.delete_at(@excluded_role)
28
+ @index_roles.freeze
29
+ end
25
30
  end
26
31
 
27
32
  def +(a)
@@ -68,17 +73,19 @@ module ActiveFacts
68
73
  KeyArray.new(a)
69
74
  end
70
75
 
76
+ # Return the full key for the object according to the object_type of this role
71
77
  def index_values object
72
- if @index_roles
73
- @index_roles.map{|r|
78
+ if @excluded_role
79
+ @index_roles.map do |r|
74
80
  role_value = object.send(r.name)
75
81
  role_value.identifying_role_values((c = r.counterpart) ? c.object_type : role_value.class)
76
- }
82
+ end
77
83
  else
78
- object.identifying_role_values
84
+ object.identifying_role_values(role.object_type)
79
85
  end
80
86
  end
81
87
 
88
+ # The key must include the excluded role, if any
82
89
  def add_instance(value, key)
83
90
  if @sort
84
91
  # Exclude the excluded role, if any:
@@ -89,9 +96,12 @@ module ActiveFacts
89
96
  end
90
97
  end
91
98
 
99
+ # The key must include the excluded role, if any
92
100
  def delete_instance(value, key)
93
101
  if @sort
94
- # Exclude the excluded role, if any:
102
+ if key.size != role.object_type.identifying_roles.size
103
+ raise "Internal error: incorrectly-sized key #{key.inspect} to delete_instance"
104
+ end
95
105
  (key = key.dup).delete_at(@excluded_role) if @excluded_role
96
106
  deleted = @a.delete(form_key(key))
97
107
  else
@@ -134,16 +144,16 @@ module ActiveFacts
134
144
  def_single_delegator :@a, :empty?
135
145
  def_single_delegator :@a, :include?
136
146
  def_single_delegator :@a, :inject, 2
137
- def_single_delegator :@a, :select, -1, 1
138
- def_single_delegator :@a, :reject, -1, 1
147
+ def_single_delegator :@a, :select, -2, 1
148
+ def_single_delegator :@a, :reject, -2, 1
139
149
  def_single_delegator :@a, :size
140
- def_single_delegator :@a, :sort_by, -1, 1
150
+ def_single_delegator :@a, :sort_by, -2, 1
141
151
  def_single_delegator :@a, :to_a
142
152
  def_single_delegator :@a, :-
143
153
  # These delegators allow a negative arity in RSpec because the tests test it (to make sure the code doesn't pass too many args)
144
- def_single_delegator :@a, :each, *([-1, 1] + Array(defined?(::RSpec) ? -2 : nil))
154
+ def_single_delegator :@a, :each, *([-2, 1] + Array(defined?(::RSpec) ? -2 : nil))
145
155
  def_single_delegator :@a, :detect, 1, *([-1, 1] + Array(defined?(::RSpec) ? -2 : nil))
146
- def_single_delegator :@a, :map, -1, 1
156
+ def_single_delegator :@a, :map, -2, 1
147
157
  end
148
158
  end
149
159
  end
@@ -17,7 +17,7 @@ module ActiveFacts
17
17
  module ValueClass #:nodoc:
18
18
  def value_type *args, &block #:nodoc:
19
19
  # The inclusion of instance methods triggers ClassMethods to be included in the class too
20
- include ActiveFacts::API::Value
20
+ include ::ActiveFacts::API::Value
21
21
  value_type(*args, &block)
22
22
  end
23
23
  end
@@ -11,12 +11,6 @@ unless Object.const_defined?("Infinity")
11
11
  Infinity = 1.0/0.0
12
12
  end
13
13
 
14
- class Symbol #:nodoc:
15
- def to_proc
16
- Proc.new{|*args| args.shift.__send__(self, *args)}
17
- end
18
- end
19
-
20
14
  class String #:nodoc:
21
15
  # This may be overridden by a version from ActiveSupport. For our purposes, either will work.
22
16
  def camelcase(first_letter = :upper)
@@ -155,7 +155,7 @@ module ActiveFacts
155
155
  class << klass
156
156
  def new_instance constellation, *args
157
157
  instance = allocate
158
- instance.instance_variable_set(@@constellation_variable_name ||= "@constellation", constellation)
158
+ instance.instance_variable_set(constellation_variable_name, constellation)
159
159
  instance.send(:initialize, *args)
160
160
  instance
161
161
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveFacts
2
2
  module API
3
- VERSION = "1.9.10"
3
+ VERSION = "1.9.13"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activefacts-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.10
4
+ version: 1.9.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clifford Heath
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-02 00:00:00.000000000 Z
11
+ date: 2022-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbtree-pure
@@ -68,16 +68,16 @@ dependencies:
68
68
  name: rake
69
69
  requirement: !ruby/object:Gem::Requirement
70
70
  requirements:
71
- - - "~>"
71
+ - - ">="
72
72
  - !ruby/object:Gem::Version
73
- version: '10.0'
73
+ version: '10'
74
74
  type: :development
75
75
  prerelease: false
76
76
  version_requirements: !ruby/object:Gem::Requirement
77
77
  requirements:
78
- - - "~>"
78
+ - - ">="
79
79
  - !ruby/object:Gem::Version
80
- version: '10.0'
80
+ version: '10'
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: rspec
83
83
  requirement: !ruby/object:Gem::Requirement
@@ -139,7 +139,7 @@ homepage: https://github.com/cjheath/activefacts-api
139
139
  licenses:
140
140
  - MIT
141
141
  metadata: {}
142
- post_install_message:
142
+ post_install_message:
143
143
  rdoc_options: []
144
144
  require_paths:
145
145
  - lib
@@ -154,9 +154,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
154
  - !ruby/object:Gem::Version
155
155
  version: '0'
156
156
  requirements: []
157
- rubyforge_project:
158
- rubygems_version: 2.4.5
159
- signing_key:
157
+ rubygems_version: 3.2.22
158
+ signing_key:
160
159
  specification_version: 4
161
160
  summary: A fact-based data model DSL and API
162
161
  test_files: []