class ActiveFacts::Metamodel::EntityType
Public Instance Methods
identifying_refs_from()
click to toggle source
# File lib/activefacts/generators/transform/surrogate.rb, line 80 def identifying_refs_from pi = preferred_identifier rrs = pi.role_sequence.all_role_ref # REVISIT: This is actually a ref to us, not from # if absorbed_via # return [absorbed_via] # end rrs.map do |rr| r = references_from.detect{|ref| rr.role == ref.to_role } raise "failed to find #{name} identifying reference for #{rr.role.object_type.name} in #{references_from.inspect}" unless r r end end
inject_surrogate()
click to toggle source
# File lib/activefacts/generators/transform/surrogate.rb, line 165 def inject_surrogate trace :transform_surrogate, "Injecting a surrogate key into #{self.name}" # Disable the preferred identifier: pi = preferred_identifier trace :transform_surrogate, "pi for #{name} was '#{pi.describe}'" pi.is_preferred_identifier = false @preferred_identifier = nil # Kill the cache add_surrogate trace :transform_surrogate, "pi for #{name} is now '#{preferred_identifier.describe}'" end
needs_surrogate()
click to toggle source
# File lib/activefacts/generators/transform/surrogate.rb, line 96 def needs_surrogate # A recursive proc to replace any reference to an Entity Type by its identifying references: trace :transform_surrogate_expansion, "Expanding key for #{name}" substitute_identifying_refs = proc do |object| if ref = object.absorbed_via # This shouldn't be necessary, but see the absorbed_via comment above. absorbed_into = ref.from trace :transform_surrogate_expansion, "recursing to handle absorption of #{object.name} into #{absorbed_into.name}" [substitute_identifying_refs.call(absorbed_into)] else irf = object.identifying_refs_from trace :transform_surrogate_expansion, "Iterating for #{object.name} over #{irf.inspect}" do irf.each_with_index do |ref, i| next if ref.is_unary next if ref.to_role.object_type.kind_of?(ActiveFacts::Metamodel::ValueType) recurse_to = ref.to_role.object_type trace :transform_surrogate_expansion, "#{i}: recursing to expand #{recurse_to.name} key in #{ref}" do irf[i] = substitute_identifying_refs.call(recurse_to) end end end irf end end irf = substitute_identifying_refs.call(self) trace :transform_surrogate, "Does #{name} need a surrogate? it's identified by #{irf.inspect}" do pk_fks = identifying_refs_from.map do |ref| ref.to && ref.to.is_table ? ref.to : nil end irf.flatten! # Multi-part identifiers are only allowed if: # * each part is a foreign key (i.e. it's a join table), # * there are no other columns (that might require updating) and # * the object is not the target of a foreign key: if irf.size >= 2 if pk_fks.include?(nil) trace :transform_surrogate, "#{self.name} needs a surrogate because its multi-part key contains a non-table" return true elsif references_to.size != 0 trace :transform_surrogate, "#{self.name} is a join table between #{pk_fks.map(&:name).inspect} but is also an FK target" return true elsif (references_from-identifying_refs_from).size > 0 # There are other attributes to worry about return true else trace :transform_surrogate, "#{self.name} is a join table between #{pk_fks.map(&:name).inspect}" return false end return true end # Single-part key. It must be an Auto Counter, or we will add a surrogate identifying_type = irf[0].to if identifying_type.needs_surrogate trace :transform_surrogate, "#{self.name} needs a surrogate because #{irf[0].to.name} is not an AutoCounter, but #{identifying_type.supertypes_transitive.map(&:name).inspect}" return true end false end end