red_grape 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|