activefacts-api 1.9.5 → 1.9.6

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.
@@ -23,31 +23,31 @@ module ActiveFacts
23
23
 
24
24
  class InvalidEntityException < SchemaException
25
25
  def initialize klass
26
- super "#{klass.basename} may not be an entity type"
26
+ super "#{klass.basename} may not be an entity type"
27
27
  end
28
28
  end
29
29
 
30
30
  class InvalidIdentificationException < SchemaException
31
31
  def initialize object_type, role, is_single
32
- msg =
33
- if is_single
34
- "#{object_type} has a single identifying role '#{role}' which is has_one, but must be one_to_one"
35
- else
36
- "#{object_type} has an identifying role '#{role}' which is one_to_one, but must be has_one"
37
- end
38
- super msg
32
+ msg =
33
+ if is_single
34
+ "#{object_type} has a single identifying role '#{role}' which is has_one, but must be one_to_one"
35
+ else
36
+ "#{object_type} has an identifying role '#{role}' which is one_to_one, but must be has_one"
37
+ end
38
+ super msg
39
39
  end
40
40
  end
41
41
 
42
42
  class MissingIdentificationException < SchemaException
43
43
  def initialize klass
44
- super "You must list the roles which will identify #{klass.basename}"
44
+ super "You must list the roles which will identify #{klass.basename}"
45
45
  end
46
46
  end
47
47
 
48
48
  class InvalidObjectType < SchemaException
49
49
  def initialize vocabulary, klass, reason
50
- super "A constellation over #{vocabulary.name} cannot index instances of #{klass} because it #{reason}"
50
+ super "A constellation over #{vocabulary.name} cannot index instances of #{klass} because it #{reason}"
51
51
  end
52
52
  end
53
53
 
@@ -71,7 +71,7 @@ module ActiveFacts
71
71
 
72
72
  class UnexpectedIdentifyingValueException < RuntimeException
73
73
  def initialize object_type, identifying_role_names, extra_args
74
- super "#{object_type.basename} expects only (#{identifying_role_names*', '}) for its identifier, but you provided additional values #{extra_args.inspect}"
74
+ super "#{object_type.basename} expects only (#{identifying_role_names*', '}) for its identifier, but you provided additional values #{extra_args.inspect}"
75
75
  end
76
76
  end
77
77
 
@@ -92,14 +92,14 @@ module ActiveFacts
92
92
  # When an existing object having multiple identification patterns is re-asserted, all the keys must match the existing object
93
93
  class TypeConflictException < RuntimeException
94
94
  def initialize(klass, supertype, key, existing)
95
- super "#{klass} cannot be asserted to have #{supertype} identifier #{key.inspect} because the existing object has #{existing.inspect}"
95
+ super "#{klass} cannot be asserted to have #{supertype} identifier #{key.inspect} because the existing object has #{existing.inspect}"
96
96
  end
97
97
  end
98
98
 
99
99
  # When a new entity is asserted, but a supertype identifier matches an existing object of a different type, type migration is implied but unfortunately is impossible in Ruby
100
100
  class TypeMigrationException < RuntimeException
101
101
  def initialize(klass, supertype, key)
102
- super "#{klass} cannot be asserted due to the prior existence of a conflicting #{supertype} identified by #{key.inspect}"
102
+ super "#{klass} cannot be asserted due to the prior existence of a conflicting #{supertype} identified by #{key.inspect}"
103
103
  end
104
104
  end
105
105
 
@@ -13,7 +13,7 @@ module ActiveFacts
13
13
  # invariant { self.all_role.each {|role| self.is_a?(ObjectifiedFactType) ? role.counterpart.object_type == self.objectified_as : role.fact_type == self } }
14
14
 
15
15
  def initialize
16
- @all_role ||= []
16
+ @all_role ||= []
17
17
  end
18
18
  end
19
19
 
@@ -30,11 +30,11 @@ module ActiveFacts
30
30
  attr_reader :supertype_role, :subtype_role
31
31
 
32
32
  def initialize(supertype, subtype)
33
- super()
33
+ super()
34
34
 
35
- # The supertype role is not mandatory, but the subtype role is. Both are unique.
36
- @supertype_role = Role.new(self, supertype, subtype.name.gsub(/.*::/,'').to_sym, false, true)
37
- @subtype_role = Role.new(self, subtype, supertype.name.gsub(/.*::/,'').to_sym, true, true)
35
+ # The supertype role is not mandatory, but the subtype role is. Both are unique.
36
+ @supertype_role = Role.new(self, supertype, subtype.name.gsub(/.*::/,'').to_sym, false, true)
37
+ @subtype_role = Role.new(self, subtype, supertype.name.gsub(/.*::/,'').to_sym, true, true)
38
38
  end
39
39
  end
40
40
  end
@@ -24,17 +24,17 @@ class Guid
24
24
  if i == :new
25
25
  case @@sequence
26
26
  when 'fixed'
27
- @@counter ||= 0
28
- @value = SecureRandom.format_uuid('%032x' % (@@counter += 1))
27
+ @@counter ||= 0
28
+ @value = SecureRandom.format_uuid('%032x' % (@@counter += 1))
29
29
  when 'record'
30
- @@sequence_file ||= File.open(SEQ_FILE_NAME, 'w')
31
- @value = SecureRandom.uuid.freeze
32
- @@sequence_file.puts(@value)
30
+ @@sequence_file ||= File.open(SEQ_FILE_NAME, 'w')
31
+ @value = SecureRandom.uuid.freeze
32
+ @@sequence_file.puts(@value)
33
33
  when 'replay'
34
- @@sequence_file ||= File.open(SEQ_FILE_NAME, 'r')
35
- @value = @@sequence_file.gets.chomp
34
+ @@sequence_file ||= File.open(SEQ_FILE_NAME, 'r')
35
+ @value = @@sequence_file.gets.chomp
36
36
  else
37
- @value = SecureRandom.uuid.freeze
37
+ @value = SecureRandom.uuid.freeze
38
38
  end
39
39
  elsif (v = i.to_s).length == 36 and !(v !~ /[^0-9a-f]/i)
40
40
  @value = v.clone.freeze
@@ -68,7 +68,7 @@ class Guid
68
68
  to_s.eql?(o.to_s)
69
69
  end
70
70
 
71
- def <=>(o) #:nodoc:
71
+ def <=>(o) #:nodoc:
72
72
  to_s.<=>(o.to_s)
73
73
  end
74
74
 
@@ -15,10 +15,10 @@ module ActiveFacts
15
15
  unless (self.class.is_entity_type)
16
16
  begin
17
17
  super(*args)
18
- rescue TypeError => e
19
- if trace(:debug)
20
- p e; puts e.backtrace*"\n\t"; debugger; true
21
- end
18
+ rescue TypeError => e
19
+ if trace(:debug)
20
+ p e; puts e.backtrace*"\n\t"; debugger; true
21
+ end
22
22
  rescue ArgumentError => e
23
23
  e.message << " constructing a #{self.class}"
24
24
  raise
@@ -32,16 +32,16 @@ module ActiveFacts
32
32
 
33
33
  # List entities which have an identifying role played by this object.
34
34
  def related_entities(indirectly = true, instances = [])
35
- # Check all roles of this instance
35
+ # Check all roles of this instance
36
36
  self.class.all_role.each do |role_name, role|
37
- # If the counterpart role is not identifying for its object type, skip it
38
- next unless c = role.counterpart and c.is_identifying
39
-
40
- identified_instances = Array(self.send(role.getter))
41
- instances.concat(identified_instances)
42
- identified_instances.each do |instance|
43
- instance.related_entities(indirectly, instances) if indirectly
44
- end
37
+ # If the counterpart role is not identifying for its object type, skip it
38
+ next unless c = role.counterpart and c.is_identifying
39
+
40
+ identified_instances = Array(self.send(role.getter))
41
+ instances.concat(identified_instances)
42
+ identified_instances.each do |instance|
43
+ instance.related_entities(indirectly, instances) if indirectly
44
+ end
45
45
  end
46
46
  instances
47
47
  end
@@ -52,101 +52,106 @@ module ActiveFacts
52
52
 
53
53
  # De-assign all functional roles and remove from constellation, if any.
54
54
  def retract
55
- return unless constellation = @constellation
56
-
57
- unless constellation.loggers.empty?
58
- # An object may have multiple identifiers, with potentially overlapping role sets
59
- # Get one copy of each role to use in asserting the instance
60
- if self.class.is_entity_type
61
- identifying_role_values = {}
62
- ([self.class]+self.class.supertypes_transitive).each do |klass|
63
- klass.identifying_role_names.zip(identifying_role_values(klass)).each do |name, value|
64
- identifying_role_values[name] = value
65
- end
66
- end
67
- else
68
- identifying_role_values = self
69
- end
70
- end
55
+ return unless constellation = @constellation
56
+
57
+ unless constellation.loggers.empty?
58
+ # An object may have multiple identifiers, with potentially overlapping role sets
59
+ # Get one copy of each role to use in asserting the instance
60
+ if self.class.is_entity_type
61
+ identifying_role_values = {}
62
+ ([self.class]+self.class.supertypes_transitive).each do |klass|
63
+ klass.identifying_role_names.zip(identifying_role_values(klass)).each do |name, value|
64
+ identifying_role_values[name] = value
65
+ end
66
+ end
67
+ else
68
+ identifying_role_values = self
69
+ end
70
+ end
71
71
 
72
72
  # Delete from the constellation first, while we remember our identifying role values
73
73
  constellation.deindex_instance(self)
74
- instance_variable_set(@@constellation_variable_name ||= "@constellation", nil)
74
+ instance_variable_set(@@constellation_variable_name ||= "@constellation", nil)
75
75
 
76
76
  # Now, for all roles (from this class and all supertypes), assign nil to all functional roles
77
77
  # The counterpart roles get cleared automatically.
78
- klasses = [self.class]+self.class.supertypes_transitive
79
-
80
- irvrvs = {} # identifying_role_values by RoleValues
81
- self.class.all_role_transitive.each do |_, role|
82
- next unless role.counterpart and
83
- role.unique and
84
- !role.counterpart.unique and
85
- counterpart = send(role.getter)
86
- role_values = counterpart.send(role.counterpart.getter)
87
- irvrvs[role_values] = role_values.index_values(self)
88
- end
89
-
90
- # Nullify the counterpart role of objects we identify first, before damaging our identifying_role_values:
91
- klasses.each do |klass|
78
+ klasses = [self.class]+self.class.supertypes_transitive
79
+
80
+ irvrvs = {} # identifying_role_values by RoleValues
81
+ self.class.all_role_transitive.each do |_, role|
82
+ next unless role.counterpart and
83
+ role.unique and
84
+ !role.counterpart.unique and
85
+ counterpart = send(role.getter)
86
+ role_values = counterpart.send(role.counterpart.getter)
87
+ irvrvs[role_values] = role_values.index_values(self)
88
+ end
89
+
90
+ # Nullify the counterpart role of objects we identify first, before damaging our identifying_role_values:
91
+ klasses.each do |klass|
92
92
  klass.all_role.each do |role_name, role|
93
- next if role.unary?
94
- next if !(counterpart = role.counterpart).is_identifying
95
- next if role.fact_type.is_a?(TypeInheritanceFactType)
96
-
97
- counterpart_instances = send(role.getter)
98
- counterpart_instances.to_a.each do |counterpart_instance|
99
- # Allow nullifying non-mandatory roles, as long as they're not identifying.
100
- if counterpart.mandatory
101
- counterpart_instance.retract
102
- else
103
- counterpart_instance.send(counterpart.setter, nil, false)
104
- end
105
- end
106
- end
107
- end
108
-
109
- # Now deal with other roles:
110
- klasses.each do |klass|
93
+ next if role.unary?
94
+ next if !(counterpart = role.counterpart).is_identifying
95
+ next if role.fact_type.is_a?(TypeInheritanceFactType)
96
+
97
+ counterpart_instances = send(role.getter)
98
+ counterpart_instances.to_a.each do |counterpart_instance|
99
+ # Allow nullifying non-mandatory roles, as long as they're not identifying.
100
+ if counterpart.mandatory
101
+ counterpart_instance.retract
102
+ else
103
+ counterpart_instance.send(counterpart.setter, nil, false)
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ # Now deal with other roles:
110
+ klasses.each do |klass|
111
111
  klass.all_role.each do |role_name, role|
112
112
  next if role.unary?
113
113
  counterpart = role.counterpart
114
114
 
115
- # Objects being created do not have to have non-identifying mandatory roles,
116
- # so we allow retracting to the same state.
115
+ # Objects being created do not have to have non-identifying mandatory roles,
116
+ # so we allow retracting to the same state.
117
117
  if role.unique
118
- next if role.fact_type.is_a?(TypeInheritanceFactType)
119
- i = send(role.getter)
120
- next unless i
121
-
122
- if (counterpart.unique)
123
- # REVISIT: This will incorrectly fail to propagate a key change for a non-mandatory role
124
- i.send(counterpart.setter, nil, false)
125
- else
126
- rv = i.send(role.counterpart.getter)
127
- rv.delete_instance(self, irvrvs[rv])
128
-
129
- if (rv.empty? && !i.class.is_entity_type)
130
- i.retract if i.plays_no_role
131
- end
132
-
133
- end
134
- instance_variable_set(role.variable, nil)
118
+ next if role.fact_type.is_a?(TypeInheritanceFactType)
119
+ counterpart_instance = send(role.getter)
120
+ next unless counterpart_instance && counterpart_instance.constellation
121
+
122
+ if (counterpart.unique)
123
+ # REVISIT: This will incorrectly fail to propagate a key change for a non-mandatory role
124
+ counterpart_instance.send(counterpart.setter, nil, false)
125
+ else
126
+ rv = counterpart_instance.send(role.counterpart.getter)
127
+ rv.delete_instance(self, irvrvs[rv])
128
+
129
+ if (rv.empty? && !counterpart_instance.class.is_entity_type)
130
+ counterpart_instance.retract if counterpart_instance.plays_no_role
131
+ end
132
+
133
+ end
134
+ instance_variable_set(role.variable, nil)
135
135
  else
136
136
  # puts "Not removing role #{role_name} from counterpart RoleValues #{counterpart.name}"
137
137
  # Duplicate the array using to_a, as the RoleValues here will be modified as we traverse it:
138
- next if role.fact_type.is_a?(TypeInheritanceFactType)
139
- counterpart_instances = send(role.getter)
140
- counterpart_instances.to_a.each do |counterpart_instance|
141
- # This action deconstructs our RoleValues as we go:
142
- counterpart_instance.send(counterpart.setter, nil, false)
138
+ next if role.fact_type.is_a?(TypeInheritanceFactType)
139
+ counterpart_instances = send(role.getter)
140
+ counterpart_instances.to_a.each do |counterpart_instance|
141
+ next unless counterpart_instance.constellation
142
+ # This action deconstructs our RoleValues as we go:
143
+ if counterpart.mandatory
144
+ counterpart_instance.retract
145
+ else
146
+ counterpart_instance.send(counterpart.setter, nil, false)
147
+ end
143
148
  end
144
- instance_variable_set(role.variable, nil)
149
+ instance_variable_set(role.variable, nil)
145
150
  end
146
151
  end
147
152
  end
148
153
 
149
- constellation.loggers.each{|l| l.call(:retract, self.class, identifying_role_values) }
154
+ constellation.loggers.each{|l| l.call(:retract, self.class, identifying_role_values) }
150
155
 
151
156
  end
152
157
 
@@ -10,48 +10,48 @@ module ActiveFacts
10
10
  module API
11
11
  class KeyArray < Array
12
12
  def initialize(a)
13
- super(
14
- a.map do |e|
15
- if e.is_a?(Array) && e.class != self.class
16
- KeyArray.new(e)
17
- elsif e.eql?(nil)
18
- []
19
- else
20
- e
21
- end
22
- end
23
- )
13
+ super(
14
+ a.map do |e|
15
+ if e.is_a?(Array) && e.class != self.class
16
+ KeyArray.new(e)
17
+ elsif e.eql?(nil)
18
+ []
19
+ else
20
+ e
21
+ end
22
+ end
23
+ )
24
24
  end
25
25
 
26
26
  def inspect
27
- "KeyArray"+super
27
+ "KeyArray"+super
28
28
  end
29
29
 
30
30
  # This is used by RBTree for searching, and we need it to use eql? semantics to be like a Hash
31
31
  def ==(other)
32
- self.eql? other
32
+ self.eql? other
33
33
  end
34
34
 
35
35
  def <=>(other)
36
- unless other.is_a?(Array) # Any kind of Array, not just KeyArray
37
- return 1
38
- end
39
-
40
- 0.upto(size-1) do |i|
41
- diff = ((s = self[i]) <=> (o = other[i]) rescue nil)
42
- case diff
43
- when 0 # Same value, whether exactly the same class or not
44
- next
45
- when nil # Non-comparable values
46
- return -1 if s == nil # Ensure that nil values come before other values
47
- return 1 if o == nil
48
- diff = s.class.name <=> o.class.name # Otherwise just ensure stable sorting
49
- return diff if diff != 0
50
- else
51
- return diff
52
- end
53
- end
54
- 0
36
+ unless other.is_a?(Array) # Any kind of Array, not just KeyArray
37
+ return 1
38
+ end
39
+
40
+ 0.upto(size-1) do |i|
41
+ diff = ((s = self[i]) <=> (o = other[i]) rescue nil)
42
+ case diff
43
+ when 0 # Same value, whether exactly the same class or not
44
+ next
45
+ when nil # Non-comparable values
46
+ return -1 if s == nil # Ensure that nil values come before other values
47
+ return 1 if o == nil
48
+ diff = s.class.name <=> o.class.name # Otherwise just ensure stable sorting
49
+ return diff if diff != 0
50
+ else
51
+ return diff
52
+ end
53
+ end
54
+ 0
55
55
  end
56
56
  end
57
57
 
@@ -65,15 +65,15 @@ module ActiveFacts
65
65
 
66
66
  # Should be in module ForwardableWithArityChecking
67
67
  def self.def_single_delegator(accessor, method, *expected_arities)
68
- str = %{
69
- def #{method}(*args, &block)
70
- if #{expected_arities.size == 0 ? "block" : "!block || !#{expected_arities.inspect}.include?(block.arity)" }
71
- raise ArgumentError.new("Arity mismatch on #{name}\##{method}, got \#{block ? block.arity : 'none'} want #{expected_arities.inspect} at \#{caller*"\n\t"})")
72
- end
73
- #{accessor}.__send__(:#{method}, *args, &block)
74
- end
75
- }
76
- eval(str)
68
+ str = %{
69
+ def #{method}(*args, &block)
70
+ if #{expected_arities.size == 0 ? "block" : "!block || !#{expected_arities.inspect}.include?(block.arity)" }
71
+ raise ArgumentError.new("Arity mismatch on #{name}\##{method}, got \#{block ? block.arity : 'none'} want #{expected_arities.inspect} at \#{caller*"\n\t"})")
72
+ end
73
+ #{accessor}.__send__(:#{method}, *args, &block)
74
+ end
75
+ }
76
+ eval(str)
77
77
  end
78
78
 
79
79
  def_single_delegator :@hash, :size
@@ -87,7 +87,7 @@ module ActiveFacts
87
87
  def initialize(constellation, klass, sort)
88
88
  @constellation = constellation
89
89
  @klass = klass
90
- @sort = sort
90
+ @sort = sort
91
91
  @hash = sort ? RBTree.new : {}
92
92
  end
93
93
 
@@ -96,7 +96,7 @@ module ActiveFacts
96
96
  end
97
97
 
98
98
  def delete(k)
99
- @hash.delete(@sort ? form_key(k) : k)
99
+ @hash.delete(@sort ? form_key(k) : k)
100
100
  end
101
101
 
102
102
  def detect &b
@@ -109,7 +109,7 @@ module ActiveFacts
109
109
  end
110
110
 
111
111
  def [](key)
112
- @hash[@sort ? form_key(key) : key]
112
+ @hash[@sort ? form_key(key) : key]
113
113
  end
114
114
 
115
115
  def refresh_key(old_key)
@@ -119,14 +119,14 @@ module ActiveFacts
119
119
  end
120
120
 
121
121
  def form_key key
122
- case key
123
- when Array
124
- KeyArray.new(key)
125
- when nil
126
- []
127
- else
128
- key
129
- end
122
+ case key
123
+ when Array
124
+ KeyArray.new(key)
125
+ when nil
126
+ []
127
+ else
128
+ key
129
+ end
130
130
  end
131
131
  end
132
132
  end