lib/grumlin/repository.rb in grumlin-0.17.0 vs lib/grumlin/repository.rb in grumlin-0.18.0

- old
+ new

@@ -8,21 +8,91 @@ single: :next, traversal: :nil }.freeze module InstanceMethods + include Grumlin::Expressions + def __ TraversalStart.new(self.class.shortcuts) end def g TraversalStart.new(self.class.shortcuts) end + + def drop_vertex(id) + g.V(id).drop.iterate + end + + def drop_edge(id = nil, from: nil, to: nil, label: nil) # rubocop:disable Metrics/AbcSize + raise ArgumentError, "either id or from:, to: and label: must be passed" if [id, from, to, label].all?(&:nil?) + return g.E(id).drop.iterate unless id.nil? + + raise ArgumentError, "from:, to: and label: must be passed" if [from, to, label].any?(&:nil?) + + g.V(from).outE(label).where(__.inV.hasId(to)).limit(1).drop.iterate + end + + def add_vertex(label, id = nil, **properties) + id ||= properties[T.id] + properties = except(properties, T.id) + + t = g.addV(label) + t = t.props(T.id => id) unless id.nil? + t.props(**properties).next + end + + def add_edge(label, id = nil, from:, to:, **properties) + id ||= properties[T.id] + properties = except(properties, T.label) + properties[T.id] = id + + g.addE(label).from(__.V(from)).to(__.V(to)).props(**properties).next + end + + def upsert_vertex(label, id, create_properties: {}, update_properties: {}) # rubocop:disable Metrics/AbcSize + create_properties = except(create_properties, T.id, T.label) + update_properties = except(update_properties, T.id, T.label) + g.V(id) + .fold + .coalesce( + __.unfold, + __.addV(label).props(**create_properties.merge(T.id => id)) + ).props(**update_properties) + .next + end + + # Only from and to are used to find the existing edge, if one wants to assign an id to a created edge, + # it must be passed as T.id in via create_properties. + def upsert_edge(label, from:, to:, create_properties: {}, update_properties: {}) # rubocop:disable Metrics/AbcSize + create_properties = except(create_properties, T.label) + update_properties = except(update_properties, T.id, T.label) + + g.V(from) + .outE(label).where(__.inV.hasId(to)) + .fold + .coalesce( + __.unfold, + __.addE(label).from(__.V(from)).to(__.V(to)).props(**create_properties) + ).props(**update_properties).next + end + + private + + # A polyfill for Hash#except for ruby 2.x environments without ActiveSupport + # TODO: delete and use native Hash#except when after ruby 2.7 is deprecated. + def except(hash, *keys) + return hash.except(*keys) if hash.respond_to?(:except) + + hash.each_with_object({}) do |(k, v), res| + res[k] = v unless keys.include?(k) + end + end end def self.extended(base) base.extend(Grumlin::Shortcuts) - base.include(Grumlin::Expressions) base.include(InstanceMethods) base.shortcuts_from(Grumlin::Shortcuts::Properties) end