Skip to content

Database Classes

topofocus edited this page Dec 13, 2020 · 8 revisions

Plain Vanilla

start the ActiveOrientConsole

ORD.execute { "CREATE CLASS tnt" }
=> INFO->CREATE CLASS tnt

Tnt
=> NameError (uninitialized constant Tnt)

The database class is created. ActiveOrient is notified. But the class is not accessible.

The solution: Restart ActiveOrient – or use the following approach

Create API

ActiveOrient provides a simple API to create classes and class-hierarchies

ORD.create_class(class_name or list_of class_names ){ BaseClass }

{BaseClass}.create_class class_names

V and E are always present after creating a database. Thus

ORD.create_class        'class_document_name'  # creates a abstract document-class 
                                              # and maps it to ClassDocumentName

V.create_class 'vertex_name'                   # creates a vertex-class
                                              # and maps it to VertexName
E.create_class   'edge_name'                   # creates an edge-class, providing bidirectional links between documents
29.03.(08:08:46) INFO->CREATE CLASS edge_name EXTENDS E
=> EdgeName 

Create multiple database-classes at once and display hierarchy and existing Ruby-Classes

V.create_class(:base, :first_list, :second_list )
29.03.(06:19:08) INFO->CREATE CLASS base EXTENDS V
29.03.(06:19:09) INFO->CREATE CLASS first_list EXTENDS V
29.03.(06:19:09) INFO->CREATE CLASS second_list EXTENDS V
 => [Base, FirstList, SecondList] 

puts ORD.class_hierarchy.to_yaml
---
- E
- - V
  - - base
    - first_list
    - second_list

puts ActiveOrient::show_classes
---------------------------------------------
Database Class  ->  ActiveOrient ClassName
---------------------------------------------
              E ->  E
              V ->  V
           base ->  Base
     first_list ->  FirstList
    second_list ->  SecondList
---------------------------------------------

Inheritance

The creation of extended classes is not limited to E and V.

  V.create_class  :sector
  Sector.create_class :industry, :category, :subcategory 
  
  Industry.create name: 'Communications'   #--->   Create an Industry-Record with the attribute "name"
  Sector.where  name: 'Communications'	   #--->   an Array with the Industry-Object
  => [#<Industry:0x0000000225e098 @metadata= (...) ] 

Naming-Convention

The name given in the create-class-Statement becomes the DatabaseClassname.

The default action is to camelized, ie: V.create_class(:hut_ab) generates a Ruby-Class HutAb.

This can be customized in the naming_convention-class-method.

To change the Ruby-Class-Name to uppercase put this method to model/e.rb

class E 
      def self.naming_convention name=nil
          name.present? ? name.upcase : ref_name.upcase
      end
end

Namespace Support

Consider a project, where different tasks are clearly separated.

A common case is, to concentrate any gathering of raw data in a separate module, maybe even in a gem.

ActiveOrient enables this by switching the »ActiveOrient::Model.namespace« directive.

The Default Case

Databsase-Classes are mapped to the Object-Layer

ActiveOrient::Init.define_namespace namespace: :object  

Activate Namespace

to activate the namespace "HC" run

module HC; end
ActiveOrient::Init.define_namespace { HC }
 => HC 
V.create_vertex_class :new_list
INFO->CREATE CLASS hc_new_list EXTENDS V
 => HC::NewList 
puts ActiveOrient::show_classes
---------------------------------------------
Database Class  ->  ActiveOrient ClassName
---------------------------------------------
              E ->  E
              V ->  V
           base ->  Base
     first_list ->  FirstList
    second_list ->  SecondList
    hc_new_list ->  HC::NewList
---------------------------------------------

Prefixed Classnames to Avoid Ambiguous Identifiers

OrientDB-Classnames follow a class-hierarchy but namespacing is not implemented. We are mocking Namespace-Support through prefixing.

ActiveOrient::Model.namespace_prefix translates a single namespace into a database-prefix:

ActiveOrient::Init.define_namespace namespace: :object
ActiveOrient::OrientDB.new  preallocate: true
ActiveOrient::Init.define_namespace { HH  }
ActiveOrient::OrientDB.new  preallocate: true
ActiveOrient::Init.define_namespace { HY }
ActiveOrient::OrientDB.new  preallocate: true

note The preallocation-algorithm tries to load any class. If the classes "tg_hui, ib_hui, hui" are present, "TgHui,IbHui,Hui" are created during the basic initialization of ActiveOrient (Namespace: Object). If ActiveOrient::Model.keep_models_without_file is set to false, classes are allocated only, if a model-file is present.

As a result something like this appears:

---------------------------------------------
Database Class  ->  ActiveOrient Class
---------------------------------------------
              E ->  E
              V ->  V
  hh_hipp_hurra ->  HH::HippHurra
       hh_hurra ->  HH::Hurra
     hipp_hurra ->  HippHurra
          hurra ->  Hurra
  hy_hipp_hurra ->  HY::HippHurra
       hy_hurra ->  HY::Hurra
---------------------------------------------

By changing the namespace-scope with ActiveOrient::Init.define_namespace its always possible to change properties, include links and edges or to add and remove classes in the Sub-Modules.

ORD.create_class "hurry" creates a Ruby-Class HH::Hurry and a DatabaseClass hh_hurry. This can be changed through redefinition of ActiveOrient::Model.namespace_prefix

## Deactivate Namespace-Prefix
class ActiveOrient::Model
  def self.namespace_prefix
  ""
  end
end

Preallocation and Cashing

All database-classes are preallocated after connecting to the database. Thus you can use Model-Classes from the start.

If the "rid" is known, any Object can be retrieved and correctly allocated by rid.expand

  the_object =  "#xx:yy".expand
  --->  {ActiveOrient::Model} Object 

Class Hierarchy

All preallocated database classes and their relationship to ruby-classes is stored in ActiveOrient.database_classes

=> {"Contracts"=>Contracts, "E"=>E, "V"=>V, "base"=>Base, "first_list"=>FirstList,  "second_list"=>SecondList} 

Complex hierarchies can be analyzed with pp ORD.class_hierarchy( base_class: 'V' )

["hc_account_values",
 ["hc_accounts", ["hc_advisors", "hc_users"]],
 "hc_contracts",
 "hc_portfolio_values",
 ["tg_time_base", ["tg_jahr", "tg_monat", "tg_stunde", "tg_tag"]]]

and even further

ORD.class_hierarchy( base_class: 'tg_time_base' )
 => ["tg_jahr", "tg_monat", "tg_stunde", "tg_tag"] 
Clone this wiki locally