module ModelClass

Public Instance Methods

all() click to toggle source

get all the elements of the class

# File lib/model/the_class.rb, line 395
def all
              query.execute
end
alter_property(property, attribute: "DEFAULT", alteration: orientdb.alter_property self, property: property, attribute: attribute, alteration: alteration) click to toggle source

See orientdb.com/docs/2.1/SQL-Alter-Property.html

# File lib/model/the_class.rb, line 651
def alter_property property, attribute: "DEFAULT", alteration:  # :nodoc:
  orientdb.alter_property self, property: property, attribute: attribute, alteration: alteration
end
count(**args) click to toggle source

Used to count of the elements in the class

Examples

TestClass.count where: 'last_access is NULL'  # only records where 'last_access' is not set
TestClass.count                               # all records
# File lib/model/the_class.rb, line 417
def count **args
              query( **( { projection:  'COUNT(*)' }.merge args )).execute(reduce: true){|x|  x[:"COUNT(*)"]}
end
create(**attributes) { |result| ... } click to toggle source

Universal method to create a new record. It's overloaded to create specific kinds, eg. edge and vertex and is called only for abstract classes

Example:

V.create_class :test
Test.create string_attribute: 'a string', symbol_attribute: :a_symbol, array_attribute: [34,45,67]
Test.create link_attribute: Test.create( :a_new_attribute => 'new' )
# File lib/model/the_class.rb, line 174
def create **attributes
  attributes.merge :created_at => DateTime.new
              result = db.create_record self, attributes: attributes
              if result.nil
                      logger.error('Model::Class'){ "Table #{refname}:  create failed:  #{attributes.inspect}" }
              elsif block_given?
                      yield result
              else
                      result  # return value
              end
      end
create_class(*c) click to toggle source

creates an inherent class

# File lib/model/the_class.rb, line 158
def create_class *c
        orientdb.create_class( *c ){ self }
end
create_index(name, **attributes) click to toggle source

Add an Index

Parameters:

                                         name (string / symbol), 
[ on: :automatic / single Column, Array of Columns,
[ type: :unique, :nonunique, :dictionary,:fulltext, {other supported index-types} ]]

Default:

on: :automatic
type: :unique

Example

ORD.create_vertex_class :pagination
  Pagination.create_property :col1 , type: :string
           Pagination.create_property :col2, type: :integer
           Pagination.create_property :col3, type: :string
           Pagination.create_property :col4, type: :integer
           Pagination.create_index :composite,  :on => [:col1, :col2, :col3], type: 'dictionary'
# File lib/model/the_class.rb, line 345
def create_index name, **attributes
  orientdb.create_index self, name: name, **attributes
end
create_properties(argument_hash, &b) click to toggle source

Create more Properties in the Schema of the Class

# File lib/model/the_class.rb, line 320
def create_properties argument_hash, &b
  orientdb.create_properties self, argument_hash, &b
end
create_property(field (required), click to toggle source
type: :a_supported_type',
linked_class: nil

Create a Property in the Schema of the Class and optionally create an automatic index

Examples:

create_property  :customer_id, type: :integer, index: :unique
create_property(  :name, type: :string ) {  :unique  }
create_property(  :name, type: :string ) { name: 'some_index', on: :automatic, type: :unique  }
create_property  :in,  type: :link, linked_class: V    (used by edges)

supported types:

:bool         :double       :datetime  = :date    :float        :decimal      
:embedded_list = :list      :embedded_map = :map        :embedded_set = :set          
:int          :integer      :link_list    :link_map     :link_set

If `:list`, `:map`, `:set`, `:link`, `:link_list`, `:link_map` or `:link_set` is specified a `linked_class:` parameter can be specified. Argument is the OrientDB-Class-Constant

# File lib/model/the_class.rb, line 255
def create_property field, type: :integer, index: nil,  **args
              arguments =  args.values.map do |y| 
                      if y.is_a?(Class)  && ActiveOrient.database_classes.values.include?(y) 
                              y.ref_name 
                      elsif  ActiveOrient.database_classes.keys.include?(y.to_s) 
                              y 
                      else
                              puts ActiveOrient.database_classes.inspect
                              puts "YY : #{y.to_s} #{y.class}"
                              raise ArgumentError , "database class #{y.to_s} not allocated"
                      end
              end.compact.join(',')

              supported_types = {
                      :bool          => "BOOLEAN",
                      :double        => "BYTE",
                      :datetime      => "DATE",
                      :date                             => "DATE",
                      :float         => "FLOAT",
                      :decimal       => "DECIMAL",
                      :embedded_list => "EMBEDDEDLIST",
                      :list          => "EMBEDDEDLIST",
                      :embedded_map  => "EMBEDDEDMAP",
                      :map           => "EMBEDDEDMAP",
                      :embedded_set  => "EMBEDDEDSET",
                      :set           => "EMBEDDEDSET",
                      :string        => "STRING",
                      :int           => "INTEGER",
                      :integer       => "INTEGER",
                      :link          => "LINK",
                      :link_list     => "LINKLIST",
                      :link_map      => "LINKMAP",
                      :link_set      => "LINKSET",
              }

              ## if the »type« argument is a string, it is used unchanged
              type =  supported_types[type] if type.is_a?(Symbol)

              raise ArgumentError , "unsupported type" if type.nil?
      s= " CREATE PROPERTY #{ref_name}.#{field} #{type} #{arguments}" 
      puts s
      db.execute {  s }

      i =  block_given? ? yield : index
      ## supported format of block:  index: { name: 'something' , on: :automatic, type: :unique }
      ## or                                 { name: 'something' , on: :automatic, type: :unique }  #
      ## or                                 {                                some_name: :unique }  # manual index
      ## or                                 {                                           :unique }  # automatic index
      if i.is_a? Hash  
              att=  i.key( :index ) ?   i.values.first : i
              name, on, type = if  att.size == 1  && att[:type].nil? 
                                                                                       [att.keys.first,  field,  att.values.first ]
                                                                               else  
                                                                                       [ att[:name] || field , att[:on] || field , att[:type] || :unique ]
                                                                               end
              create_index( name , on: on, type: type)
      elsif i.is_a?(Symbol)  || i.is_a?(String)
              create_index field, type: i
      end

      # orientdb.create_property self, field, **keyword_arguments, &b
      end
custom_where(*attributes)
Alias for: where
delete(where: {})
Alias for: delete_records
delete_document(*rid)
Alias for: delete_record
delete_property(field) click to toggle source

Delete a property from the class

# File lib/model/the_class.rb, line 584
def delete_property field
  orientdb.delete_property self, field
end
delete_record(*rid) click to toggle source

Delete record(s) specified by their rid's

# File lib/model/the_class.rb, line 590
def delete_record *rid
  db.delete_record rid
end
Also aliased as: delete_document
delete_records(where: {}) click to toggle source

Query the database and delete the records of the resultset

Returns the count of datasets effected

# File lib/model/the_class.rb, line 598
def delete_records where: {} , **args
              if args[:all] == true 
                      where = {}
              else
                      where.merge!(args) if where.is_a?(Hash)
                      return 0 if where.empty?
              end
  orientdb.delete_records( self, where: where   ).count
      end
Also aliased as: delete
first(**args) click to toggle source

get the first element of the class

# File lib/model/the_class.rb, line 401
def first **args
  query( **( { order: "@rid" , limit: 1 }.merge args)).execute(reduce: true)
      end
get(rid) click to toggle source

get elements by rid

# File lib/model/the_class.rb, line 385
def get rid
  if @excluded.blank?
    db.get_record(rid)
  else
    db.execute{ "select expand( @this.exclude( #{@excluded.map(&:to_or).join(",")})) from #{rid} "} 
  end
end
get_class_properties()
Alias for: properties
get_documents(**args)
Alias for: get_records
get_records(**args) click to toggle source

»GetRecords« uses the REST-Interface to query the database. The alternative »QueryDatabase« submits the query via Execute.

Both methods rely on OrientSupport::OrientQuery and its capacity to support complex query-builds. The method requires a hash of arguments. The following keys are supported:

projection:

SQL-Queries use »select« to specify a projection (ie. `select sum(a), b+5 as z from class where …`)

In ruby »select« is a method of enumeration. To specify what to »select« from in the query-string we use »projection«, which accepts different arguments

projection: a_string --> inserts the sting as it appears
projection: an OrientSupport::OrientQuery-Object --> performs a sub-query and uses the result for further querying though the given parameters.
projection: [a, b, c] --> "a, b, c" (inserts a comma-separated list)
projection: {a: b, "sum(x)" => f} --> "a as b, sum(x) as f" (renames properties and uses functions)

distinct:

Constructs a query like »select distinct(property) [as property] from …«

distinct: :property -->  the result is mapped to the property »distinct«.
distinct: [:property] --> the result replaces the property
distinct: {property: :some_name} -->  the result is mapped to ModelInstance.some_name

order:

Sorts the result-set. If new properties were introduced via select:, distinct: etc. Sorting takes place on these properties

 order: :property {property: asc, property: desc}[property, property, ..  ](orderdirection is 'asc')

Further supported Parameter:

group_by
skip
limit
unwind

see orientdb- documentation (https://orientdb.com/docs/last/SQL-Query.html)

query:

Instead of providing the parameter to »get_records«, a OrientSupport::OrientQuery can build and tested prior to the method-call. The OrientQuery-Object is then provided with the query-parameter. I.e.

q = OrientSupport::OrientQuery.new
ORD.create_class :test_model
   q.from TestModel
   q.where {name: 'Thomas'}
   count = TestModel.count query: q
   q.limit 10
   0.step(count,10) do |x|
      q.skip = x
      puts TestModel.get_documents(query: q).map{|x| x.adress }.join('\t')
   end
  prints a Table with 10 columns.
# File lib/model/the_class.rb, line 496
def get_records **args
  db.get_records(from: self, **args){self}
end
Also aliased as: get_documents
indexes() click to toggle source

list all Indexes

# File lib/model/the_class.rb, line 350
def indexes
        properties[:indexes]
end
last(**args) click to toggle source

get the last element of the class

# File lib/model/the_class.rb, line 408
def last **args
  query( **( { order: {"@rid" => 'desc'} , limit: 1 }.merge args)).execute(reduce: true)
      end
migrate_property(property, to: , linked_class: nil, via: 'tzr983') click to toggle source
# File lib/model/the_class.rb, line 355
        def migrate_property property, to: , linked_class: nil, via: 'tzr983'
                if linked_class.nil?
                        create_property  via, type: to
                else
                        create_property  via, type: to, linked_class: linked_class
                end
#                       my_count = query.kind(:update!).set( "#{via} = #{property} ").execute(reduce: true){|c| c[:count]}
#                       logger.info{" migrate property: #{count} records prosessed"}
                  all.each{ |r| r.update set:{ via => r[property.to_sym] }}
                        nullify =  query.kind(:update!).set( property: nil ).execute(reduce: true){|c| c[:count]}
#                 raise "migrate property: count of erased items( #{nullify} differs from total count (#{my_count}) " if nullify != my_count
                        db.execute{" alter property #{ref_name}.#{via} name '#{property}' "}
                        logger.info{ "successfully migrated #{property} to #{:to} " }








        end
namespace_prefix() click to toggle source

Set the namespace_prefix for database-classes.

If a namespace is set by

ActiveOrient::Init.define_namespace { ModuleName }

ActiveOrient translates this to

ModuleName::CamelizedClassName

The database-class becomes

modulename_class_name

If the namespace is set to a class (Object, ActiveOrient::Model ) namespace_prefix returns an empty string.

Override to change its behavior

# File lib/model/the_class.rb, line 51
def namespace_prefix 
  namespace.is_a?(Class )? '' : namespace.to_s.downcase+'_' 
end
naming_convention(name=nil) click to toggle source

NamingConvention provides a translation from database-names to class-names.

It can be overwritten to provide different conventions for different classes, eg. Vertexes or edges and to introduce distinct naming-conventions in different namespaces

To overwrite use

 class Model # < ActiveOrient::Model[:: ...]
   def self.naming_convention
   ( conversion code )
   end
end
# File lib/model/the_class.rb, line 25
def naming_convention name=nil  
  nc =  name.present?? name.to_s : ref_name
   if namespace_prefix.present?
       nc.split(namespace_prefix).last.camelize
   else
     nc.camelize
   end
      rescue
              nil
end
orientdb_class(name:, superclass: nil ActiveOrient.database_classes[name.to_s].presence || ActiveOrient::Model) click to toggle source

orientdb_class is used to refer a ActiveOrient:Model-Object providing its name

Parameter: name: string or symbol

# File lib/model/the_class.rb, line 60
def orientdb_class name:, superclass: nil  # :nodoc:    # public method: autoload_class

  ActiveOrient.database_classes[name.to_s].presence || ActiveOrient::Model
rescue NoMethodError => e
  logger.error { "Error in orientdb_class: is ActiveOrient.database_classes initialized ? \n\n\n" }
  logger.error{ e.backtrace.map {|l| "  #{l}\n"}.join  }
  Kernel.exit
end
print_properties() click to toggle source

Print the properties of the class

properties() click to toggle source

Get the properties of the class

# File lib/model/the_class.rb, line 423
def properties
  object = orientdb.get_class_properties self
  {:properties => object['properties'], :indexes => object['indexes']}
end
Also aliased as: get_class_properties
query(**args) click to toggle source

returns a OrientSupport::OrientQuery

# File lib/model/the_class.rb, line 188
def query **args
        OrientSupport::OrientQuery.new( **( {from: self}.merge args))
end
query_database(query, set_from: true) { |x| ... } click to toggle source

QueryDatabase sends the Query directly to the database.

The query returns a hash if a result set is expected

select  {something} as {result} (...)

leads to

[ { :{result}  =>  {result of query} } ]

It can be modified further by passing a block, ie.

    q =  OrientSupport::OrientQuery.new( from: :base )
                                           .projection( 'first_list[5].second_list[9] as second_list' )
                                           .where( label: 9 )

q.to_s  => 'select first_list[5].second_list[9] as second_list from base where label = 9 '

            second_list = Base.query_database( q ){|x|  x[:second_list]}.first

The query returns (a list of) documents of type ActiveOrient::Model if a document is queried i.e.

q =  OrientSupport::OrientQuery.new  from: :base
q.projection  'expand( first_list[5].second_list[9])'  #note: no 'as' statement
result2 = Base.query_database( q ).first
=> #<SecondList:0x000000000284e840 @metadata={}, @d=nil, @attributes={:zobel=>9, "@class"=>"second_list"}>

query_database is used on model-level and submits

select (...) from class

query performs queries on the instance-level and submits

select (...) from #{a}:{b}
# File lib/model/the_class.rb, line 564
def query_database query, set_from: true
  # note: the parameter is not used anymore
              query.from self if query.is_a?(OrientSupport::OrientQuery) && query.from.nil?
  result = db.execute{  query.to_s  }
              result = if block_given?
                                                       result.is_a?(Array) ? result.map{|x| yield(x) } : yield(result)
                                               else
                                                       result
                                               end
  if result.is_a? Array  
    OrientSupport::Array.new work_on: self, work_with: result
  else
    result
  end  # return value
end
require_model_file(dir = nil) click to toggle source

requires the file specified in the model-dir

In fact, the model-files are loaded instead of required. Thus, even after recreation of a class (Class.delete_class, ORD.create_class classname) custom methods declared in the model files are present.

If a class is destroyed (i.e. the database class is deleted), the ruby-class and its methods vanish, too.

The directory specified is expanded by the namespace. The parameter itself is the base-dir.

Example:

Namespace:  HC
model_dir : 'lib/model'
searched directory: 'lib/model/hc'

ActiveOrient::Model.modeldir is aimed to be set to the application dir. It may be a String, Pathname or an array of strings or pathnames.

The parameter `dir` is used internally and by gems to ensure that basic methods are loaded first.

# File lib/model/the_class.rb, line 111
def require_model_file  dir = nil
        logger.progname = 'ModelClass#RequireModelFile'
        # model-dir can either be a string or an array of string or pathnames
        default =  [ActiveOrient::Model.model_dir].flatten
        # access the default dir's first
        the_directories = case dir
                                                                                when String, Pathname
                                                                                  default.present? ?  [dir] + default : [dir]
                                                                                when Array
                                                                                        default.present? ? dir + default  : dir
                                                                                else
                                                                                        default.present? ? default : []
                                                                                end.uniq.compact
        the_directories.uniq.map do |raw_directory|
                the_directory = Pathname( raw_directory )
                if File.exists?( the_directory )
                        model= self.to_s.underscore + ".rb"
                        filename =   the_directory +  model
                        if  File.exists?(filename )
                                if load filename
                                        logger.debug{ "#{filename} sucessfully loaded"  }
                                        self #return_value
                                else
                                        logger.error{ "#{filename} load error" }
                                        nil #return_value
                                end
                        else
                                logger.debug{ "model-file not present: #{filename}  --> skipping" }
                                nil #return_value
                        end
                else
                        logger.error{ "Directory #{ the_directory  } not present " }
                        nil  #return_value
                end
        end.compact.present?  # return true only if at least one model-file is present

        rescue TypeError => e
                puts "THE CLASS#require_model_file -> TypeError:  #{e.message}" 
                puts "Working on #{self.to_s} -> #{self.superclass}"
                puts "Class_hierarchy: #{orientdb.class_hierarchy.inspect}."
                print e.backtrace.join("\n") 
                raise
                #
        end
update(where: , set: {}) click to toggle source

same as update!, but returns a list of updated records

# File lib/model/the_class.rb, line 227
def update where:  , set: {},  **arg
        # In OrientDB V.3 the database only returns the affected rid's
        # We have to update the contents manually, this is done in the execute-block
        query( kind: :update, set: set.merge(arg), where: where).execute{|y| y[:$current].reload!}
end
update!(where: nil , set: {}) click to toggle source

Sets a value to certain attributes, overwrites existing entries, creates new attributes if necessary

returns the count of affected records

IB::Account.update connected: false
IB::Account.update where: "account containsText 'F'", set:{ connected: false }

# or

IB::Account.update  connected: false, where: "account containsText 'F'"
# File lib/model/the_class.rb, line 219
def update! where: nil , set: {},  **arg
              query( kind: :update!, set: set.merge(arg), where: where).execute(reduce: true){|y| y[:count]}
end
Also aliased as: update_all
update_all(where: nil , set: {})
Alias for: update!
upsert(set: nil, where: , **args) click to toggle source

Creates or updates records. Parameter:

  • set: A hash of attributes to insert or update unconditionally

  • where: A string or hash as condition which should return just one record.

The where-part should be covered with an unique-index.

returns the affected record, if the where-condition is set properly. Otherwise upsert acts as »update« and returns all updated records (as array).

# File lib/model/the_class.rb, line 204
def upsert set: nil, where: , **args
              set = where if set.nil?
              query( **args.merge( kind: :upsert, set: set, where: where )).execute(reduce: true){|y| y[:$current].reload!}
end
where(*attributes) click to toggle source

Performs a query on the Class and returns an Array of ActiveOrient:Model-Records.

Fall-back method, is overloaded by Vertex.where

Is aliased by »custom_where»

Example:

Log.where priority: 'high'
# File lib/model/the_class.rb, line 520
def where *attributes 
  q= OrientSupport::OrientQuery.new  where: attributes 
  query_database( q)
end
Also aliased as: custom_where