Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactor assignment process.

  • Loading branch information...
commit 8056c4590bd71dfad459af1b3f989fe381a0503b 1 parent d5c29e2
@kouno authored
Showing with 61 additions and 78 deletions.
  1. +53 −5 lib/activefacts/api/instance.rb
  2. +8 −73 lib/activefacts/api/object_type.rb
View
58 lib/activefacts/api/instance.rb
@@ -96,6 +96,9 @@ def related_entities(instances = [])
instances
end
+ # Searches for entities which are referenced by this entity.
+ #
+ # This is done recursively through the constellation.
def reverse_related_entities(instances = [])
self.class.roles.each do |role_name, role|
instance_index_counterpart(role).each do |instance|
@@ -113,16 +116,61 @@ def reverse_related_entities(instances = [])
instances
end
- def two_way_related_entities(old)
- entities = self.reverse_related_entities
- if old && old.constellation
- entities = entities + old.related_entities
- end
+ def two_way_related_entities
+ entities = self.reverse_related_entities + self.related_entities
entities.map do |entity, role_obj, role_value|
[entity.identifying_role_values, entity, role_obj, role_value]
end
end
+ def role_setter(role, value)
+ r_val = prepare_assignment(role, value)
+ if r_val.nil?
+ true
+ else
+ old, value = r_val
+
+ keys = two_way_related_entities
+
+ instance_variable_set(role.variable, value)
+
+ update_counterpart_roles(role, old, value)
+
+ update_linked_roles(keys) unless keys.empty?
+
+ value
+ end
+ end
+
+ def update_counterpart_roles(role, old, value)
+ if role.counterpart.unique
+ old.send(role.counterpart.setter, nil) if old
+ value.send(role.counterpart.setter, self) if value
+ else
+ old.send(role.counterpart.getter).update(self, nil) if old
+ value.send(role.counterpart.getter).update(old, self) if value
+ end
+ end
+
+ def update_linked_roles(keys)
+ keys.each do |key, entity, role_obj, role_value|
+ entity.instance_index.refresh_key(key)
+ role_value.refresh_key(entity) unless role_value.nil?
+ end
+ end
+
+ def prepare_assignment(role, value)
+ old = instance_variable_get(role.variable) rescue nil
+ return nil if old.equal?(value) # Occurs when another instance having the same value is assigned
+
+ value = role.adapt(@constellation, value) if value
+ return nil if old.equal?(value) # Occurs when same value but not same instance is assigned
+
+ detect_inconsistencies(role, value)
+
+ [old, value]
+ end
+
# Determine if entity is an identifying value
# of the current instance.
def is_identified_by?(entity)
View
81 lib/activefacts/api/object_type.rb
@@ -161,11 +161,7 @@ def realise_role(role) #:nodoc:
# Unary role
define_unary_role_accessor(role)
elsif (role.unique)
- if role.counterpart.unique
- define_one_to_one_accessor(role)
- else
- define_one_to_many_accessor(role)
- end
+ define_single_accessor(role)
else
define_many_to_one_accessor(role)
end
@@ -229,10 +225,10 @@ def define_unary_role_accessor(role)
assigned
end
end
- define_single_role_getter(role)
+ define_role_getter(role)
end
- def define_single_role_getter(role)
+ def define_role_getter(role)
class_eval do
define_method role.getter do |*a|
raise "Parameters passed to #{self.class.name}\##{role.name}" if a.size > 0
@@ -241,78 +237,17 @@ def define_single_role_getter(role)
end
end
- def define_one_to_one_accessor(role)
- define_single_role_getter(role)
-
+ def define_role_setter(role)
class_eval do
define_method role.setter do |value|
-
- old = instance_variable_get(role.variable) rescue nil
- return true if old.equal?(value) # Occurs when another instance having the same value is assigned
-
- value = role.adapt(@constellation, value) if value
- return true if old.equal?(value) # Occurs when same value but not same instance is assigned
-
- detect_inconsistencies(role, value)
-
- keys = two_way_related_entities(old)
-
- instance_variable_set(role.variable, value)
-
- # Remove self from the old counterpart:
- old.send(role.counterpart.setter, nil) if old
-
- # Assign self to the new counterpart
- value.send(role.counterpart.setter, self) if value
-
- unless keys.empty?
- keys.each do |key, entity, role_obj, role_value|
- entity.instance_index.refresh_key(key)
- role_value.refresh_key(entity) unless role_value.nil?
- end
- end
-
- value
+ role_setter(role, value)
end
end
end
- def define_one_to_many_accessor(role)
- define_single_role_getter(role)
-
- class_eval do
- define_method role.setter do |value|
- role_var = role.variable
-
- # Get old value, and jump out early if it's unchanged:
- old = instance_variable_get(role_var) rescue nil
- return value if old.equal?(value) # Occurs during one_to_one assignment, for example
-
- value = role.adapt(constellation, value) if value
- return value if old.equal?(value) # Occurs when another instance having the same value is assigned
-
- detect_inconsistencies(role, value) if value
-
- keys = two_way_related_entities(old)
-
- instance_variable_set(role_var, value)
-
- # Remove "self" from the old counterpart:
- old.send(getter = role.counterpart.getter).update(self, nil) if old
-
- # Add "self" into the counterpart
- value.send(getter ||= role.counterpart.getter).update(old, self) if value
-
- unless keys.empty?
- keys.each do |key, entity, role_obj, role_value|
- entity.instance_index.refresh_key(key)
- role_value.refresh_key(entity) unless role_value.nil?
- end
- end
-
- value
- end
- end
+ def define_single_accessor(role)
+ define_role_getter(role)
+ define_role_setter(role)
end
def define_many_to_one_accessor(role)
Please sign in to comment.
Something went wrong with that request. Please try again.