Class: ActiveFacts::Persistence::Column
- Inherits:
-
Object
- Object
- ActiveFacts::Persistence::Column
- Defined in:
- lib/activefacts/persistence/columns.rb
Instance Method Summary collapse
-
#absorption_level ⇒ Object
How many of the initial references are involved in full absorption of an EntityType into this column’s table.
-
#absorption_references ⇒ Object
All references up to and including the first non-absorbing reference.
-
#comment ⇒ Object
The comment is the readings from the References expressed as a join.
-
#initialize(reference = nil) ⇒ Column
constructor
:nodoc:.
-
#is_auto_assigned ⇒ Object
Is this column an auto-assigned value type?.
-
#is_mandatory ⇒ Object
Is this column mandatory or nullable?.
-
#name(joiner = "") ⇒ Object
A Column name is a sequence of names (derived from the to_roles of the References) joined by a joiner string (pass nil to get the original array of names) The names to use is derived from the to_names of each Reference, modified by these rules: * A reference after the first one which is not a TypeInheritance but where the from object plays the sole role in the preferred identifier of the to entity is ignored, * A reference (after a name has been retained) which is a TypeInheritance retains the names of the subtype, * If the names retained so far end in XYZ and the to_names start with XYZ, remove the duplication * If we have retained the name of an entity, and this reference is the sole identifying role of an entity, and the identifying object has a name that is prefixed by the name of the object it identifies, remove the prefix and use just the suffix.
-
#prepend(reference) ⇒ Object
:nodoc:.
-
#references ⇒ Object
A Column is created from a path through an array of References to a ValueType.
-
#to_s ⇒ Object
:nodoc:.
-
#type ⇒ Object
What’s the underlying SQL data type of this column?.
Constructor Details
#initialize(reference = nil) ⇒ Column
:nodoc:
23 24 25 |
# File 'lib/activefacts/persistence/columns.rb', line 23 def initialize(reference = nil) #:nodoc: references << reference if reference end |
Instance Method Details
#absorption_level ⇒ Object
How many of the initial references are involved in full absorption of an EntityType into this column’s table
43 44 45 46 47 48 49 50 |
# File 'lib/activefacts/persistence/columns.rb', line 43 def absorption_level l = 0 @references.detect do |ref| l += 1 if ref.is_absorbing false end l end |
#absorption_references ⇒ Object
All references up to and including the first non-absorbing reference
33 34 35 36 37 38 39 40 |
# File 'lib/activefacts/persistence/columns.rb', line 33 def absorption_references @references.inject([]) do |array, ref| array << ref # puts "Column #{name} spans #{ref}, #{ref.is_absorbing ? "" : "not "} absorbing (#{ref.to.name} absorbs via #{ref.to.absorbed_via.inspect})" break array unless ref.is_absorbing array end end |
#comment ⇒ Object
The comment is the readings from the References expressed as a join
168 169 170 171 172 173 174 |
# File 'lib/activefacts/persistence/columns.rb', line 168 def comment @references.map do |ref| (ref.is_mandatory ? "" : "maybe ") + (ref.fact_type && ref.fact_type.entity_type ? ref.fact_type.entity_type.name+" is where " : "") + ref.reading end * " and " end |
#is_auto_assigned ⇒ Object
Is this column an auto-assigned value type?
139 140 141 |
# File 'lib/activefacts/persistence/columns.rb', line 139 def is_auto_assigned (to = references[-1].to) && to.is_auto_assigned end |
#is_mandatory ⇒ Object
Is this column mandatory or nullable?
134 135 136 |
# File 'lib/activefacts/persistence/columns.rb', line 134 def is_mandatory !@references.detect{|ref| !ref.is_mandatory} end |
#name(joiner = "") ⇒ Object
A Column name is a sequence of names (derived from the to_roles of the References) joined by a joiner string (pass nil to get the original array of names) The names to use is derived from the to_names of each Reference, modified by these rules:
-
A reference after the first one which is not a TypeInheritance but where the from object plays the sole role in the preferred identifier of the to entity is ignored,
-
A reference (after a name has been retained) which is a TypeInheritance retains the names of the subtype,
-
If the names retained so far end in XYZ and the to_names start with XYZ, remove the duplication
-
If we have retained the name of an entity, and this reference is the sole identifying role of an entity, and the identifying object has a name that is prefixed by the name of the object it identifies, remove the prefix and use just the suffix.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/activefacts/persistence/columns.rb', line 65 def name(joiner = "") last_names = [] names = @references. inject([]) do |a, ref| # Skip any object after the first which is identified by this reference if ref != @references[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 debug :columns, "Skipping #{ref}, identifies non-initial object" next a end names = ref.to_names # 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? debug :columns, "Skipping supertype #{ref}" next a end debug :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 debug :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 debug :columns, "truncating repeated name in #{names.inspect}" names.shift end # If the reference is to the single identifying role of the concept making the reference, # strip the concept 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 debug :columns, "truncating transitive identifying role #{names.inspect}" names[0] = names[0][et.name.size..-1] names.shift if names[0] == "" end 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 } name_array = names.map{|n| n.sub(/^[a-z]/){|s| s.upcase}} joiner ? name_array * joiner : name_array end |
#prepend(reference) ⇒ Object
:nodoc:
52 53 54 55 |
# File 'lib/activefacts/persistence/columns.rb', line 52 def prepend reference #:nodoc: references.insert 0, reference self end |
#references ⇒ Object
A Column is created from a path through an array of References to a ValueType
28 29 30 |
# File 'lib/activefacts/persistence/columns.rb', line 28 def references @references ||= [] end |
#to_s ⇒ Object
:nodoc:
176 177 178 |
# File 'lib/activefacts/persistence/columns.rb', line 176 def to_s #:nodoc: "#{@references[0].from.name} column #{name('.')}" end |
#type ⇒ Object
What’s the underlying SQL data type of this column?
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/activefacts/persistence/columns.rb', line 144 def type params = {} constraints = [] return ["BIT", params, constraints] if references[-1].is_unary # It's a unary # Add a role value constraint # REVISIT: Can add join-role-value-constraints here, if we ever provide a way to define them if references[-1].to_role && references[-1].to_role.role_value_constraint constraints << references[-1].to_role.role_value_constraint end vt = references[-1].is_self_value ? references[-1].from : references[-1].to params[:length] ||= vt.length if vt.length.to_i != 0 params[:scale] ||= vt.scale if vt.scale.to_i != 0 while vt.supertype 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 vt = vt.supertype end return [vt.name, params, constraints] end |