Class: ROM::Struct

Inherits:
Dry::Struct
  • Object
show all
Defined in:
lib/rom/struct.rb

Overview

Simple data-struct class

ROM structs are plain data structures loaded by repositories. They implement Hash protocol which means that they can be used in places where Hash-like objects are supported.

Repositories define subclasses of ROM::Struct automatically, they are defined in the ROM::Struct namespace by default, but you set it up to use your namespace/module as well.

Structs are based on dry-struct gem, they include schema with detailed information about attribute types returned from relations, thus can be introspected to build additional functionality when desired.

There is a caveat you should know about when working with structs. Struct classes have names but at the same time they're anonymous, i.e. you can't get the User struct class with ROM::Struct::User. ROM will create as many struct classes for User as needed, they all will have the same name and ROM::Struct::User will be the common parent class for them. Combined with the ability to provide your own namespace for structs this enables to pre-define the parent class.

Examples:

accessing relation struct model

rom = ROM.container(:sql, 'sqlite::memory') do |conf|
  conf.default.create_table(:users) do
    primary_key :id
    column :name, String
  end
end

class UserRepo < ROM::Repository[:users]
end

user_repo = UserRepo.new(rom)

# get auto-generated User struct
model = user_repo.users.mapper.model
# => ROM::Struct::User

# see struct's schema attributes

# model.schema.key(:id)
# => #<Dry::Types[id: Nominal<Integer meta={primary_key: true, source: :users}>]>

model.schema[:name]
# => #<Dry::Types[name: Sum<Nominal<NilClass> | Nominal<String> meta={source: :users}>]>

passing a namespace with an existing parent class

module Entities
  class User < ROM::Struct
    def upcased_name
      name.upcase
    end
  end
end

class UserRepo < ROM::Repository[:users]
  struct_namespace Entities
end

user_repo = UserRepo.new(rom)
user = user_repo.users.by_pk(1).one!
user.name # => "Jane"
user.upcased_name # => "JANE"

See Also:

Constant Summary collapse

MissingAttribute =
Class.new(NameError) do
  def initialize(&block)
    super
    @message_proc = block
  end

  def message
    @message_proc.call
  end
end

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missingObject (private)


102
103
104
105
106
# File 'lib/rom/struct.rb', line 102

def method_missing(*)
  super
rescue NameError => e
  raise MissingAttribute.new { "#{e.message} (attribute not loaded?)" }
end

Instance Method Details

#fetch(name) ⇒ Object

Return attribute value

Parameters:

  • name (Symbol)

    The attribute name


91
92
93
# File 'lib/rom/struct.rb', line 91

def fetch(name)
  __send__(name)
end

#respond_to_missing?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)

96
97
98
# File 'lib/rom/struct.rb', line 96

def respond_to_missing?(*)
  super
end