activefacts-api 1.9.10 → 1.9.13

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
- 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: []