Class: Arcade::Vertex

Inherits:
Base
  • Object
show all
Extended by:
Support::Model
Includes:
Support::Model
Defined in:
lib/model/vertex.rb

Direct Known Subclasses

Basicvertex, Revision

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Support::Model

_allocate_model, resolve_edge_name

Methods inherited from Base

#==, all, begin_transaction, commit, count, create_type, database_name, #delete, descendants, drop_type, find, first, #html_attributes, #in_and_out_attributes, insert, #insert_document, #inspect, #invariant_attributes, last, #method_missing, not_permitted, properties, query, #query, #rid?, rollback, timestamps, #to_html, #to_json, #to_or, update, #update, update!, #update_embedded, #update_list, #update_map, upsert, where

Methods included from Support::Sql

#compose_where, #generate_sql_list

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Arcade::Base

Class Method Details

.create(timestamp: true, **args) ⇒ Object

Creates a Vertex-Instance.

Similar to `Vertex#insert`.

Difference is the presence of a `created` property, a timestamp set to the time and date of creation.


24
25
26
27
28
29
# File 'lib/model/vertex.rb', line 24

def self.create timestamp: true, **args
  #t= timestamp ?  ", created = Date(#{DateTime.now.to_i}) "  : ""
  t= timestamp ?  ", created = sysdate() "  : ""
 # db.transmit { "create VERTEX #{database_name} set #{args.map{|x,y| [x,y.to_or].join("=")}.join(', ')+t}" } &.first.allocate_model(false)
 Api.create_document  db.database, database_name, session_id: db.session,  **args
end

.delete(where: {}, **args) ⇒ Object

Vertex.delete fires a “delete vertex” command to the database.

To remove all records  use  


42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/model/vertex.rb', line 42

def self.delete where: {} , **args
  if args[:all] == true
    where = {}
  elsif args[:rid].present?
    return db.transmit { "delete from #{args[:rid]}"  }.first["count"]
  else
    where.merge!(args) if where.is_a?(Hash)
    return 0 if where.empty?
  end
  # query returns [{count => n }]
  #  puts "delete from  #{database_name} #{compose_where(where)}"
  db.transmit { "delete  from `#{database_name}` #{compose_where(where)}"   } &.first[:count] rescue 0
end

.match(**args) ⇒ Object

———————————– Match —————————————— (ClassMethod)

Creates a Match-Statement based on the vertex type

“‘ m = Watchlist.match( symbol: ’iBit’, as: :ibit )

.out( HasUnderlying)
.node( as: :u )

m.to_s

=> "MATCH { type: watchlist, where: ( symbol='iBit' ), as: ibit }
          .out('has_underlying'){ as: u } 
    RETURN ibit,u "

“‘



233
234
235
236
237
# File 'lib/model/vertex.rb', line 233

def self.match **args
     as = args.delete( :as) || :a
     args = args.delete( :where ) if args.key?( :where )
     Arcade::Match.new type: self,  where: args, as: as
end

.nodes(in_or_out = :both, via: nil, **args) ⇒ Object



59
60
61
62
63
64
# File 'lib/model/vertex.rb', line 59

def self.nodes in_or_out = :both, via: nil ,  **args

  s =  Query.new from: self
  s.nodes in_or_out, via: via, **args
  s.query &.select_result
end

Instance Method Details

#accepted_methodsObject

#



11
12
13
# File 'lib/model/vertex.rb', line 11

def accepted_methods
 super + [ :in, :out, :both, :edges, :inE, :outE, :bothE,  :assign]
end

#assign(vertex: nil, via: Arcade::Edge, **attributes) ⇒ Object

Assigns another Vertex via an EdgeClass. If specified, puts attributes on the edge.

‘Vertex.assign via: Edge to: Vertex`

Returns the reloaded assigned vertex

Wrapper for

Edge.create from: self, to: a_vertex,  some: attributes.  on: the,  edge: type }

returns the assigned vertex, thus enabling to chain vertices through

Vertex.assign() via: E , to: VertexClass.create()).assign( via: E, ... )

or (1..100).each{|n| vertex = vertex.assign(via: E2, vertex: V2.create(item: n))}



201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/model/vertex.rb', line 201

def assign vertex: nil , via: Arcade::Edge   , **attributes
  vertex = attributes[:to] if attributes.has_key? :to
  raise "vertex not provided" if vertex.nil?

  via.create from: self, to: vertex,  **attributes

  db.get vertex.rid unless vertex.is_a? Array # return the assigned vertex
rescue IndexError => e
  db.logger.error "Edge not created, already present."
  vertex  #  return the vertex (for chaining)
rescue ArgumentError => e
  db.logger.error "ArgumentError: #{e.message}"
  nil
end

#both(count = 0, via: nil) ⇒ Object

get all Vertices connected by edges of type via



132
133
134
135
136
137
138
# File 'lib/model/vertex.rb', line 132

def both count=0, via:nil
  if count.zero?
    @bufferedboth ||= nodes :both, 1, via: via
  else
    nodes :both, count, via: via   # not cached
  end
end

#bothE(count = 1, via: nil) ⇒ Object

get all via-type-edges



152
153
154
# File 'lib/model/vertex.rb', line 152

def bothE  count=1, via:nil
  edges :both, count, via: via
end

#coeObject

Count Of Edges (coe) returns an Array: [ count-of-in-edges, count-of-out-edges ]



293
294
295
# File 'lib/model/vertex.rb', line 293

def coe 
   db.query( "select in().size() as ie, out().size() as oe from #{rid}" ) &.first.values
end

#edges(in_or_out = :both, depth = 1, via: nil, execute: true) ⇒ Object

Supports where: { where condition for edges }



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/model/vertex.rb', line 97

def edges in_or_out = :both, depth= 1, via: nil , execute: true

  v = in_or_out.to_s.delete_suffix 'E'
  e = v + 'E'
  edge_name = via.nil? ? "" : resolve_edge_name( via )
  argument =  "#{e}(#{edge_name})"
  q= if depth > 1
        repeated_argument = Array.new(depth -1 , "#{v}(#{edge_name})").join(".")
        query.projection repeated_argument + "." + argument
     else
        query.projection  argument
     end
  execute ?  q.execute &.allocate_model : q
end

#expandObject

# ——————————— Instance Methods ——————————— ##

We need expand as fallback if a vertex, which is stored as link, is automatically loaded


72
73
74
# File 'lib/model/vertex.rb', line 72

def expand
  self
end

#in(count = 0, via: nil) ⇒ Object

get Vertices through in by edges of type via



114
115
116
117
118
119
120
# File 'lib/model/vertex.rb', line 114

def in count=0, via:nil
  if count.zero?
    @bufferedin ||= nodes :in,  1, via: via
  else
    nodes :in, count, via: via   # not cached
  end
end

#inE(count = 1, via: nil) ⇒ Object

get via-type-edges through in



142
143
144
# File 'lib/model/vertex.rb', line 142

def inE count=1, via:nil
  edges :in,  count, via: via
end

#match(as: nil) ⇒ Object

———————————– Match —————————————— (InstanceMethod)

Creates a Match-Statement based on the current vertex ( i.e as response to a website-request )

“‘ params => “#49:0”

m= params.load_rid.match.out( HasUnterlying ).node( as: :u ) m.to_s

=> "MATCH { type: strategie, rid: #49:0 }.out('has_underlying'){ as: u } RETURN u "

“‘



253
254
255
256
257
258
259
# File 'lib/model/vertex.rb', line 253

def match as: nil
  if as.nil?
    Arcade::Match.new vertex: self
  else
    Arcade::Match.new vertex: self, as: as
  end
end

#nodes(in_or_out = :both, depth = 1, via: nil, execute: true, **args) ⇒ Object

fetches adjacet nodes

supported
nodes  in_or_out =  :in, :out, :both, :inE, :outE
       depth     =  fetch the n'th node through travese
       via:      =  Arcade Database Type (the ruby class)
       where:    =  a condition
                    inE, outE  -->  matches attributes on the edge
                    in, out, both -> matches attributes on the adjacent vertex
Example  Strategie.first nodes  where: {size: 10}
"select  both()[ size = 10  ]  from #113:8 "


87
88
89
90
91
92
93
94
# File 'lib/model/vertex.rb', line 87

def nodes in_or_out=:both, depth= 1, via: nil , execute: true, **args
  if depth <= 1
    s= query.nodes in_or_out, via: via, **args
    execute ? s.query &.select_result : s
  else
   travese in_or_out, depth: depth, start_at: depth-1, via: via, execute: execute, where: args[:where]
  end
end

#out(count = 0, via: nil) ⇒ Object

get Vertices through out by edges of type via



123
124
125
126
127
128
129
# File 'lib/model/vertex.rb', line 123

def out count=0, via:nil
  if count.zero?
    @bufferedout ||= nodes :out, 1,  via: via
  else
    nodes :out, count, via: via   # not cached
  end
end

#outE(count = 1, via: nil) ⇒ Object

get via-type-edges through out



147
148
149
# File 'lib/model/vertex.rb', line 147

def outE count=1, via:nil
  edges :out, count,  via: via
end

#refreshObject



298
299
300
301
302
303
# File 'lib/model/vertex.rb', line 298

def refresh
  # force reloading of edges and nodes
  # edges are not cached (now)
  @bufferedin, @bufferedout, @bufferedboth = nil
  super
end

#removeObject



261
262
263
# File 'lib/model/vertex.rb', line 261

def remove
   db.execute{ "delete vertex #{rid}" }
end

#to_humanObject

Human readable representation of Vertices

Format: < Classname: Edges, Attributes >



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/model/vertex.rb', line 269

def to_human

   in_and_out =  coe.then{| i,o| "{#{i}->}{->#{o}}, "}

  #Default presentation of Arcade::Base::Model-Objects

  "<#{self.class.to_s.snake_case}[#{rid}]:"  +
     in_and_out +
     invariant_attributes.map do |attr, value|
    v= case value
       when  Class
         "< #{self.class.to_s.snake_case}: #{value.rid} >"
       when Array
         value.to_s
       else
         value.from_db
       end
    "%s: %s" % [ attr, v]  unless v.nil?
  end.compact.sort.join(', ') + ">".gsub('"' , ' ')
end

#traverse(in_or_out = :out, via: nil, depth: 1, execute: true, start_at: 0, where: nil) ⇒ Object

e.i.

traverse( :in, via: [TG::DateOf, Arcade::HasOrder], depth: 4, start_at: 1 ).map(&:w).reverse


174
175
176
177
178
179
180
181
182
# File 'lib/model/vertex.rb', line 174

def traverse in_or_out = :out, via: nil,  depth: 1, execute: true, start_at: 0, where: nil

  the_query = query kind: 'traverse'
    the_query.projection  in_or_out.to_s + "(" + resolve_edge_name(*via) + ")"
  the_query.where where if where.present?
  the_query.while "$depth < #{depth} " unless depth <=0
  outer_query = Query.new from: the_query, where: "$depth >= #{start_at}"
  execute ?  outer_query.execute.allocate_model :  the_query # return only the traverse part
end