Class: ROM::Attribute

Inherits:
Object
  • Object
show all
Extended by:
Initializer
Includes:
Memoizable
Defined in:
lib/rom/attribute.rb

Overview

Schema attributes provide meta information about types and an API for additional operations. This class can be extended by adapters to provide database-specific features. In example rom-sql provides SQL::Attribute with more features like creating SQL expressions for queries.

Schema attributes are accessible through canonical relation schemas and instance-level schemas.

Constant Summary

Constants included from Memoizable

Memoizable::MEMOIZED_HASH

Instance Attribute Summary collapse

Attributes included from Memoizable

#__memoized__

Instance Method Summary collapse

Methods included from Initializer

extended

Methods included from Memoizable

included

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



422
423
424
425
426
427
428
429
430
431
432
433
434
# File 'lib/rom/attribute.rb', line 422

def method_missing(meth, *args, &block)
  if type.respond_to?(meth)
    response = type.__send__(meth, *args, &block)

    if response.is_a?(type.class)
      self.class.new(response, options)
    else
      response
    end
  else
    super
  end
end

Instance Attribute Details

#typeDry::Types::Definition, ... (readonly)

Returns The attribute’s type object.

Returns:

  • (Dry::Types::Definition, Dry::Types::Sum, Dry::Types::Constrained)

    The attribute’s type object



24
# File 'lib/rom/attribute.rb', line 24

param :type

Instance Method Details

#[](input) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



27
28
29
# File 'lib/rom/attribute.rb', line 27

def [](input)
  type[input]
end

#aliasNilClass, Symbol

Return attribute’s alias

Examples:

class Tasks < ROM::Relation[:memory]
  schema do
    attribute :user_id, Types::Int.meta(alias: :id)
    attribute :name, Types::String
  end
end

Users.schema[:user_id].alias
# => :user_id

Users.schema[:name].alias
# => nil

Returns:

  • (NilClass, Symbol)


218
219
220
# File 'lib/rom/attribute.rb', line 218

def alias
  meta[:alias]
end

#aliased(name) ⇒ Attribute Also known as: as

Return new attribute type with provided alias

Examples:

class Tasks < ROM::Relation[:memory]
  schema do
    attribute :user_id, Types::Int
    attribute :name, Types::String
  end
end

aliased_user_id = Users.schema[:user_id].aliased(:id)

aliased_user_id.aliased?
# => true

aliased_user_id.name
# => :user_id

aliased_user_id.alias
# => :id

Parameters:

  • name (Symbol)

    The alias

Returns:



248
249
250
# File 'lib/rom/attribute.rb', line 248

def aliased(name)
  meta(alias: name)
end

#aliased?TrueClass, FalseClass

Return true if this attribute type is a foreign key

Examples:

class Tasks < ROM::Relation[:memory]
  schema do
    attribute :user_id, Types::Int.meta(alias: :id)
    attribute :name, Types::String
  end
end

Users.schema[:user_id].aliased?
# => true

Users.schema[:name].aliased?
# => false

Returns:

  • (TrueClass, FalseClass)


98
99
100
# File 'lib/rom/attribute.rb', line 98

def aliased?
  !meta[:alias].nil?
end

#eql?(other) ⇒ TrueClass, FalseClass

Check if the attribute type is equal to another

Parameters:

Returns:

  • (TrueClass, FalseClass)


344
345
346
# File 'lib/rom/attribute.rb', line 344

def eql?(other)
  other.is_a?(self.class) ? super : type.eql?(other)
end

#foreign_key?TrueClass, FalseClass

Return true if this attribute type is a foreign key

Examples:

class Tasks < ROM::Relation[:memory]
  schema do
    attribute :id, Types::Int
    attribute :user_id, Types.ForeignKey(:users)
  end
end

Users.schema[:user_id].foreign_key?
# => true

Users.schema[:id].foreign_key?
# => false

Returns:

  • (TrueClass, FalseClass)


75
76
77
# File 'lib/rom/attribute.rb', line 75

def foreign_key?
  meta[:foreign_key].equal?(true)
end

#inspectString Also known as: pretty_inspect

Return string representation of the attribute type

Returns:

  • (String)


332
333
334
# File 'lib/rom/attribute.rb', line 332

def inspect
  %(#<#{self.class}[#{type.name}] #{meta.map { |k, v| "#{k}=#{v.inspect}" }.join(' ')}>)
end

#keySymbol

Return tuple key

When schemas are projected with aliased attributes, we need a simple access to tuple keys

Examples:

class Tasks < ROM::Relation[:memory]
  schema do
    attribute :user_id, Types::Int.meta(alias: :id)
    attribute :name, Types::String
  end
end

Users.schema[:id].key
# :id

Users.schema.project(Users.schema[:id].aliased(:user_id)).key
# :user_id

Returns:

  • (Symbol)


195
196
197
# File 'lib/rom/attribute.rb', line 195

def key
  meta[:alias] || name
end

#meta(opts = nil) ⇒ Attribute

Return attribute type with additional meta information

Return meta information hash if no opts are provided

Parameters:

  • opts (Hash) (defaults to: nil)

    The meta options

Returns:



319
320
321
322
323
324
325
# File 'lib/rom/attribute.rb', line 319

def meta(opts = nil)
  if opts
    self.class.new(type.meta(opts))
  else
    type.meta
  end
end

#meta_astObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



410
411
412
413
414
415
# File 'lib/rom/attribute.rb', line 410

def meta_ast
  meta_keys = %i(wrapped alias primary_key)
  ast = meta.select { |k, _| meta_keys.include?(k) }
  ast[:source] = source.to_sym if source
  ast
end

#nameSymbol

Return the canonical name of this attribute name

This always returns the name that is used in the datastore, even when an attribute is aliased

Examples:

class Tasks < ROM::Relation[:memory]
  schema do
    attribute :user_id, Types::Int.meta(alias: :id)
    attribute :name, Types::String
  end
end

Users.schema[:id].name
# => :id

Users.schema[:user_id].name
# => :user_id

Returns:

  • (Symbol)


170
171
172
# File 'lib/rom/attribute.rb', line 170

def name
  meta[:name]
end

#optionalAttribute

Return nullable attribute

Returns:



381
382
383
384
# File 'lib/rom/attribute.rb', line 381

def optional
  sum = self.class.new(super, options)
  read? ? sum.meta(read: meta[:read].optional) : sum
end

#prefixed(prefix = source.dataset) ⇒ Attribute

Return new attribute type with an alias using provided prefix

Examples:

class Users < ROM::Relation[:memory]
  schema do
    attribute :id, Types::Int
    attribute :name, Types::String
  end
end

prefixed_id = Users.schema[:id].prefixed

prefixed_id.aliased?
# => true

prefixed_id.name
# => :id

prefixed_id.alias
# => :users_id

prefixed_id = Users.schema[:id].prefixed(:user)

prefixed_id.alias
# => :user_id

Parameters:

  • prefix (Symbol) (defaults to: source.dataset)

    The prefix (defaults to source.dataset)

Returns:



284
285
286
# File 'lib/rom/attribute.rb', line 284

def prefixed(prefix = source.dataset)
  aliased(:"#{prefix}_#{name}")
end

#primary_key?TrueClass, FalseClass

Return true if this attribute type is a primary key

Examples:

class Users < ROM::Relation[:memory]
  schema do
    attribute :id, Types::Int
    attribute :name, Types::String

    primary_key :id
  end
end

Users.schema[:id].primary_key?
# => true

Users.schema[:name].primary_key?
# => false

Returns:

  • (TrueClass, FalseClass)


52
53
54
# File 'lib/rom/attribute.rb', line 52

def primary_key?
  meta[:primary_key].equal?(true)
end

#read?TrueClass, FalseClass

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return if this attribute type has additional attribute type for reading tuple values

Returns:

  • (TrueClass, FalseClass)


354
355
356
# File 'lib/rom/attribute.rb', line 354

def read?
  ! meta[:read].nil?
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


387
388
389
# File 'lib/rom/attribute.rb', line 387

def respond_to_missing?(name, include_private = false)
  type.respond_to?(name) || super
end

#sourceSymbol, Relation::Name

Return source relation of this attribute type

Examples:

class Tasks < ROM::Relation[:memory]
  schema do
    attribute :id, Types::Int
    attribute :user_id, Types.ForeignKey(:users)
  end
end

Users.schema[:id].source
# => :tasks

Users.schema[:user_id].source
# => :tasks

Returns:



121
122
123
# File 'lib/rom/attribute.rb', line 121

def source
  meta[:source]
end

#targetNilClass, ...

Return target relation of this attribute type

Examples:

class Tasks < ROM::Relation[:memory]
  schema do
    attribute :id, Types::Int
    attribute :user_id, Types.ForeignKey(:users)
  end
end

Users.schema[:id].target
# => nil

Users.schema[:user_id].target
# => :users

Returns:



144
145
146
# File 'lib/rom/attribute.rb', line 144

def target
  meta[:target]
end

#to_astArray

Return AST for the type

Returns:

  • (Array)


396
397
398
# File 'lib/rom/attribute.rb', line 396

def to_ast
  [:attribute, [name, type.to_ast(meta: false), meta_ast]]
end

#to_read_astArray

Return AST for the read type

Returns:

  • (Array)


405
406
407
# File 'lib/rom/attribute.rb', line 405

def to_read_ast
  [:attribute, [name, to_read_type.to_ast(meta: false), meta_ast]]
end

#to_read_typeDry::Types::Type

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return read type

Returns:

  • (Dry::Types::Type)


363
364
365
# File 'lib/rom/attribute.rb', line 363

def to_read_type
  read? ? meta[:read] : type
end

#to_write_typeDry::Types::Type

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return write type

Returns:

  • (Dry::Types::Type)


372
373
374
# File 'lib/rom/attribute.rb', line 372

def to_write_type
  type
end

#wrapped(name = source.dataset) ⇒ Attribute

Return attribute type wrapped for the specified relation name

Parameters:

  • name (Symbol) (defaults to: source.dataset)

    The name of the source relation (defaults to source.dataset)

Returns:



306
307
308
# File 'lib/rom/attribute.rb', line 306

def wrapped(name = source.dataset)
  prefixed(name).meta(wrapped: true)
end

#wrapped?Boolean

Return if the attribute type is from a wrapped relation

Wrapped attributes are used when two schemas from different relations are merged together. This way we can identify them easily and handle correctly in places like auto-mapping.

Returns:

  • (Boolean)


295
296
297
# File 'lib/rom/attribute.rb', line 295

def wrapped?
  meta[:wrapped].equal?(true)
end