red_grape 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +23 -0
- data/.gemtest +0 -0
- data/History.txt +6 -0
- data/Manifest.txt +32 -0
- data/README.txt +59 -0
- data/Rakefile +19 -0
- data/bin/red_grape +3 -0
- data/data/graph-example-1.xml +54 -0
- data/lib/red_grape/edge.rb +34 -0
- data/lib/red_grape/graph.rb +139 -0
- data/lib/red_grape/path_group.rb +16 -0
- data/lib/red_grape/pipe/as_pipe.rb +36 -0
- data/lib/red_grape/pipe/back_pipe.rb +25 -0
- data/lib/red_grape/pipe/base.rb +83 -0
- data/lib/red_grape/pipe/context.rb +34 -0
- data/lib/red_grape/pipe/filter_pipe.rb +22 -0
- data/lib/red_grape/pipe/if_then_else_pipe.rb +27 -0
- data/lib/red_grape/pipe/in_pipe.rb +31 -0
- data/lib/red_grape/pipe/loop_pipe.rb +39 -0
- data/lib/red_grape/pipe/out_pipe.rb +37 -0
- data/lib/red_grape/pipe/paths_pipe.rb +24 -0
- data/lib/red_grape/pipe/property_pipe.rb +25 -0
- data/lib/red_grape/pipe/side_effect_pipe.rb +23 -0
- data/lib/red_grape/pipe/transform_pipe.rb +21 -0
- data/lib/red_grape/propertied_object.rb +46 -0
- data/lib/red_grape/property_description.rb +47 -0
- data/lib/red_grape/vertex.rb +46 -0
- data/lib/red_grape/vertex_group.rb +72 -0
- data/lib/red_grape.rb +31 -0
- data/test/test_graph.rb +80 -0
- data/test/test_on_the_nature_of_pipes.rb +101 -0
- data/test/test_propertied_object.rb +42 -0
- data/test/test_red_grape.rb +8 -0
- data/test/test_traversal_patterns.rb +18 -0
- data/test/test_vertex.rb +34 -0
- metadata +114 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'red_grape/pipe/base'
|
2
|
+
|
3
|
+
module RedGrape
|
4
|
+
module Pipe
|
5
|
+
class LoopPipe < Pipe::Base
|
6
|
+
def pass(obj, context) # TODO: 無理やり・・・
|
7
|
+
condition = self.opts.first
|
8
|
+
label = self.opts[1]
|
9
|
+
|
10
|
+
looped_pipe = self.prev.dup
|
11
|
+
looped_pipe.prev = self.prev.prev
|
12
|
+
(label - 1).times do
|
13
|
+
prev = looped_pipe.prev.dup
|
14
|
+
prev.next = looped_pipe
|
15
|
+
looped_pipe = prev
|
16
|
+
end
|
17
|
+
|
18
|
+
context.loops += 1
|
19
|
+
while context.eval :it => obj, &condition
|
20
|
+
pipe = looped_pipe
|
21
|
+
while pipe
|
22
|
+
obj = obj.pass_through pipe, context
|
23
|
+
pipe = pipe.next
|
24
|
+
end
|
25
|
+
context.loops += 1
|
26
|
+
end
|
27
|
+
context.loops = 1
|
28
|
+
|
29
|
+
if self.last?
|
30
|
+
obj
|
31
|
+
else
|
32
|
+
context.push_history obj do |ctx|
|
33
|
+
obj.pass_through self.next, ctx
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'red_grape/pipe/base'
|
2
|
+
|
3
|
+
module RedGrape
|
4
|
+
module Pipe
|
5
|
+
module Out
|
6
|
+
def out(*opts)
|
7
|
+
OutPipe.new self, *opts
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class OutPipe < Pipe::Base
|
12
|
+
def pipe_name
|
13
|
+
@opts.empty? ? super : "#{super}(#{@opts.first})"
|
14
|
+
end
|
15
|
+
|
16
|
+
def pass(obj, context)
|
17
|
+
case obj
|
18
|
+
when RedGrape::Vertex
|
19
|
+
group =
|
20
|
+
if self.opts.empty? or self.opts.first.empty? # TODO $B$J$<$+(Blabel$B$K(B[]$B$,F~$C$F$k(B
|
21
|
+
VertexGroup.new obj._out_edges.map(&:target)
|
22
|
+
else
|
23
|
+
label = self.opts.first
|
24
|
+
VertexGroup.new obj._out_edges.find_all{|e| e.label == label}.map(&:target)
|
25
|
+
end
|
26
|
+
if self.last?
|
27
|
+
group
|
28
|
+
else
|
29
|
+
context.push_history obj do |ctx|
|
30
|
+
group.pass_through self.next, ctx
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'red_grape/pipe/base'
|
2
|
+
require 'red_grape/path_group'
|
3
|
+
|
4
|
+
module RedGrape
|
5
|
+
module Pipe
|
6
|
+
class PathsPipe < Pipe::Base
|
7
|
+
def pass(obj, context)
|
8
|
+
case obj
|
9
|
+
when 'TODO'
|
10
|
+
else
|
11
|
+
context.push_history obj do |ctx|
|
12
|
+
if self.last?
|
13
|
+
#ctx.history.dup
|
14
|
+
PathGroup.new ctx.history
|
15
|
+
else
|
16
|
+
# TODO
|
17
|
+
raise 'not implemented'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'red_grape/pipe/base'
|
2
|
+
|
3
|
+
module RedGrape
|
4
|
+
module Pipe
|
5
|
+
class PropertyPipe < Pipe::Base
|
6
|
+
def pipe_name
|
7
|
+
"#{super}(#{@opts.first})"
|
8
|
+
end
|
9
|
+
|
10
|
+
def pass(obj, context)
|
11
|
+
case obj
|
12
|
+
when RedGrape::Vertex
|
13
|
+
prop = obj[self.opts.first]
|
14
|
+
if self.last?
|
15
|
+
prop
|
16
|
+
else
|
17
|
+
context.push_history obj do |ctx|
|
18
|
+
prop.pass_through self.next, ctx
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'red_grape/pipe/base'
|
2
|
+
|
3
|
+
module RedGrape
|
4
|
+
module Pipe
|
5
|
+
module SideEffect
|
6
|
+
def side_effect(&block)
|
7
|
+
SideEffectPipe.new self, block
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class SideEffectPipe < Pipe::Base
|
12
|
+
def pass(obj, context)
|
13
|
+
side_effect = self.opts.first
|
14
|
+
context.eval :it => obj, &side_effect
|
15
|
+
if self.last?
|
16
|
+
obj
|
17
|
+
else
|
18
|
+
obj.pass_through self.next, context
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'red_grape/pipe/base'
|
2
|
+
|
3
|
+
module RedGrape
|
4
|
+
module Pipe
|
5
|
+
class TransformPipe < Pipe::Base
|
6
|
+
def pass(obj, context)
|
7
|
+
case obj
|
8
|
+
when 'TODO'
|
9
|
+
else
|
10
|
+
transformer = self.opts.first
|
11
|
+
val = context.eval :it => obj, &transformer
|
12
|
+
if self.last?
|
13
|
+
val
|
14
|
+
else
|
15
|
+
raise 'not implemented'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'red_grape/property_description'
|
2
|
+
|
3
|
+
module RedGrape
|
4
|
+
class PropertiedObject
|
5
|
+
def initialize(graph, opts={})
|
6
|
+
@graph = graph
|
7
|
+
@property = {}
|
8
|
+
@property_description = opts[:property_description] || {}
|
9
|
+
@property_description.each do |k ,v|
|
10
|
+
if v.is_a? Array
|
11
|
+
v = PropertyDescription.new(*v)
|
12
|
+
elsif v.is_a? Hash
|
13
|
+
v = PropertyDescription.new v[:name], v[:type], v[:default]
|
14
|
+
end
|
15
|
+
@property_description[k] = v
|
16
|
+
set_property k, v.default if v.has_default?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_property(kid, v)
|
21
|
+
# TODO: should be refactored
|
22
|
+
desc = @property_description[kid]
|
23
|
+
if desc.accessible? v
|
24
|
+
self[desc.name] = v
|
25
|
+
elsif desc.convertable? v
|
26
|
+
self[desc.name] = desc.convert v
|
27
|
+
else
|
28
|
+
raise ArgumentError.new "#{kid} should be #{desc.type}."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def []=(k, v)
|
33
|
+
# TODO: type check?
|
34
|
+
@property[k.to_s] = v
|
35
|
+
end
|
36
|
+
|
37
|
+
def [](k)
|
38
|
+
@property[k.to_s]
|
39
|
+
end
|
40
|
+
|
41
|
+
# TODO: $B$$$i$J$$!)(B
|
42
|
+
def pass_through(pipe, context)
|
43
|
+
pipe.pass self, context
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module RedGrape
|
2
|
+
class PropertyDescription
|
3
|
+
attr_reader :name, :type, :default
|
4
|
+
|
5
|
+
def initialize(name, type, default=nil)
|
6
|
+
@name = name
|
7
|
+
@type = type
|
8
|
+
@default = default
|
9
|
+
end
|
10
|
+
|
11
|
+
def accessible?(val)
|
12
|
+
case type
|
13
|
+
when 'int', 'integer'
|
14
|
+
val.is_a? Integer
|
15
|
+
else
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def convertable?(val)
|
21
|
+
case type
|
22
|
+
when 'int', 'integer'
|
23
|
+
val =~ /^\d+$/
|
24
|
+
else
|
25
|
+
true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def convert(val)
|
30
|
+
case type
|
31
|
+
when 'int', 'integer'
|
32
|
+
val.to_i
|
33
|
+
else
|
34
|
+
val
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def has_default?
|
39
|
+
not @default.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
"{#{@name}:#{@type}:#{@default}}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'red_grape/propertied_object'
|
2
|
+
|
3
|
+
module RedGrape
|
4
|
+
class Vertex < PropertiedObject
|
5
|
+
include RedGrape::Pipe::Out
|
6
|
+
include RedGrape::Pipe::OutE
|
7
|
+
include RedGrape::Pipe::SideEffect
|
8
|
+
include RedGrape::Pipe::As
|
9
|
+
|
10
|
+
def initialize(graph, id, opts={})
|
11
|
+
super graph, opts
|
12
|
+
@id = id
|
13
|
+
@out_edges = []
|
14
|
+
@in_edges = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def _id
|
18
|
+
@id
|
19
|
+
end
|
20
|
+
|
21
|
+
def _in_edges
|
22
|
+
@in_edges
|
23
|
+
end
|
24
|
+
|
25
|
+
def _out_edges
|
26
|
+
@out_edges
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_out_edge(edge)
|
30
|
+
@out_edges << edge
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_in_edge(edge)
|
34
|
+
@in_edges << edge
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
"v[#{_id}]"
|
39
|
+
#"v[id(#{_id}):#{@property}]"
|
40
|
+
end
|
41
|
+
|
42
|
+
def method_missing(name, *args, &block)
|
43
|
+
self[name.to_s] or raise NoMethodError.new(name.to_s)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'red_grape/vertex'
|
2
|
+
|
3
|
+
#TODO delegate to array
|
4
|
+
module RedGrape
|
5
|
+
class VertexGroup < Vertex
|
6
|
+
def initialize(group=[])
|
7
|
+
@group = group
|
8
|
+
end
|
9
|
+
|
10
|
+
def _group
|
11
|
+
@group
|
12
|
+
end
|
13
|
+
|
14
|
+
def pass_through(pipe, context)
|
15
|
+
@group.map! do |v|
|
16
|
+
pipe.pass v, context
|
17
|
+
end
|
18
|
+
@group.reject! do |v|
|
19
|
+
v.nil? or (v.respond_to?(:empty?) and v.empty?) # TODO
|
20
|
+
end
|
21
|
+
@group.map! do |v|
|
22
|
+
v.is_a?(self.class) ? v._group : v
|
23
|
+
end
|
24
|
+
#@group.flatten!
|
25
|
+
flatten_group!
|
26
|
+
@group.all? {|e| e.is_a? self.class} ? self : @group
|
27
|
+
end
|
28
|
+
|
29
|
+
def flatten_group
|
30
|
+
ret = []
|
31
|
+
@group.each do |v|
|
32
|
+
case v
|
33
|
+
when Array
|
34
|
+
ret += v.flatten
|
35
|
+
when self.class
|
36
|
+
ret += v._group.flatten_group
|
37
|
+
else
|
38
|
+
ret << v
|
39
|
+
end
|
40
|
+
end
|
41
|
+
ret
|
42
|
+
end
|
43
|
+
|
44
|
+
def flatten_group!
|
45
|
+
@group = flatten_group
|
46
|
+
end
|
47
|
+
|
48
|
+
def size
|
49
|
+
@group.size
|
50
|
+
end
|
51
|
+
|
52
|
+
def map(&block)
|
53
|
+
@group.map(&block)
|
54
|
+
end
|
55
|
+
|
56
|
+
def sort(&block)
|
57
|
+
@group.sort
|
58
|
+
end
|
59
|
+
|
60
|
+
def empty?
|
61
|
+
@group.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_a
|
65
|
+
@group.dup.map{|e| e.is_a?(self.class) ? e.to_a : e}
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
"[#{@group.map(&:to_s).join ', '}]"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/red_grape.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'red_grape/pipe/in_pipe'
|
3
|
+
require 'red_grape/pipe/out_pipe'
|
4
|
+
require 'red_grape/pipe/property_pipe'
|
5
|
+
require 'red_grape/pipe/paths_pipe'
|
6
|
+
require 'red_grape/pipe/filter_pipe'
|
7
|
+
require 'red_grape/pipe/transform_pipe'
|
8
|
+
require 'red_grape/pipe/side_effect_pipe'
|
9
|
+
require 'red_grape/pipe/if_then_else_pipe'
|
10
|
+
require 'red_grape/pipe/back_pipe'
|
11
|
+
require 'red_grape/pipe/as_pipe'
|
12
|
+
require 'red_grape/pipe/loop_pipe'
|
13
|
+
require 'red_grape/pipe/has_pipe'
|
14
|
+
require 'red_grape/pipe/out_e_pipe'
|
15
|
+
require 'red_grape/pipe/in_v_pipe'
|
16
|
+
require 'red_grape/graph'
|
17
|
+
|
18
|
+
module RedGrape
|
19
|
+
VERSION = '0.0.1'
|
20
|
+
|
21
|
+
module_function
|
22
|
+
def load_graph(filename)
|
23
|
+
Graph.load filename
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Object
|
28
|
+
def pass_through(pipe, context)
|
29
|
+
pipe.pass self, context
|
30
|
+
end
|
31
|
+
end
|
data/test/test_graph.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'stringio'
|
3
|
+
require 'red_grape'
|
4
|
+
|
5
|
+
class GraphTest < Test::Unit::TestCase
|
6
|
+
def test_vertex
|
7
|
+
graph = RedGrape::Graph.new
|
8
|
+
graph.add_vertex id:1, val:'a'
|
9
|
+
graph.add_vertex id:2, val:'b'
|
10
|
+
graph.add_vertex id:3, val:'c'
|
11
|
+
|
12
|
+
assert_equal 3, graph.vertex.size
|
13
|
+
assert_equal 1, graph.vertex(1)._id
|
14
|
+
assert_equal 2, graph.vertex(1, 2).size
|
15
|
+
assert_equal 2, graph.vertex([1, 2]).size
|
16
|
+
assert_equal 3, graph.vertex(:all).size
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_construct
|
20
|
+
graph = RedGrape::Graph.new
|
21
|
+
v1 = graph.add_vertex 1, name:'yasushi'
|
22
|
+
v2 = graph.add_vertex 2, name:'ando'
|
23
|
+
e12 = graph.add_edge 1, :fullname, v1, v2
|
24
|
+
|
25
|
+
assert_equal 1, v1._out_edges.size
|
26
|
+
assert_equal 0, v1._in_edges.size
|
27
|
+
assert_equal e12, v1._out_edges.first
|
28
|
+
|
29
|
+
assert_equal 0, v2._out_edges.size
|
30
|
+
assert_equal 1, v2._in_edges.size
|
31
|
+
assert_equal e12, v2._in_edges.first
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_load
|
35
|
+
data = <<-EOS
|
36
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
37
|
+
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
38
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
39
|
+
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
|
40
|
+
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
41
|
+
<key id="weight" for="edge" attr.name="weight" attr.type="float"/>
|
42
|
+
<key id="name" for="node" attr.name="name" attr.type="string"/>
|
43
|
+
<graph id="G" edgedefault="directed">
|
44
|
+
<node id="1">
|
45
|
+
<data key="name">marko</data>
|
46
|
+
</node>
|
47
|
+
<node id="2">
|
48
|
+
<data key="name">vadas</data>
|
49
|
+
</node>
|
50
|
+
<node id="3">
|
51
|
+
<data key="name">lop</data>
|
52
|
+
</node>
|
53
|
+
<edge id="4" source="1" target="2" label="knows">
|
54
|
+
<data key="weight">0.5</data>
|
55
|
+
</edge>
|
56
|
+
<edge id="5" source="1" target="3" label="knows">
|
57
|
+
<data key="weight">1.0</data>
|
58
|
+
</edge>
|
59
|
+
</graph>
|
60
|
+
</graphml>
|
61
|
+
EOS
|
62
|
+
graph = RedGrape::Graph.load data
|
63
|
+
assert_equal 'marko', graph.vertex(1).name
|
64
|
+
assert_equal 'vadas', graph.vertex(2).name
|
65
|
+
assert_equal 'lop', graph.vertex(3).name
|
66
|
+
assert_equal 'marko', graph.edge(4).source.name
|
67
|
+
assert_equal 'vadas', graph.edge(4).target.name
|
68
|
+
assert_equal 'marko', graph.edge(5).source.name
|
69
|
+
assert_equal 'lop', graph.edge(5).target.name
|
70
|
+
|
71
|
+
graph = RedGrape::Graph.load StringIO.new(data)
|
72
|
+
assert_equal 'marko', graph.vertex(1).name
|
73
|
+
assert_equal 'vadas', graph.vertex(2).name
|
74
|
+
assert_equal 'lop', graph.vertex(3).name
|
75
|
+
assert_equal 'marko', graph.edge(4).source.name
|
76
|
+
assert_equal 'vadas', graph.edge(4).target.name
|
77
|
+
assert_equal 'marko', graph.edge(5).source.name
|
78
|
+
assert_equal 'lop', graph.edge(5).target.name
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'red_grape'
|
3
|
+
|
4
|
+
# test the patterns shown in: http://markorodriguez.com/2011/08/03/on-the-nature-of-pipes/
|
5
|
+
class OnTheNatureOfPipesTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@graph = RedGrape.load_graph 'data/graph-example-1.xml'
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_basic
|
11
|
+
assert_equal '1',
|
12
|
+
@graph.v(1)._id
|
13
|
+
|
14
|
+
assert_equal %w(2 3 4),
|
15
|
+
@graph.v(1).out.take.map(&:_id).sort
|
16
|
+
|
17
|
+
assert_equal %w(josh lop vadas),
|
18
|
+
@graph.v(1).out.name.take.sort
|
19
|
+
|
20
|
+
paths = @graph.v(1).out.name.paths.take
|
21
|
+
assert_equal 3,
|
22
|
+
paths.size
|
23
|
+
|
24
|
+
assert_equal [3, 3, 3],
|
25
|
+
paths.map(&:size)
|
26
|
+
|
27
|
+
assert_equal %w[OutPipe PropertyPipe(name) PathsPipe],
|
28
|
+
@graph.v(1).out.name.paths.to_a
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_filter
|
32
|
+
assert_equal %w(2 4),
|
33
|
+
@graph.v(1).out('knows').take.map(&:_id).sort
|
34
|
+
|
35
|
+
assert_equal %W(2),
|
36
|
+
@graph.v(1).out('knows').filter{it.age < 30}.take.map(&:_id).sort
|
37
|
+
|
38
|
+
assert_equal %W(vadas),
|
39
|
+
@graph.v(1).out('knows').filter{it.age < 30}.name.take.sort
|
40
|
+
|
41
|
+
assert_equal [5],
|
42
|
+
@graph.v(1).out('knows').filter{it.age < 30}.name.transform{it.size}.take.sort
|
43
|
+
|
44
|
+
assert_equal %w[OutPipe(knows) FilterPipe PropertyPipe(name) TransformPipe],
|
45
|
+
@graph.v(1).out('knows').filter{it.age < 30}.name.transform{it.size}.to_a
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_side_effect
|
49
|
+
assert_equal 'marko',
|
50
|
+
@graph.v(1).side_effect{@x = it}.take.name
|
51
|
+
|
52
|
+
assert_equal %w(3),
|
53
|
+
@graph.v(1).side_effect{@x = it}.out('created').take.map(&:_id).sort
|
54
|
+
|
55
|
+
assert_equal %w(1 4 6),
|
56
|
+
@graph.v(1).side_effect{@x = it}.out('created').in('created').take.map(&:_id).sort
|
57
|
+
|
58
|
+
assert_equal %w(4 6),
|
59
|
+
@graph.v(1).side_effect{@x = it}.out('created').in('created').filter{it != @x}.take.map(&:_id).sort
|
60
|
+
|
61
|
+
assert_equal %w(SideEffectPipe OutPipe(created) InPipe(created) FilterPipe),
|
62
|
+
@graph.v(1).side_effect{@x = it}.out('created').in('created').filter{it != @x}.to_a
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_if_then_else
|
66
|
+
#assert_equal ['vadas', ['ripple', 'lop']],
|
67
|
+
assert_equal ['vadas', 'ripple', 'lop'],
|
68
|
+
@graph.v(1).out('knows').if_then_else(proc{it.age < 30}, proc{it.name}, proc{it.out('created').name}).take.to_a
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_back
|
72
|
+
assert_equal %w(josh vadas),
|
73
|
+
@graph.v(1).out('knows').name.take.to_a.sort
|
74
|
+
|
75
|
+
assert_equal %w(vadas),
|
76
|
+
@graph.v(1).out('knows').name.filter{it[0] == 'v'}.take.to_a
|
77
|
+
|
78
|
+
assert_equal %w(2),
|
79
|
+
@graph.v(1).out('knows').name.filter{it[0] == 'v'}.back(2).take.to_a.map(&:_id)
|
80
|
+
|
81
|
+
assert_equal %w(OutPipe(knows) PropertyPipe(name) FilterPipe BackPipe),
|
82
|
+
@graph.v(1).out('knows').name.filter{it[0] == 'v'}.back(2).to_a
|
83
|
+
|
84
|
+
assert_equal %w(2 4),
|
85
|
+
@graph.v(1).out('knows').as('here').name.filter{it[0] == 'v'}.back('here').take.to_a.map(&:_id)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_loop
|
89
|
+
assert_equal %w(3 5),
|
90
|
+
@graph.v(1).out.out.take.to_a.map(&:_id).sort
|
91
|
+
|
92
|
+
assert_equal %w(3 5),
|
93
|
+
@graph.v(1).out.loop(1){loops < 3}.take.to_a.map(&:_id).sort
|
94
|
+
|
95
|
+
assert_equal %w(lop ripple),
|
96
|
+
@graph.v(1).out.loop(1){loops < 3}.name.take.sort
|
97
|
+
|
98
|
+
assert_equal %w(OutPipe LoopPipe PropertyPipe(name)),
|
99
|
+
@graph.v(1).out.loop(1){loops < 3}.name.to_a
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'red_grape'
|
3
|
+
require 'red_grape/propertied_object'
|
4
|
+
require 'red_grape/property_description'
|
5
|
+
|
6
|
+
class PropertiedObjectTest < Test::Unit::TestCase
|
7
|
+
def test_new
|
8
|
+
g = RedGrape::Graph.new
|
9
|
+
v = RedGrape::PropertiedObject.new g, property_description:{
|
10
|
+
name:RedGrape::PropertyDescription.new('name', 'string'),
|
11
|
+
sex:RedGrape::PropertyDescription.new('sex', 'string', 'male'),
|
12
|
+
age:RedGrape::PropertyDescription.new('age', 'integer')
|
13
|
+
}
|
14
|
+
desc = v.instance_eval '@property_description'
|
15
|
+
assert_equal 'name', desc[:name].name
|
16
|
+
assert_equal 'string', desc[:name].type
|
17
|
+
assert_nil desc[:name].default
|
18
|
+
assert_equal 'male', desc[:sex].default
|
19
|
+
|
20
|
+
v = RedGrape::PropertiedObject.new g, property_description:{
|
21
|
+
name:['name', 'string'],
|
22
|
+
sex:['sex', 'string', 'male'],
|
23
|
+
age:['age', 'integer']
|
24
|
+
}
|
25
|
+
desc = v.instance_eval '@property_description'
|
26
|
+
assert_equal 'name', desc[:name].name
|
27
|
+
assert_equal 'string', desc[:name].type
|
28
|
+
assert_nil desc[:name].default
|
29
|
+
assert_equal 'male', desc[:sex].default
|
30
|
+
|
31
|
+
v = RedGrape::PropertiedObject.new g, property_description:{
|
32
|
+
name:{name:'name', type:'string'},
|
33
|
+
sex:{name:'sex', type:'string', default:'male'},
|
34
|
+
age:{name:'age', type:'integer'}
|
35
|
+
}
|
36
|
+
desc = v.instance_eval '@property_description'
|
37
|
+
assert_equal 'name', desc[:name].name
|
38
|
+
assert_equal 'string', desc[:name].type
|
39
|
+
assert_nil desc[:name].default
|
40
|
+
assert_equal 'male', desc[:sex].default
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'red_grape'
|
3
|
+
|
4
|
+
class TraversalPatternsTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@graph = RedGrape.load_graph 'data/graph-example-1.xml'
|
7
|
+
end
|
8
|
+
|
9
|
+
# https://github.com/tinkerpop/gremlin/wiki/Backtrack-Pattern
|
10
|
+
def test_backtrack_pattern
|
11
|
+
assert_equal [29], @graph.V.out('knows').has('age', :gt, 30).back(2).age.take
|
12
|
+
assert_equal [29], @graph.V.as('x').outE('knows').inV.has('age', :gt, 30).back('x').age.take
|
13
|
+
end
|
14
|
+
|
15
|
+
# https://github.com/tinkerpop/gremlin/wiki/Except-Retain-Pattern
|
16
|
+
def test_except_retain_pattern
|
17
|
+
end
|
18
|
+
end
|