class Ashikawa::Core::Graph

A certain graph in the database.

@note All CRUD operations on related collections (edges and vertices) must be performed

through their corresponding graph class. Not doing so will eventually lead to inconsistency
and data corruption.

@see docs.arangodb.com/HttpGharial/README.html

Constants

ALL_NEIGHBORS_AQL

Prepared AQL statement for neighbors function on ALL edge collections

SPECIFIC_NEIGHBORS_AQL

Prepared AQL statement for neighbors function on a specific edge collections

Attributes

database[R]

The database the Graph belongs to

@return [Database] The associated database @api public @example

database = Ashikawa::Core::Database.new('http://localhost:8529')
raw_graph = {
  'name' => 'example_1',
  'edgeDefinitions' => [],
  'orphanCollections' => []
}
graph = Ashikawa::Core::Graph.new(database, raw_collection)
graph.database #=> #<Database: ...>
edge_definitions[R]

The edge definitions for this Graph

@return [Hash] The edge definitons of this Graph as a simple data structure @api public

name[R]

The name of the graph

@return [String] The name of the graph @api public @example

database = Ashikawa::Core::Database.new('http://localhost:8529')
raw_graph = {
  'name' => 'example_1',
  'edgeDefinitions' => [],
  'orphanCollections' => []
}
graph = Ashikawa::Core::Graph.new(database, raw_collection)
graph.name #=> 'example_1
revision[R]

The revision of the Graph

@return [String] The revision of the Graph @api public

Public Class Methods

new(database, raw_graph) click to toggle source

Initialize a new graph instance

@param [Database] database A reference to the database this graph belongs to @param [Hash] raw_graph The parsed JSON response from the database representing the graph

# File lib/ashikawa-core/graph.rb, line 77
def initialize(database, raw_graph)
  @database = database
  parse_raw_graph(raw_graph)
end

Public Instance Methods

add_edge_definition(collection_name, directions) click to toggle source

Adds an edge definition to this Graph

If the edge definition doesn’t exist it will be created, else it will just return the edge collection.

@param [Symbol] collection_name The name of the resulting edge collection @param [Hash] directions The specification between which vertices the edges should be created @option [Array<Symbol>] :from A list of collections names from which the edge directs @option [Array<Symbol>] :to A list of collections names to which the edge directs @see add_edge_definition at Graph! if you need to know the edge definition was already present @return [EdgeCollection] The edge collection used be the definition

# File lib/ashikawa-core/graph.rb, line 187
def add_edge_definition(collection_name, directions)
  add_edge_definition!(collection_name, directions)
rescue Ashikawa::Core::EdgeCollectionAlreadyPresent
  edge_collection(collection_name)
end
add_edge_definition!(collection_name, directions) click to toggle source

Adds an edge definition to this Graph

If the edge definition doesn’t exist it will be created, else it will raise an error.

@param [Symbol] collection_name The name of the resulting edge collection @param [Hash] directions The specification between which vertices the edges should be created @option [Array<Symbol>] :from A list of collections names from which the edge directs @option [Array<Symbol>] :to A list of collections names to which the edge directs @raise Ashikawa::Core::EdgeCollectionAlreadyPresent if the edge definition is already defined @see Graph#add_edge_definition if you need an idempotent version of this @return [EdgeCollection] The edge collection used be the definition

# File lib/ashikawa-core/graph.rb, line 204
def add_edge_definition!(collection_name, directions)
  create_options = {
    collection: collection_name,
    from:       directions[:from],
    to:         directions[:to]
  }

  response = send_request("gharial/#@name/edge", post: create_options)
  parse_raw_graph(response['graph'])
  edge_collection(collection_name)
end
add_vertex_collection(collection_name) click to toggle source

Adds a vertex collection to this graph

If the collection does not yet exist it will be created. If it already exists it will just be added to the list of vertex collections.

@param [String] collection_name The name of the vertex collection @see Graph#add_vertex_collection! if you need to know if the collection is already present @return [VertexCollection] The newly created collection

# File lib/ashikawa-core/graph.rb, line 116
def add_vertex_collection(collection_name)
  add_vertex_collection!(collection_name)
rescue Ashikawa::Core::VertexCollectionAlreadyPresent
  vertex_collection(collection_name)
end
add_vertex_collection!(collection_name) click to toggle source

Adds a vertex collection to this graph

If the collection does not exist yet it will be created. Initially it will add it as an orphaned collection to the graph. If the collection is already present in the graph definition, either as an orphan or as part of an edge definition an error is raised.

@param [String] collection_name The name of the vertex collection @raise [Ashikawa::Core::VertexCollectionAlreadyPresent] if the collection is already part of the graph @see Graph#add_vertex_collection if you want to silently ignore the exception @return [VertexCollection] The newly created collection

# File lib/ashikawa-core/graph.rb, line 132
def add_vertex_collection!(collection_name)
  response = send_request("gharial/#@name/vertex", post: { collection: collection_name })
  parse_raw_graph(response['graph'])
  vertex_collection(collection_name)
end
delete(options = {}) click to toggle source
# File lib/ashikawa-core/graph.rb, line 82
def delete(options = {})
  drop_collections = options.fetch(:drop_collections) { false }
  send_request("gharial/#@name", delete: { dropCollections: drop_collections })
end
edge_collection(collection_name) click to toggle source

Fetches an edge collection from the database

@param [String] collection_name The name of the desired edge @return [EdgeCollection] The edge collection for the given name

# File lib/ashikawa-core/graph.rb, line 220
def edge_collection(collection_name)
  response = send_request("collection/#{collection_name}")
  EdgeCollection.new(database, response, self)
end
edge_collection_names() click to toggle source

The list of names of the edge collections

@return [Array] Names of all edge collections

# File lib/ashikawa-core/graph.rb, line 172
def edge_collection_names
  @edge_definitions.map { |edge_def| edge_def['collection'] }
end
edge_collections() click to toggle source

Gets a list of edge collections

Due to the fact we need to fetch each of the collections by hand this will just return an enumerator which will lazily fetch the collections from the database.

@return [Enumerator] An Enumerator referencing the edge collections

# File lib/ashikawa-core/graph.rb, line 161
def edge_collections
  Enumerator.new do |yielder|
    edge_collection_names.each do |collection_name|
      yielder.yield edge_collection(collection_name)
    end
  end
end
has_vertex_collection?(collection_name) click to toggle source

Checks if a collection is present in the list of vertices

@param [String] collection_name The name of the collection to query @return [Boolean] True if the collection is present, false otherwise

# File lib/ashikawa-core/graph.rb, line 151
def has_vertex_collection?(collection_name)
  vertex_collection_names.any? { |name| name == collection_name }
end
neighbors(vertex, options = {}) click to toggle source

Return a Cursor representing the neighbors for the given document and optional edge collections

@param [Document] vertex The start vertex @param [options] options Additional options like restrictions on the edge collections @option [Array<Symbol>] :edges A list of edge collection to restrict the neighbors function on @return [Cursor] The cursor to the query result

# File lib/ashikawa-core/graph.rb, line 231
def neighbors(vertex, options = {})
  bind_vars = {
    graph: name,
    vertex_key: vertex.key
  }
  aql_string = ALL_NEIGHBORS_AQL

  if options.has_key?(:edges)
    aql_string = SPECIFIC_NEIGHBORS_AQL
    bind_vars[:edge_collection] = [options[:edges]].flatten
  end

  database.query.execute(aql_string, bind_vars: bind_vars)
end
vertex_collection(collection_name) click to toggle source

Fetches a vertex collection associated with graph from the database

@param [String] collection_name The name of the collection @return [VertexCollection] The fetched VertexCollection

# File lib/ashikawa-core/graph.rb, line 142
def vertex_collection(collection_name)
  raw_collection = send_request("collection/#{collection_name}")
  VertexCollection.new(database, raw_collection, self)
end
vertex_collection_names() click to toggle source

The list of names of the vertex collections

@return [Array] Names of all vertex collections

# File lib/ashikawa-core/graph.rb, line 104
def vertex_collection_names
  @orphan_collections | @edge_definitions.map { |edge_def| edge_def.values_at('from', 'to') }.flatten
end
vertex_collections() click to toggle source

Gets a list of vertex collections

Due to the fact we need to fetch each of the collections by hand this will just return an enumerator which will lazily fetch the collections from the database.

@return [Enumerator] An Enumerator referencing the vertex collections

# File lib/ashikawa-core/graph.rb, line 93
def vertex_collections
  Enumerator.new do |yielder|
    vertex_collection_names.each do |collection_name|
      yielder.yield vertex_collection(collection_name)
    end
  end
end

Private Instance Methods

parse_raw_graph(raw_graph) click to toggle source

Parses the raw graph structure as returned from the database

@param [Hash] raw_graph The structure as returned from the database @api private

# File lib/ashikawa-core/graph.rb, line 252
def parse_raw_graph(raw_graph)
  @name               = raw_graph['name'] || raw_graph['_key']
  @revision           = raw_graph['_rev']
  @edge_definitions   = raw_graph.fetch('edgeDefinitions') { [] }
  @orphan_collections = raw_graph.fetch('orphanCollections') { [] }
end