lib/activefacts/rmap/columns.rb in activefacts-rmap-1.8.1 vs lib/activefacts/rmap/columns.rb in activefacts-rmap-1.8.2
- old
+ new
@@ -66,73 +66,77 @@
self.class.name(@references, separator)
end
def self.name(refs, separator = "")
last_names = []
- names = refs.
- inject([]) do |a, ref|
+ name_array = nil
+ trace :columns, "Building column name from #{refs.inspect}" do
+ names = refs.
+ inject([]) do |a, ref|
- # Skip any object after the first which is identified by this reference
- if ref != refs[0] and
- !ref.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) and
- ref.to and
- ref.to.is_a?(ActiveFacts::Metamodel::EntityType) and
- (role_ref = ref.to.preferred_identifier.role_sequence.all_role_ref.single) and
- role_ref.role == ref.from_role
- trace :columns, "Skipping #{ref}, identifies non-initial object"
- next a
- end
+ # Skip any object after the first which is identified by this reference
+ if ref != refs[0] and
+ !ref.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) and
+ ref.to and
+ ref.to.is_a?(ActiveFacts::Metamodel::EntityType) and
+ (role_ref = ref.to.preferred_identifier.role_sequence.all_role_ref.single) and
+ role_ref.role == ref.from_role
+ trace :columns, "Skipping #{ref}, identifies non-initial object"
+ next a
+ end
- names = ref.to_names(ref != refs.last)
+ names = ref.to_names(ref != refs.last)
- # When traversing type inheritances, keep the subtype name, not the supertype names as well:
- if a.size > 0 && ref.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
- if ref.to != ref.fact_type.subtype # Did we already have the subtype?
- trace :columns, "Skipping supertype #{ref}"
- next a
+ # When traversing type inheritances, keep the subtype name, not the supertype names as well:
+ if a.size > 0 && ref.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
+ if ref.to != ref.fact_type.subtype # Did we already have the subtype?
+ trace :columns, "Skipping supertype #{ref}"
+ next a
+ end
+ trace :columns, "Eliding supertype in #{ref}"
+ last_names.size.times { a.pop } # Remove the last names added
+ elsif last_names.last && last_names.last == names[0][0...last_names.last.size]
+ # When Xyz is followed by XyzID, truncate that to just ID
+ trace :columns, "truncating repeated #{last_names.last} in #{names[0]}"
+ names[0] = names[0][last_names.last.size..-1]
+ names.shift if names[0] == ''
+ elsif last_names.last == names[0]
+ # Same, but where an underscore split up the words
+ trace :columns, "truncating repeated name in #{names.inspect}"
+ names.shift
end
- trace :columns, "Eliding supertype in #{ref}"
- last_names.size.times { a.pop } # Remove the last names added
- elsif last_names.last && last_names.last == names[0][0...last_names.last.size]
- # When Xyz is followed by XyzID, truncate that to just ID
- trace :columns, "truncating repeated #{last_names.last} in #{names[0]}"
- names[0] = names[0][last_names.last.size..-1]
- names.shift if names[0] == ''
- elsif last_names.last == names[0]
- # Same, but where an underscore split up the words
- trace :columns, "truncating repeated name in #{names.inspect}"
- names.shift
- end
- # If the reference is to the single identifying role of the object_type making the reference,
- # strip the object_type name from the start of the reference role
- if a.size > 0 and
- (et = ref.from).is_a?(ActiveFacts::Metamodel::EntityType) and
- # This instead of the next 2 would apply to all identifying roles, but breaks some examples:
- # (role_ref = et.preferred_identifier.role_sequence.all_role_ref.detect{|rr| rr.role == ref.to_role}) and
- (role_ref = et.preferred_identifier.role_sequence.all_role_ref.single) and
- role_ref.role == ref.to_role and
- names[0][0...et.name.size].downcase == et.name.downcase
+ # If the reference is to the single identifying role of the object_type making the reference,
+ # strip the object_type name from the start of the reference role
+ if a.size > 0 and
+ (et = ref.from).is_a?(ActiveFacts::Metamodel::EntityType) and
+ # This instead of the next 2 would apply to all identifying roles, but breaks some examples:
+ # (role_ref = et.preferred_identifier.role_sequence.all_role_ref.detect{|rr| rr.role == ref.to_role}) and
+ (role_ref = et.preferred_identifier.role_sequence.all_role_ref.single) and
+ role_ref.role == ref.to_role and
+ names[0][0...et.name.size].downcase == et.name.downcase
- trace :columns, "truncating transitive identifying role #{names.inspect}"
- names[0] = names[0][et.name.size..-1]
- names.shift if names[0] == ""
- end
+ trace :columns, "truncating transitive identifying role #{names.inspect}"
+ names[0] = names[0][et.name.size..-1]
+ names.shift if names[0] == ""
+ end
- last_names = names
+ last_names = names
- a += names
- a
- end.elide_repeated_subsequences { |a, b|
- if a.is_a?(Array)
- a.map{|e| e.downcase} == b.map{|e| e.downcase}
- else
- a.downcase == b.downcase
- end
- }
+ a += names
+ a
+ end.elide_repeated_subsequences { |a, b|
+ if a.is_a?(Array)
+ a.map{|e| e.downcase} == b.map{|e| e.downcase}
+ else
+ a.downcase == b.downcase
+ end
+ }
- name_array = names.map{|n| n.sub(/^[a-z]/){|s| s.upcase}}
+ name_array = names.map{|n| n.sub(/^[a-z]/){|s| s.upcase}}
+ trace :columns, "column name is #{name_array*'.'}"
+ end
separator ? name_array * separator : name_array
end
# Is this column mandatory or nullable?
def is_mandatory
@@ -161,25 +165,25 @@
if references[-1].to_role && references[-1].to_role.role_value_constraint
constraints << references[-1].to_role.base_role.role_value_constraint
end
vt = references[-1].is_self_value ? references[-1].from : references[-1].to
- begin
+ begin
params[:length] ||= vt.length if vt.length.to_i != 0
params[:scale] ||= vt.scale if vt.scale.to_i != 0
constraints << vt.value_constraint if vt.value_constraint
- last_vt = vt
+ last_vt = vt
vt = vt.supertype
end while vt
- params[:underlying_type] = last_vt
+ params[:underlying_type] = last_vt
return [last_vt.name, params, constraints]
end
# The comment is the readings from the References expressed as a series of steps (not a full verbalisation)
def comment
@references.map do |ref|
- ref.verbalised_path
+ ref.verbalised_path
end.compact * " and "
end
def to_s #:nodoc:
"#{@references[0].from.name} column #{name('.')}"
@@ -190,38 +194,38 @@
def columns(excluded_supertypes) #:nodoc:
kind = ""
cols =
if is_unary
kind = "unary "
- objectified_unary_columns =
- ((@to && @to.fact_type) ? @to.all_columns(excluded_supertypes) : [])
+ objectified_unary_columns =
+ ((@to && @to.fact_type) ? @to.all_columns(excluded_supertypes) : [])
=begin
- # This code omits the unary if it's objectified and that plays a mandatory role
- first_mandatory_column = nil
- if (@to && @to.fact_type)
- trace :unary_col, "Deciding whether to skip unary column for #{inspect}" do
- first_mandatory_column =
- objectified_unary_columns.detect do |col| # Detect a mandatory column for the unary
- trace :unary_col, "checking column #{col.name}" do
- !col.references.detect do |ref|
- trace :unary_col, "#{ref} is mandatory=#{ref.is_mandatory.inspect}"
- !ref.is_mandatory
- end
- end
- end
- if is_from_objectified_fact && first_mandatory_column
- trace :unary_col, "Skipping unary column for #{inspect} because #{first_mandatory_column.name} is mandatory"
- end
- end
- end
+ # This code omits the unary if it's objectified and that plays a mandatory role
+ first_mandatory_column = nil
+ if (@to && @to.fact_type)
+ trace :unary_col, "Deciding whether to skip unary column for #{inspect}" do
+ first_mandatory_column =
+ objectified_unary_columns.detect do |col| # Detect a mandatory column for the unary
+ trace :unary_col, "checking column #{col.name}" do
+ !col.references.detect do |ref|
+ trace :unary_col, "#{ref} is mandatory=#{ref.is_mandatory.inspect}"
+ !ref.is_mandatory
+ end
+ end
+ end
+ if is_from_objectified_fact && first_mandatory_column
+ trace :unary_col, "Skipping unary column for #{inspect} because #{first_mandatory_column.name} is mandatory"
+ end
+ end
+ end
- (is_from_objectified_fact && first_mandatory_column ? [] : [Column.new()]) + # The unary itself, unless its objectified
+ (is_from_objectified_fact && first_mandatory_column ? [] : [Column.new()]) + # The unary itself, unless its objectified
=end
- [Column.new()] + # The unary itself
- objectified_unary_columns
+ [Column.new()] + # The unary itself
+ objectified_unary_columns
elsif is_self_value
kind = "self-role "
[Column.new()]
elsif is_simple_reference
@to.reference_columns(excluded_supertypes)
@@ -256,11 +260,11 @@
@columns =
all_columns({})
end
def wipe_columns
- @columns = nil
+ @columns = nil
end
end
# The ValueType class is defined in the metamodel; full documentation is not generated.
# This section shows the features relevant to relational mapping.
@@ -325,10 +329,10 @@
class EntityType < DomainObjectType
# The identifier_columns for an EntityType are the columns that result from the identifying roles
def identifier_columns
trace :columns, "Identifier Columns for #{name}" do
if absorbed_via and
- # If this is a subtype that has its own identification, use that.
+ # If this is a subtype that has its own identification, use that instead
(all_type_inheritance_as_subtype.size == 0 ||
all_type_inheritance_as_subtype.detect{|ti| ti.provides_identification })
return absorbed_via.from.identifier_columns
end