lib/activefacts/rmap/foreignkey.rb in activefacts-rmap-1.8.1 vs lib/activefacts/rmap/foreignkey.rb in activefacts-rmap-1.8.2

- old
+ new

@@ -26,66 +26,66 @@ @from, @to, @references, @from_columns, @to_columns = from, to, references, from_columns, to_columns end def describe - "foreign key from #{from.name}(#{from_columns.map{|c| c.name}*', '}) to #{to.name}(#{to_columns.map{|c| c.name}*', '})" + "foreign key from #{from.name}(#{from_columns.map{|c| c.name}*', '}) to #{to.name}(#{to_columns.map{|c| c.name}*', '})" end def verbalised_path reverse = false - # REVISIT: This should be a proper join path verbalisation: - refs = reverse ? references.reverse : references - refs.map do |r| - r.verbalised_path reverse - end * ' and ' + # REVISIT: This should be a proper join path verbalisation: + refs = reverse ? references.reverse : references + refs.map do |r| + r.verbalised_path reverse + end * ' and ' end # Which references are absorbed into the "from" table? def precursor_references - fk_jump = @references.detect(&:fk_jump) - jump_index = @references.index(fk_jump) - @references[0, jump_index] + fk_jump = @references.detect(&:fk_jump) + jump_index = @references.index(fk_jump) + @references[0, jump_index] end # Which references are absorbed into the "to" table? def following_references - fk_jump = @references.detect(&:fk_jump) - jump_index = @references.index(fk_jump) - fk_jump != @references.last ? @references[jump_index+1..-1] : [] + fk_jump = @references.detect(&:fk_jump) + jump_index = @references.index(fk_jump) + fk_jump != @references.last ? @references[jump_index+1..-1] : [] end def jump_reference - @references.detect(&:fk_jump) + @references.detect(&:fk_jump) end def to_name - p = precursor_references - f = following_references - j = jump_reference + p = precursor_references + f = following_references + j = jump_reference - @references.last.to_names + - (p.empty? && f.empty? ? [] : ['via'] + p.map{|r| r.to_names}.flatten + f.map{|r| r.from_names}.flatten) + @references.last.to_names + + (p.empty? && f.empty? ? [] : ['via'] + p.map{|r| r.to_names}.flatten + f.map{|r| r.from_names}.flatten) end # The from_name is the role name of the table with the FK, viewed from the other end # When there are no precursor_references or following_references, it's the jump_reference.from_names # REVISIT: I'm still working out what to do with precursor_references and following_references def from_name - p = precursor_references - f = following_references - j = jump_reference + p = precursor_references + f = following_references + j = jump_reference - # pluralise unless j.is_one_to_one + # pluralise unless j.is_one_to_one - # REVISIT: references[0].from_names is where the FK lives; but the object of interest may be an absorbed subclass which we should use here instead: - # REVISIT: Should crunch superclasses in subtype traversals - # REVISIT: Need to add "_as_rolename" where rolename is not to.name + # REVISIT: references[0].from_names is where the FK lives; but the object of interest may be an absorbed subclass which we should use here instead: + # REVISIT: Should crunch superclasses in subtype traversals + # REVISIT: Need to add "_as_rolename" where rolename is not to.name - [ - @references[0].from_names, - (p.empty? && f.empty? ? [] : ['via'] + p.map{|r| r.to_names}.flatten + f.map{|r| r.from_names}.flatten) - ] + [ + @references[0].from_names, + (p.empty? && f.empty? ? [] : ['via'] + p.map{|r| r.to_names}.flatten + f.map{|r| r.from_names}.flatten) + ] end end end @@ -101,86 +101,86 @@ next array if absorbed_via && TypeInheritance === absorbed_via.fact_type # Ignore the case where a subtype is absorbed elsewhere: # REVISIT: Disabled, as this should never happen. # next array if ref.to.absorbed_via != ref.fact_type end - ref.fk_jump = true + ref.fk_jump = true array << [ref] elsif ref.is_absorbing or (ref.to && !ref.to.is_table) - trace :fk, "getting fks absorbed into #{name} via #{ref}" do - ref.to.all_absorbed_foreign_key_reference_path.each do |aref| - array << aref.insert(0, ref) - end - end + trace :fk, "getting fks absorbed into #{name} via #{ref}" do + ref.to.all_absorbed_foreign_key_reference_path.each do |aref| + array << aref.insert(0, ref) + end + end end array end end def foreign_keys_to - @foreign_keys_to ||= [] + @foreign_keys_to ||= [] end # Return an array of all the foreign keys from this table def foreign_keys # Get the ForeignKey object for each absorbed reference path - @foreign_keys ||= - begin - fk_ref_paths = all_absorbed_foreign_key_reference_path - fk_ref_paths.map do |fk_ref_path| - trace :fk, "\nFK: " + fk_ref_path.map{|fk_ref| fk_ref.reading }*" and " do + @foreign_keys ||= + begin + fk_ref_paths = all_absorbed_foreign_key_reference_path + fk_ref_paths.map do |fk_ref_path| + trace :fk, "\nFK: " + fk_ref_path.map{|fk_ref| fk_ref.reading }*" and " do - from_columns = (columns||all_columns({})).select{|column| - column.references[0...fk_ref_path.size] == fk_ref_path - } - trace :fk, "from_columns = #{from_columns.map { |column| column.name }*", "}" + from_columns = (columns||all_columns({})).select{|column| + column.references[0...fk_ref_path.size] == fk_ref_path + } + trace :fk, "from_columns = #{from_columns.map { |column| column.name }*", "}" - # Figure out absorption on the target end: - to = fk_ref_path.last.to - if to.absorbed_via - trace :fk, "Reference target #{fk_ref_path.last.to.name} is absorbed via:" do - while (r = to.absorbed_via) - m = r.reversed - trace :fk, "#{m.reading}" - fk_ref_path << m - to = m.from == to ? m.to : m.from - end - trace :fk, "Absorption ends at #{to.name}" - end - end + # Figure out absorption on the target end: + to = fk_ref_path.last.to + if to.absorbed_via + trace :fk, "Reference target #{fk_ref_path.last.to.name} is absorbed via:" do + while (r = to.absorbed_via) + m = r.reversed + trace :fk, "#{m.reading}" + fk_ref_path << m + to = m.from == to ? m.to : m.from + end + trace :fk, "Absorption ends at #{to.name}" + end + end - # REVISIT: This test may no longer be necessary - raise "REVISIT: #{fk_ref_path.inspect} is bad" unless to and to.columns + # REVISIT: This test may no longer be necessary + raise "REVISIT: #{fk_ref_path.inspect} is bad" unless to and to.columns - # REVISIT: This fails for absorbed subtypes having their own identification. - # Check the CompanyDirectorEmployee model for example, EmployeeManagerNr -> Person (should reference EmployeeNr) - # Need to use the absorbed identifier_columns of the subtype, - # not the columns of the supertype that absorbs it. - # But in general, that isn't going to work because in most DBMS - # there's no suitable uniquen index on the subtype's identifier_columns + # REVISIT: This fails for absorbed subtypes having their own identification. + # Check the CompanyDirectorEmployee model for example, EmployeeManagerNr -> Person (should reference EmployeeNr) + # Need to use the absorbed identifier_columns of the subtype, + # not the columns of the supertype that absorbs it. + # But in general, that isn't going to work because in most DBMS + # there's no suitable uniquen index on the subtype's identifier_columns - to_columns = fk_ref_path[-1].to.identifier_columns + to_columns = fk_ref_path[-1].to.identifier_columns - # Put the column pairs in the correct order. They MUST be in the order they appear in the primary key - froms, tos = from_columns.zip(to_columns).sort_by { |pair| - to_columns.index(pair[1]) - }.transpose + # Put the column pairs in the correct order. They MUST be in the order they appear in the primary key + froms, tos = from_columns.zip(to_columns).sort_by { |pair| + to_columns.index(pair[1]) + }.transpose - fk = ActiveFacts::RMap::ForeignKey.new(self, to, fk_ref_path, froms, tos) - to.foreign_keys_to << fk - fk - end - end. - sort_by do |fk| - # Put the foreign keys in a defined order: -# debugger if !fk.to_columns || fk.to_columns.include?(nil) || !fk.from_columns || fk.from_columns.include?(nil) - [ fk.to.name, - fk.to_columns.map{|col| col.name(nil).sort}, - fk.from_columns.map{|col| col.name(nil).sort} - ] - end - end + fk = ActiveFacts::RMap::ForeignKey.new(self, to, fk_ref_path, froms, tos) + to.foreign_keys_to << fk + fk + end + end. + sort_by do |fk| + # Put the foreign keys in a defined order: +# debugger if !fk.to_columns || fk.to_columns.include?(nil) || !fk.from_columns || fk.from_columns.include?(nil) + [ fk.to.name, + fk.to_columns.map{|col| col.name(nil).sort}, + fk.from_columns.map{|col| col.name(nil).sort} + ] + end + end end end end end