require 'geoff/children_dsl' class NodeDsl attr_reader :node_name def initialize(options, &block) @node_name = options[:node_name] || 'root' @klass_name = options[:klass_name] || 'ROOT' @container = options[:container] || Container.new @rel_type = options[:rel_type] @outer_binding = options[:binding] @properties = {} @children_dsls = [] @rendered = false write_mode { instance_eval(&block) } if block_given? end def to_geoff geoff_lines.join "\n" end def geoff_lines #we need this to prevent rendering same node which is rendered already return [] if @rendered @rendered = true lines = [self_to_geoff] lines << all_rule_to_geoff if use_neo4j_wrapper? lines += @children_dsls.map(&:geoff_lines) lines end def b @container end def all_rule_to_geoff "(#{@klass_name})-[:all]->(#{@node_name})" end def self_to_geoff "(#{@node_name}) #{properties.to_json}" end #refactor out wrapper specific stuff later def use_neo4j_wrapper? true end def properties if use_neo4j_wrapper? { '_classname' => @klass_name }.merge @properties else @properties end end #prevent very confusing method_missing calls during debugging by #only writing to the object when expected def write_mode @write_mode = true yield @write_mode = false end # e.g. #sandwich "BLT", type: :on_menu do # filling 'bacon' # filling 'lettuce' # filling 'tomato' #end def method_missing m, *args, &blk if args.empty? @properties[m] else return super unless @write_mode val = if args.first.is_a? Proc eval("@#{m}", @outer_binding) else args.first end @properties[m] = val end end def to_s to_geoff end private def children type=nil, &block options = { parent_node_name: @node_name, type: type, container: @container, binding: @outer_binding } @children_dsls << ChildrenDsl.new(options, &block) end end