Class: ActiveFacts::Persistence::Reference
- Inherits:
-
Object
- Object
- ActiveFacts::Persistence::Reference
- Defined in:
- lib/activefacts/persistence/reference.rb,
lib/activefacts/persistence/columns.rb
Overview
This class contains the core data structure used in composing a relational schema.
A Reference is from one Concept to another Concept, and relates to the from_role and the to_role. When either Concept is an objectified fact type, the corresponding role is nil. When the Reference from_role is of a unary fact type, there’s no to_role or to Concept. The final kind of Reference is a self-reference which is added to a ValueType that becomes a table.
When the underlying fact type is a one-to-one (including an inheritance fact type), the Reference may be flipped.
Each Reference has a name; an array of names in fact, in case of adjectives, etc. Each Refererence can produce the reading of the underlying fact type.
A Reference is indexed in the player’s references_from and references_to, and flipping updates those. Finally, a Reference may be marked as absorbing the whole referenced object, and that can flip too.
Instance Attribute Summary collapse
-
#fact_type ⇒ Object
readonly
Returns the value of attribute fact_type.
-
#from ⇒ Object
readonly
A “from” instance is related to one “to” instance.
-
#from_role ⇒ Object
readonly
For objectified facts, one role will be nil (a phantom).
-
#to ⇒ Object
readonly
A “from” instance is related to one “to” instance.
-
#to_role ⇒ Object
readonly
For objectified facts, one role will be nil (a phantom).
Instance Method Summary collapse
-
#columns(excluded_supertypes) ⇒ Object
:nodoc:.
-
#detabulate ⇒ Object
:nodoc:.
-
#flip ⇒ Object
For a one-to-one (or a subtyping fact type), reverse the direction.
-
#initialize(from, role) ⇒ Reference
constructor
A Reference is created from a concept in regard to a role it plays.
-
#inspect ⇒ Object
:nodoc:.
-
#is_absorbing ⇒ Object
Is the to concept fully absorbed through this reference?.
-
#is_from_objectified_fact ⇒ Object
If this Reference is from an objectified FactType, there is no from_role.
-
#is_mandatory ⇒ Object
Is this Reference covered by a mandatory constraint (implicitly or explicitly).
-
#is_self_value ⇒ Object
Is this reference an injected role as a result a ValueType being a table?.
-
#is_simple_reference ⇒ Object
Is this a simple reference?.
-
#is_to_objectified_fact ⇒ Object
If this Reference is to an objectified FactType, there is no to_role.
-
#is_unary ⇒ Object
Is this Reference from a unary Role?.
-
#reading ⇒ Object
The reading for the fact type underlying this Reference.
-
#role_type ⇒ Object
What type of Role did this Reference arise from?.
-
#tabulate ⇒ Object
:nodoc:.
-
#to_names ⇒ Object
Return the array of names for the (perhaps implicit) to_role of this Reference.
-
#to_s ⇒ Object
:nodoc:.
Constructor Details
#initialize(from, role) ⇒ Reference
A Reference is created from a concept in regard to a role it plays
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/activefacts/persistence/reference.rb', line 44 def initialize(from, role) @from = from return unless role # All done if it's a self-value reference for a ValueType @fact_type = role.fact_type if @fact_type.all_role.size == 1 # @from_role is nil for a unary @to_role = role @to = role.fact_type.entity_type # nil unless the unary is objectified elsif (role.fact_type.entity_type == @from) # role is in "from", an objectified fact type @from_role = nil # Phantom role @to_role = role @to = @to_role.concept else @from_role = role @to = role.fact_type.entity_type # If set, to_role is a phantom unless @to raise "Illegal reference through >binary fact type" if @fact_type.all_role.size >2 @to_role = (role.fact_type.all_role-[role])[0] @to = @to_role.concept end end end |
Instance Attribute Details
#fact_type ⇒ Object (readonly)
Returns the value of attribute fact_type.
41 42 43 |
# File 'lib/activefacts/persistence/reference.rb', line 41 def fact_type @fact_type end |
#from ⇒ Object (readonly)
A “from” instance is related to one “to” instance
39 40 41 |
# File 'lib/activefacts/persistence/reference.rb', line 39 def from @from end |
#from_role ⇒ Object (readonly)
For objectified facts, one role will be nil (a phantom)
40 41 42 |
# File 'lib/activefacts/persistence/reference.rb', line 40 def from_role @from_role end |
#to ⇒ Object (readonly)
A “from” instance is related to one “to” instance
39 40 41 |
# File 'lib/activefacts/persistence/reference.rb', line 39 def to @to end |
#to_role ⇒ Object (readonly)
For objectified facts, one role will be nil (a phantom)
40 41 42 |
# File 'lib/activefacts/persistence/reference.rb', line 40 def to_role @to_role end |
Instance Method Details
#columns(excluded_supertypes) ⇒ Object
:nodoc:
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/activefacts/persistence/columns.rb', line 158 def columns(excluded_supertypes) #:nodoc: kind = "" cols = if is_unary kind = "unary " [Column.new()] elsif is_self_value kind = "self-role " [Column.new()] elsif is_simple_reference @to.reference_columns(excluded_supertypes) else kind = "absorbing " @to.all_columns(excluded_supertypes) end cols.each do |c| c.prepend self end debug :columns, "Columns from #{kind}#{self}" do cols.each {|c| debug :columns, "#{c}" } end end |
#detabulate ⇒ Object
:nodoc:
157 158 159 160 161 162 163 |
# File 'lib/activefacts/persistence/reference.rb', line 157 def detabulate #:nodoc: # Remove from @to and @from's reference lists if present return unless @from.references_from.delete(self) @to.references_to.delete self if @to # Guard against self-values debug :references, "Dropping #{to_s}" self end |
#flip ⇒ Object
For a one-to-one (or a subtyping fact type), reverse the direction.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/activefacts/persistence/reference.rb', line 131 def flip #:nodoc: raise "Illegal flip of #{self}" unless @to and [:one_one, :subtype, :supertype].include?(role_type) detabulate if @to.absorbed_via == self @to.absorbed_via = nil @from.absorbed_via = self end # Flip the reference @to, @from = @from, @to @to_role, @from_role = @from_role, @to_role tabulate end |
#inspect ⇒ Object
:nodoc:
174 175 176 |
# File 'lib/activefacts/persistence/reference.rb', line 174 def inspect #:nodoc: to_s end |
#is_absorbing ⇒ Object
Is the to concept fully absorbed through this reference?
102 103 104 |
# File 'lib/activefacts/persistence/reference.rb', line 102 def is_absorbing @to && @to.absorbed_via == self end |
#is_from_objectified_fact ⇒ Object
If this Reference is from an objectified FactType, there is no from_role
92 93 94 |
# File 'lib/activefacts/persistence/reference.rb', line 92 def is_from_objectified_fact @to && @to_role && !@from_role end |
#is_mandatory ⇒ Object
Is this Reference covered by a mandatory constraint (implicitly or explicitly)
74 75 76 77 78 |
# File 'lib/activefacts/persistence/reference.rb', line 74 def is_mandatory !@from_role || # All phantom roles of fact types are mandatory is_unary || # Unary fact types become booleans, which must be true or false @from_role.is_mandatory end |
#is_self_value ⇒ Object
Is this reference an injected role as a result a ValueType being a table?
97 98 99 |
# File 'lib/activefacts/persistence/reference.rb', line 97 def is_self_value !@to && !@to_role end |
#is_simple_reference ⇒ Object
Is this a simple reference?
107 108 109 110 111 |
# File 'lib/activefacts/persistence/reference.rb', line 107 def is_simple_reference # It's a simple reference to a thing if that thing is a table, # or is fully absorbed into another table but not via this reference. @to && (@to.is_table or @to.absorbed_via && !is_absorbing) end |
#is_to_objectified_fact ⇒ Object
If this Reference is to an objectified FactType, there is no to_role
86 87 88 89 |
# File 'lib/activefacts/persistence/reference.rb', line 86 def is_to_objectified_fact # This case is the only one that cannot be used in the preferred identifier of @from @to && !@to_role && @from_role end |
#is_unary ⇒ Object
Is this Reference from a unary Role?
81 82 83 |
# File 'lib/activefacts/persistence/reference.rb', line 81 def is_unary !@to && @to_role && @to_role.fact_type.all_role.size == 1 end |
#reading ⇒ Object
The reading for the fact type underlying this Reference
170 171 172 |
# File 'lib/activefacts/persistence/reference.rb', line 170 def reading is_self_value ? "#{from.name} has value" : @fact_type.default_reading end |
#role_type ⇒ Object
What type of Role did this Reference arise from?
68 69 70 71 |
# File 'lib/activefacts/persistence/reference.rb', line 68 def role_type role = @from_role||@to_role role && role.role_type end |
#tabulate ⇒ Object
:nodoc:
148 149 150 151 152 153 154 155 |
# File 'lib/activefacts/persistence/reference.rb', line 148 def tabulate #:nodoc: # Add to @to and @from's reference lists @from.references_from << self @to.references_to << self if @to # Guard against self-values debug :references, "Adding #{to_s}" self end |
#to_names ⇒ Object
Return the array of names for the (perhaps implicit) to_role of this Reference
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/activefacts/persistence/reference.rb', line 114 def to_names case when is_unary @to_role.fact_type.preferred_reading.reading_text.gsub(/\{[0-9]\}/,'').strip.split(/[_\s]/) when @to && !@to_role # @to is an objectified fact type so @to_role is a phantom @to.name.split(/[_\s]/) when !@to_role # Self-value role of an independent ValueType ["#{@from.name}", "Value"] when @to_role.role_name # Named role @to_role.role_name.split(/[_\s]/) else # Use the name from the preferred reading role_ref = @to_role.preferred_reference [role_ref.leading_adjective, @to_role.concept.name, role_ref.trailing_adjective].compact.map{|w| w.split(/[_\s]/)}.flatten.reject{|s| s == ''} end end |
#to_s ⇒ Object
:nodoc:
165 166 167 |
# File 'lib/activefacts/persistence/reference.rb', line 165 def to_s #:nodoc: "reference from #{@from.name}#{@to ? " to #{@to.name}" : ""}" + (@fact_type ? " in '#{@fact_type.default_reading}'" : "") end |