Class: ROM::Schema
- Inherits:
-
Object
- Object
- ROM::Schema
- Extended by:
- Notifications::Listener
- Includes:
- Enumerable
- Defined in:
- core/lib/rom/schema.rb,
core/lib/rom/schema/dsl.rb,
core/lib/rom/schema/inferrer.rb,
core/lib/rom/schema/associations_dsl.rb
Overview
Relation schema
Schemas hold detailed information about relation tuples, including their primitive types (String, Integer, Hash, etc. or custom classes), as well as various meta information like primary/foreign key and literally any other information that a given database adapter may need.
Adapters can extend this class and it can be used in adapter-specific relations. In example rom-sql extends schema with Association DSL and many additional SQL-specific APIs in schema types.
Schemas are used for projecting canonical relations into other relations and every relation object maintains its schema. This means that we always have all information about relation tuples, even when a relation was projected and diverged from its canonical form.
Furthermore schema attributes know their source relations, which makes it possible to merge schemas from multiple relations and maintain information about the source relations. In example when two relations are joined, their schemas are merged, and we know which attributes belong to which relation.
Direct Known Subclasses
Defined Under Namespace
Classes: AssociationsDSL, DSL
Constant Summary collapse
- EMPTY_ASSOCIATION_SET =
AssociationSet.build(EMPTY_HASH).freeze
- DEFAULT_INFERRER =
Inferrer.new(enabled: false).freeze
- HASH_SCHEMA =
Types::Coercible::Hash .schema(EMPTY_HASH) .with_type_transform(type_transformation)
Instance Attribute Summary collapse
-
#associations ⇒ AssociationSet
readonly
Optional association set (this is adapter-specific).
-
#attributes ⇒ Array
readonly
Array with schema attributes.
-
#canonical ⇒ Symbol
readonly
The canonical schema which is carried in all schema instances.
-
#inferrer ⇒ #call
readonly
An optional inferrer object used in
finalize!
. -
#name ⇒ Symbol
readonly
The name of this schema.
-
#primary_key_name ⇒ Symbol
readonly
The name of the primary key.
-
#primary_key_names ⇒ Array<Symbol>
readonly
A list of all pk names.
Class Method Summary collapse
-
.define(name, attributes: EMPTY_ARRAY, attr_class: Attribute, **options) ⇒ Schema
Define a relation schema from plain rom types and optional options.
-
.subscribe(event_id, query = EMPTY_HASH, &block) ⇒ Object
extended
from Notifications::Listener
Subscribe to events.
Instance Method Summary collapse
-
#[](key, src = name.to_sym) ⇒ Object
Return attribute.
-
#append(*new_attributes) ⇒ Schema
Append more attributes to the schema.
-
#call(relation) ⇒ Relation
Abstract method for creating a new relation based on schema definition.
-
#canonical? ⇒ Boolean
Return if a schema is canonical.
-
#each {|Attribute| ... } ⇒ Object
Iterate over schema's attributes.
-
#empty? ⇒ TrueClass, FalseClass
Check if schema has any attributes.
-
#exclude(*names) ⇒ Schema
Exclude provided attributes from a schema.
-
#foreign_key(relation) ⇒ Attribute
Return FK attribute for a given relation name.
-
#key?(name) ⇒ Boolean
Return if a schema includes an attribute with the given name.
-
#merge(other) ⇒ Schema
(also: #+)
Merge with another schema.
-
#prefix(prefix) ⇒ Schema
Project a schema with renamed attributes using provided prefix.
-
#primary_key ⇒ Array<Attribute>
Return primary key attributes.
-
#project(*names) ⇒ Schema
Project a schema to include only specified attributes.
-
#rename(mapping) ⇒ Schema
Project a schema with renamed attributes.
-
#to_ary ⇒ Array
Array with schema attributes.
-
#to_ast ⇒ Array
Return AST for the schema.
-
#to_h ⇒ Hash
Coerce schema into a
Attribute> Hash. -
#uniq(&block) ⇒ Schema
Return a new schema with uniq attributes.
-
#wrap(prefix = name.dataset) ⇒ Schema
Return new schema with all attributes marked as prefixed and wrapped.
Instance Attribute Details
#associations ⇒ AssociationSet (readonly)
Returns Optional association set (this is adapter-specific).
95 |
# File 'core/lib/rom/schema.rb', line 95 option :associations, default: -> { EMPTY_ASSOCIATION_SET } |
#attributes ⇒ Array (readonly)
Returns Array with schema attributes.
91 |
# File 'core/lib/rom/schema.rb', line 91 option :attributes, default: -> { EMPTY_ARRAY } |
#canonical ⇒ Symbol (readonly)
Returns The canonical schema which is carried in all schema instances.
106 |
# File 'core/lib/rom/schema.rb', line 106 option :canonical, default: -> { self } |
#inferrer ⇒ #call (readonly)
Returns An optional inferrer object used in finalize!
.
99 |
# File 'core/lib/rom/schema.rb', line 99 option :inferrer, default: -> { DEFAULT_INFERRER } |
#name ⇒ Symbol (readonly)
Returns The name of this schema.
87 |
# File 'core/lib/rom/schema.rb', line 87 param :name |
#primary_key_name ⇒ Symbol (readonly)
Returns The name of the primary key. This is set because in most of the cases relations don't have composite pks.
114 |
# File 'core/lib/rom/schema.rb', line 114 option :primary_key_name, optional: true |
#primary_key_names ⇒ Array<Symbol> (readonly)
Returns A list of all pk names.
118 |
# File 'core/lib/rom/schema.rb', line 118 option :primary_key_names, optional: true |
Class Method Details
.define(name, attributes: EMPTY_ARRAY, attr_class: Attribute, **options) ⇒ Schema
Define a relation schema from plain rom types and optional options
Resulting schema will decorate plain rom types with adapter-specific types
By default Attribute
will be used
132 133 134 135 136 137 138 139 |
# File 'core/lib/rom/schema.rb', line 132 def self.define(name, attributes: EMPTY_ARRAY, attr_class: Attribute, **) new( name, attr_class: attr_class, attributes: attributes(attributes, attr_class), ** ) { |schema| yield(schema) if block_given? } end |
.subscribe(event_id, query = EMPTY_HASH, &block) ⇒ Object Originally defined in module Notifications::Listener
Subscribe to events
Instance Method Details
#[](key, src = name.to_sym) ⇒ Object
Return attribute
224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'core/lib/rom/schema.rb', line 224 def [](key, src = name.to_sym) attr = if count_index[key].equal?(1) name_index[key] else source_index[src][key] end raise(KeyError, "#{key.inspect} attribute doesn't exist in #{src} schema") unless attr attr end |
#append(*new_attributes) ⇒ Schema
Append more attributes to the schema
This returns a new schema instance
339 340 341 |
# File 'core/lib/rom/schema.rb', line 339 def append(*new_attributes) new(attributes + new_attributes) end |
#call(relation) ⇒ Relation
Abstract method for creating a new relation based on schema definition
This can be used by views to generate a new relation automatically. In example a schema can project a relation, join any additional relations if it includes attributes from other relations etc.
Default implementation is a no-op and it simply returns back untouched relation
185 186 187 |
# File 'core/lib/rom/schema.rb', line 185 def call(relation) relation end |
#canonical? ⇒ Boolean
Return if a schema is canonical
372 373 374 |
# File 'core/lib/rom/schema.rb', line 372 def canonical? equal?(canonical) end |
#each {|Attribute| ... } ⇒ Object
Iterate over schema's attributes
194 195 196 |
# File 'core/lib/rom/schema.rb', line 194 def each(&block) attributes.each(&block) end |
#empty? ⇒ TrueClass, FalseClass
Check if schema has any attributes
203 204 205 |
# File 'core/lib/rom/schema.rb', line 203 def empty? attributes.empty? end |
#exclude(*names) ⇒ Schema
Exclude provided attributes from a schema
255 256 257 |
# File 'core/lib/rom/schema.rb', line 255 def exclude(*names) project(*(map(&:name) - names)) end |
#foreign_key(relation) ⇒ Attribute
Return FK attribute for a given relation name
305 306 307 |
# File 'core/lib/rom/schema.rb', line 305 def foreign_key(relation) detect { |attr| attr.foreign_key? && attr.target == relation } end |
#key?(name) ⇒ Boolean
Return if a schema includes an attribute with the given name
363 364 365 |
# File 'core/lib/rom/schema.rb', line 363 def key?(name) !attributes.detect { |attr| attr.name == name }.nil? end |
#merge(other) ⇒ Schema Also known as: +
Merge with another schema
325 326 327 |
# File 'core/lib/rom/schema.rb', line 325 def merge(other) append(*other) end |
#prefix(prefix) ⇒ Schema
Project a schema with renamed attributes using provided prefix
282 283 284 |
# File 'core/lib/rom/schema.rb', line 282 def prefix(prefix) new(map { |attr| attr.prefixed(prefix) }) end |
#primary_key ⇒ Array<Attribute>
Return primary key attributes
314 315 316 |
# File 'core/lib/rom/schema.rb', line 314 def primary_key select(&:primary_key?) end |
#project(*names) ⇒ Schema
Project a schema to include only specified attributes
244 245 246 |
# File 'core/lib/rom/schema.rb', line 244 def project(*names) new(names.map { |name| name.is_a?(Symbol) ? self[name] : name }) end |
#rename(mapping) ⇒ Schema
Project a schema with renamed attributes
266 267 268 269 270 271 272 273 |
# File 'core/lib/rom/schema.rb', line 266 def rename(mapping) new_attributes = map do |attr| alias_name = mapping[attr.name] alias_name ? attr.aliased(alias_name) : attr end new(new_attributes) end |
#to_ary ⇒ Array
Returns Array with schema attributes.
120 |
# File 'core/lib/rom/schema.rb', line 120 option :attributes, default: -> { EMPTY_ARRAY } |
#to_ast ⇒ Array
Return AST for the schema
449 450 451 |
# File 'core/lib/rom/schema.rb', line 449 def to_ast [:schema, [name, attributes.map(&:to_ast)]] end |
#to_h ⇒ Hash
Coerce schema into a
212 213 214 |
# File 'core/lib/rom/schema.rb', line 212 def to_h each_with_object({}) { |attr, h| h[attr.name] = attr } end |
#uniq(&block) ⇒ Schema
Return a new schema with uniq attributes
348 349 350 351 352 353 354 |
# File 'core/lib/rom/schema.rb', line 348 def uniq(&block) if block new(attributes.uniq(&block)) else new(attributes.uniq(&:name)) end end |
#wrap(prefix = name.dataset) ⇒ Schema
Return new schema with all attributes marked as prefixed and wrapped
This is useful when relations are joined and the right side should be marked as wrapped
296 297 298 |
# File 'core/lib/rom/schema.rb', line 296 def wrap(prefix = name.dataset) new(map { |attr| attr.wrapped? ? attr : attr.wrapped(prefix) }) end |