Class: Appfuel::Repository::Mapper

Inherits:
Object
  • Object
show all
Defined in:
lib/appfuel/storage/repository/mapper.rb

Overview

The mapping registry holds all entity to db mappings. Mappings are contained within a DbEntityMapEntry object and are arranged by entity name. Each entity will hold a hash where the keys are the attribute names and the value is the entry

Direct Known Subclasses

Db::Mapper, Memory::Mapper

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app_name, map = nil) ⇒ Mapper

Returns a new instance of Mapper.



10
11
12
13
14
15
16
# File 'lib/appfuel/storage/repository/mapper.rb', line 10

def initialize(app_name, map = nil)
  @container_root_name = app_name
  if !map.nil? && !map.is_a?(Hash)
    fail "repository mappings must be a hash"
  end
  @map = map
end

Instance Attribute Details

#container_root_nameObject (readonly)

Returns the value of attribute container_root_name.



8
9
10
# File 'lib/appfuel/storage/repository/mapper.rb', line 8

def container_root_name
  @container_root_name
end

Instance Method Details

#create_entity_hash(domain_attr, value) ⇒ Object



205
206
207
208
209
# File 'lib/appfuel/storage/repository/mapper.rb', line 205

def create_entity_hash(domain_attr, value)
  domain_attr.split('.').reverse.inject(value) do |result, nested_attr|
    {nested_attr => result}
  end
end

#each_entity_attr(entity_name) {|attr, entry| ... } ⇒ void

This method returns an undefined value.

Iterates over all entries for a given entity

Parameters:

  • entity_name (String)

    qualified entity name “<feature>.<entity>”

Yields:

  • (attr, entry)

    expose the entity attr name and entry



79
80
81
82
83
84
# File 'lib/appfuel/storage/repository/mapper.rb', line 79

def each_entity_attr(entity_name)
  validate_domain(entity_name)
  map[entity_name].each do |_attr, entry|
    yield entry
  end
end

#entity?(entity_name) ⇒ Boolean

Determine if an entity has been added

Parameters:

  • entity (String)

Returns:

  • (Boolean)


41
42
43
# File 'lib/appfuel/storage/repository/mapper.rb', line 41

def entity?(entity_name)
  map.key?(entity_name)
end

#entity_attr?(entity_name, entity_attr) ⇒ Boolean

Determine if an attribute is mapped for a given entity

Parameters:

  • entity (String)

    name of the entity

  • attr (String)

    name of the attribute

Returns:

  • (Boolean)


50
51
52
53
54
# File 'lib/appfuel/storage/repository/mapper.rb', line 50

def entity_attr?(entity_name, entity_attr)
  return false unless entity?(entity_name)

  map[entity_name].key?(entity_attr)
end

#entity_value(domain, map_entry) ⇒ Object



194
195
196
197
198
199
200
201
202
203
# File 'lib/appfuel/storage/repository/mapper.rb', line 194

def entity_value(domain, map_entry)
  value = resolve_entity_value(domain, map_entry.domain_attr)
  if map_entry.computed_attr?
    value = map_entry.computed_attr(value, domain)
  end

  value = nil if undefined?(value)

  value
end

#expr_conjunction?(value) ⇒ Boolean

Returns:

  • (Boolean)


225
226
227
# File 'lib/appfuel/storage/repository/mapper.rb', line 225

def expr_conjunction?(value)
  value.instance_of?(ExprConjunction)
end

#find(entity_name, entity_attr) ⇒ Boolean

Returns a mapping entry for a given entity

Parameters:

  • entity_name (String)

    qualified entity name “<feature>.<entity>”

  • entity_attr (String)

    name of the attribute

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    when entity not found

  • (RuntimeError)

    when attr not found



64
65
66
67
68
69
70
71
# File 'lib/appfuel/storage/repository/mapper.rb', line 64

def find(entity_name, entity_attr)
  validate_domain(entity_name)

  unless map[entity_name].key?(entity_attr)
    fail "Entity (#{entity_name}) attr (#{entity_attr}) is not registered"
  end
  map[entity_name][entity_attr]
end

#mapHash

The map represents domain mappings to one or more storage systems. Currently one map represents all storage. So if you have a file, and database storage for a given domain the storage attributes are the same for each interface. This will load the repository mappings from the application container if no map as been manually set.

Examples:

a map has the following structure

{
  domain_name: {
    domain_attr1: <MappingEntry>,
    domain_attr1: <MappingEntry>
  }
  ...
}

Returns:

  • (Hash)


33
34
35
# File 'lib/appfuel/storage/repository/mapper.rb', line 33

def map
  @map ||= mappings_from_container
end

#resolve_entity_value(domain, entity_attr) ⇒ Object



215
216
217
218
219
220
221
222
223
# File 'lib/appfuel/storage/repository/mapper.rb', line 215

def resolve_entity_value(domain, entity_attr)
  chain  = entity_attr.split('.')
  target = domain
  chain.each do |attr_method|
    return nil unless target.respond_to?(attr_method)
    target = target.public_send(attr_method)
  end
  target
end

#storage_attr(entity_name, entity_attr) ⇒ String

Returns a column name for an entity’s attribute

Parameters:

  • entity_name (String)

    qualified entity name “<feature>.<entity>”

  • entity_attr (String)

    name of the attribute

Returns:

  • (String)

Raises:

  • (RuntimeError)

    when entity not found

  • (RuntimeError)

    when attr not found



107
108
109
# File 'lib/appfuel/storage/repository/mapper.rb', line 107

def storage_attr(entity_name, entity_attr)
  find(entity_name, entity_attr).storage_attr
end

#storage_attr_mapped?(entity_name, storage_attr) ⇒ Boolean

Determine if an column is mapped for a given entity

Parameters:

  • entity_name (String)

    qualified entity name “<feature>.<entity>”

  • storage_attr (String)

    name the persistence attr

Returns:

  • (Boolean)


91
92
93
94
95
96
97
# File 'lib/appfuel/storage/repository/mapper.rb', line 91

def storage_attr_mapped?(entity_name, storage_attr)
  each_entity_attr(entity_name) do |entry|
    return true if storage_attr == entry.storage_attr
  end

  false
end

#storage_class(entity_name, entity_attr, type) ⇒ Object

Returns the storage class based on type mapping foo.bar, db: auth.foo_bar,

Parameters:

  • entity (String)

    name of the entity

  • attr (String)

    name of the attribute

Returns:

  • (Object)

Raises:

  • (RuntimeError)

    when entity not found

  • (RuntimeError)

    when attr not found

  • (Dry::Contriner::Error)

    when db_class is not registered



121
122
123
124
# File 'lib/appfuel/storage/repository/mapper.rb', line 121

def storage_class(entity_name, entity_attr, type)
  entry = find(entity_name, entity_attr)
  storage_class_from_entry(entry, type)
end

#storage_class_from_entry(entry, type) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/appfuel/storage/repository/mapper.rb', line 126

def storage_class_from_entry(entry, type)
  unless entry.storage?(type)
    fail "No (#{type}) storage has been mapped"
  end

  container_name = entry.container_name
  unless container_root_name == container_name
    fail "You can not access a mapping outside of this container " +
      "(mapper: #{container_root_name}, entry: #{container_name})"
  end
  app_container = Appfuel.app_container(entry.container_name)
  key = entry.storage(type)
  app_container[key]
end

#to_entity_hash(domain_name, storage) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/appfuel/storage/repository/mapper.rb', line 141

def to_entity_hash(domain_name,  storage)
  entity_attrs = {}
  storage_data = storage_hash(storage)
  each_entity_attr(domain_name) do |entry|
    attr_name   = entry.storage_attr
    domain_attr = entry.domain_attr
    next unless storage_data.key?(attr_name)
    update_entity_hash(domain_attr, storage_data[attr_name], entity_attrs)
  end

  entity_attrs
end

#to_storage(domain, type, opts = {}) ⇒ Hash

Convert the domain into a hash of storage attributes that represent. Each storage class has its own hash of mapped attributes. A domain can have more than one storage class.

Parameters:

  • domain (Appfuel::Domain::Entity)
  • type (Symbol)

    type of storage :db, :file, :memory etc…

  • opts (Hash) (defaults to: {})
  • exclued (Hash)

    a customizable set of options

Returns:

  • (Hash)

    each key is a storage class with a hash of column name/value



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/appfuel/storage/repository/mapper.rb', line 165

def to_storage(domain, type, opts = {})
  unless domain.respond_to?(:domain_name)
    fail "Domain entity must implement :domain_name"
  end

  excluded = opts[:exclude] || []
  data     = {}
  each_entity_attr(domain.domain_name) do |entry|
    unless entry.storage?(type)
      "storage type (#{type}) is not support for (#{domain.domain_name})"
    end
    storage_attr  = entry.storage_attr
    storage_class = entry.storage(type)
    next if excluded.include?(storage_attr) || entry.skip?

    data[storage_class] = {} unless data.key?(storage_class)
    data[storage_class][storage_attr] = entity_value(domain, entry)
  end
  data
end

#undefined?(value) ⇒ Boolean

Returns:

  • (Boolean)


211
212
213
# File 'lib/appfuel/storage/repository/mapper.rb', line 211

def undefined?(value)
  value == Types::Undefined
end

#update_entity_hash(domain_attr, value, hash) ⇒ Object



186
187
188
189
190
191
192
# File 'lib/appfuel/storage/repository/mapper.rb', line 186

def update_entity_hash(domain_attr, value, hash)
  if domain_attr.include?('.')
    hash.deep_merge!(create_entity_hash(domain_attr, value))
  else
    hash[domain_attr] = value
  end
end