neography-down 1.6.4

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.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.project +12 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +4 -0
  6. data/CHANGELOG.md +939 -0
  7. data/CONTRIBUTORS +18 -0
  8. data/Gemfile +4 -0
  9. data/Guardfile +14 -0
  10. data/LICENSE +19 -0
  11. data/README.md +281 -0
  12. data/Rakefile +14 -0
  13. data/examples/facebook.rb +40 -0
  14. data/examples/facebook_v2.rb +25 -0
  15. data/examples/greatest.rb +43 -0
  16. data/examples/linkedin.rb +39 -0
  17. data/examples/linkedin_v2.rb +22 -0
  18. data/examples/traversal_example1.rb +65 -0
  19. data/examples/traversal_example2.rb +54 -0
  20. data/lib/neography.rb +45 -0
  21. data/lib/neography/config.rb +64 -0
  22. data/lib/neography/connection.rb +263 -0
  23. data/lib/neography/equal.rb +21 -0
  24. data/lib/neography/errors.rb +60 -0
  25. data/lib/neography/index.rb +52 -0
  26. data/lib/neography/multi_json_parser.rb +28 -0
  27. data/lib/neography/neography.rb +10 -0
  28. data/lib/neography/node.rb +63 -0
  29. data/lib/neography/node_path.rb +29 -0
  30. data/lib/neography/node_relationship.rb +37 -0
  31. data/lib/neography/node_traverser.rb +146 -0
  32. data/lib/neography/path_traverser.rb +100 -0
  33. data/lib/neography/property.rb +110 -0
  34. data/lib/neography/property_container.rb +28 -0
  35. data/lib/neography/railtie.rb +19 -0
  36. data/lib/neography/relationship.rb +78 -0
  37. data/lib/neography/relationship_traverser.rb +80 -0
  38. data/lib/neography/rest.rb +99 -0
  39. data/lib/neography/rest/batch.rb +414 -0
  40. data/lib/neography/rest/clean.rb +17 -0
  41. data/lib/neography/rest/constraints.rb +38 -0
  42. data/lib/neography/rest/cypher.rb +29 -0
  43. data/lib/neography/rest/extensions.rb +21 -0
  44. data/lib/neography/rest/gremlin.rb +20 -0
  45. data/lib/neography/rest/helpers.rb +96 -0
  46. data/lib/neography/rest/node_auto_indexes.rb +60 -0
  47. data/lib/neography/rest/node_indexes.rb +139 -0
  48. data/lib/neography/rest/node_labels.rb +49 -0
  49. data/lib/neography/rest/node_paths.rb +49 -0
  50. data/lib/neography/rest/node_properties.rb +52 -0
  51. data/lib/neography/rest/node_relationships.rb +33 -0
  52. data/lib/neography/rest/node_traversal.rb +25 -0
  53. data/lib/neography/rest/nodes.rb +94 -0
  54. data/lib/neography/rest/other_node_relationships.rb +38 -0
  55. data/lib/neography/rest/relationship_auto_indexes.rb +60 -0
  56. data/lib/neography/rest/relationship_indexes.rb +142 -0
  57. data/lib/neography/rest/relationship_properties.rb +52 -0
  58. data/lib/neography/rest/relationship_types.rb +11 -0
  59. data/lib/neography/rest/relationships.rb +16 -0
  60. data/lib/neography/rest/schema_indexes.rb +26 -0
  61. data/lib/neography/rest/spatial.rb +137 -0
  62. data/lib/neography/rest/transactions.rb +101 -0
  63. data/lib/neography/tasks.rb +207 -0
  64. data/lib/neography/version.rb +3 -0
  65. data/neography.gemspec +39 -0
  66. data/spec/integration/authorization_spec.rb +40 -0
  67. data/spec/integration/broken_spatial_spec.rb +28 -0
  68. data/spec/integration/index_spec.rb +71 -0
  69. data/spec/integration/neography_spec.rb +10 -0
  70. data/spec/integration/node_encoding_spec.rb +71 -0
  71. data/spec/integration/node_path_spec.rb +222 -0
  72. data/spec/integration/node_relationship_spec.rb +381 -0
  73. data/spec/integration/node_spec.rb +260 -0
  74. data/spec/integration/parsing_spec.rb +13 -0
  75. data/spec/integration/performance_spec.rb +17 -0
  76. data/spec/integration/relationship_spec.rb +37 -0
  77. data/spec/integration/rest_batch_no_streaming_spec.rb +41 -0
  78. data/spec/integration/rest_batch_spec.rb +604 -0
  79. data/spec/integration/rest_batch_streaming_spec.rb +51 -0
  80. data/spec/integration/rest_bulk_spec.rb +106 -0
  81. data/spec/integration/rest_constraints_spec.rb +72 -0
  82. data/spec/integration/rest_experimental_spec.rb +22 -0
  83. data/spec/integration/rest_gremlin_fail_spec.rb +46 -0
  84. data/spec/integration/rest_header_spec.rb +15 -0
  85. data/spec/integration/rest_index_spec.rb +481 -0
  86. data/spec/integration/rest_labels_spec.rb +128 -0
  87. data/spec/integration/rest_node_spec.rb +274 -0
  88. data/spec/integration/rest_other_node_relationship_spec.rb +137 -0
  89. data/spec/integration/rest_path_spec.rb +231 -0
  90. data/spec/integration/rest_plugin_spec.rb +177 -0
  91. data/spec/integration/rest_relationship_spec.rb +354 -0
  92. data/spec/integration/rest_relationship_types_spec.rb +18 -0
  93. data/spec/integration/rest_schema_index_spec.rb +32 -0
  94. data/spec/integration/rest_spatial_spec.rb +166 -0
  95. data/spec/integration/rest_transaction_spec.rb +166 -0
  96. data/spec/integration/rest_traverse_spec.rb +149 -0
  97. data/spec/integration/unmanaged_spec.rb +27 -0
  98. data/spec/matchers.rb +33 -0
  99. data/spec/neography_spec.rb +23 -0
  100. data/spec/spec_helper.rb +44 -0
  101. data/spec/unit/config_spec.rb +135 -0
  102. data/spec/unit/connection_spec.rb +284 -0
  103. data/spec/unit/node_spec.rb +100 -0
  104. data/spec/unit/properties_spec.rb +285 -0
  105. data/spec/unit/relationship_spec.rb +118 -0
  106. data/spec/unit/rest/batch_spec.rb +262 -0
  107. data/spec/unit/rest/clean_spec.rb +16 -0
  108. data/spec/unit/rest/constraints_spec.rb +45 -0
  109. data/spec/unit/rest/cypher_spec.rb +20 -0
  110. data/spec/unit/rest/extensions_spec.rb +28 -0
  111. data/spec/unit/rest/gremlin_spec.rb +25 -0
  112. data/spec/unit/rest/helpers_spec.rb +124 -0
  113. data/spec/unit/rest/labels_spec.rb +77 -0
  114. data/spec/unit/rest/node_auto_indexes_spec.rb +70 -0
  115. data/spec/unit/rest/node_indexes_spec.rb +140 -0
  116. data/spec/unit/rest/node_paths_spec.rb +77 -0
  117. data/spec/unit/rest/node_properties_spec.rb +79 -0
  118. data/spec/unit/rest/node_relationships_spec.rb +57 -0
  119. data/spec/unit/rest/node_traversal_spec.rb +35 -0
  120. data/spec/unit/rest/nodes_spec.rb +187 -0
  121. data/spec/unit/rest/relationship_auto_indexes_spec.rb +66 -0
  122. data/spec/unit/rest/relationship_indexes_spec.rb +132 -0
  123. data/spec/unit/rest/relationship_properties_spec.rb +79 -0
  124. data/spec/unit/rest/relationship_types_spec.rb +15 -0
  125. data/spec/unit/rest/relationships_spec.rb +21 -0
  126. data/spec/unit/rest/schema_index_spec.rb +30 -0
  127. data/spec/unit/rest/transactions_spec.rb +43 -0
  128. metadata +372 -0
@@ -0,0 +1,231 @@
1
+ require 'spec_helper'
2
+
3
+ describe Neography::Rest do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+ describe "get path" do
9
+ it "can get a path between two nodes" do
10
+ new_node1 = @neo.create_node
11
+ new_node2 = @neo.create_node
12
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
13
+ path = @neo.get_path(new_node1, new_node2, {"type"=> "friends", "direction" => "out"})
14
+ expect(path["start"]).to eq(new_node1["self"])
15
+ expect(path["end"]).to eq(new_node2["self"])
16
+ expect(path["nodes"]).to eq([new_node1["self"], new_node2["self"]])
17
+ end
18
+
19
+ it "can get the shortest path between two nodes" do
20
+ new_node1 = @neo.create_node
21
+ new_node2 = @neo.create_node
22
+ new_node3 = @neo.create_node
23
+ new_node4 = @neo.create_node
24
+ new_node5 = @neo.create_node
25
+ @neo.create_relationship("friends", new_node1, new_node2)
26
+ @neo.create_relationship("friends", new_node2, new_node3)
27
+ @neo.create_relationship("friends", new_node3, new_node4)
28
+ @neo.create_relationship("friends", new_node4, new_node5)
29
+ @neo.create_relationship("friends", new_node3, new_node5)
30
+ path = @neo.get_path(new_node1, new_node5, {"type"=> "friends", "direction" => "out"}, depth=3, algorithm="shortestPath")
31
+ expect(path["start"]).to eq(new_node1["self"])
32
+ expect(path["end"]).to eq(new_node5["self"])
33
+ expect(path["nodes"]).to eq([new_node1["self"], new_node2["self"], new_node3["self"], new_node5["self"]])
34
+ end
35
+
36
+ it "can get the shortest weighted path between two nodes" do
37
+ new_node1 = @neo.create_node
38
+ new_node2 = @neo.create_node
39
+ new_node3 = @neo.create_node
40
+ new_node4 = @neo.create_node
41
+ new_node5 = @neo.create_node
42
+ rel1_2 = @neo.create_relationship("friends", new_node1, new_node2)
43
+ rel2_3 = @neo.create_relationship("friends", new_node2, new_node3)
44
+ rel3_4 = @neo.create_relationship("friends", new_node3, new_node4)
45
+ rel4_5 = @neo.create_relationship("friends", new_node4, new_node5)
46
+ rel3_5 = @neo.create_relationship("friends", new_node3, new_node5)
47
+ @neo.set_relationship_properties(rel1_2, {:weight => 1})
48
+ @neo.set_relationship_properties(rel2_3, {:weight => 1})
49
+ @neo.set_relationship_properties(rel3_4, {:weight => 1})
50
+ @neo.set_relationship_properties(rel4_5, {:weight => 1})
51
+ @neo.set_relationship_properties(rel3_5, {:weight => 3})
52
+ path = @neo.get_shortest_weighted_path(new_node1, new_node5, {"type"=> "friends", "direction" => "out"})
53
+ expect(path.first["start"]).to eq(new_node1["self"])
54
+ expect(path.first["end"]).to eq(new_node5["self"])
55
+ expect(path.first["nodes"]).to eq([new_node1["self"], new_node2["self"], new_node3["self"], new_node4["self"], new_node5["self"]])
56
+ end
57
+
58
+ it "can get a simple path between two nodes" do
59
+ new_node1 = @neo.create_node
60
+ new_node2 = @neo.create_node
61
+ new_node3 = @neo.create_node
62
+ new_node4 = @neo.create_node
63
+ new_node5 = @neo.create_node
64
+ @neo.create_relationship("friends", new_node1, new_node2)
65
+ @neo.create_relationship("friends", new_node2, new_node3)
66
+ @neo.create_relationship("friends", new_node3, new_node4)
67
+ @neo.create_relationship("friends", new_node4, new_node5)
68
+ @neo.create_relationship("friends", new_node3, new_node5)
69
+ path = @neo.get_path(new_node1, new_node5, {"type"=> "friends", "direction" => "out"}, depth=3, algorithm="simplePaths")
70
+ expect(path["start"]).to eq(new_node1["self"])
71
+ expect(path["end"]).to eq(new_node5["self"])
72
+ expect(path["nodes"]).to eq([new_node1["self"], new_node2["self"], new_node3["self"], new_node5["self"]])
73
+ end
74
+
75
+ it "fails to get a path between two nodes 3 nodes apart when using max depth of 2" do
76
+ new_node1 = @neo.create_node
77
+ new_node2 = @neo.create_node
78
+ new_node3 = @neo.create_node
79
+ new_node4 = @neo.create_node
80
+ new_node5 = @neo.create_node
81
+ @neo.create_relationship("friends", new_node1, new_node2)
82
+ @neo.create_relationship("friends", new_node2, new_node3)
83
+ @neo.create_relationship("friends", new_node3, new_node4)
84
+ @neo.create_relationship("friends", new_node4, new_node5)
85
+ @neo.create_relationship("friends", new_node3, new_node5)
86
+ expect {
87
+ @neo.get_path(new_node1, new_node5, {"type"=> "friends", "direction" => "out"}, depth=2, algorithm="shortestPath")
88
+ }.to raise_error Neography::NotFoundException
89
+ end
90
+
91
+ it "can get a path between two nodes of a specific relationship" do
92
+ new_node1 = @neo.create_node
93
+ new_node2 = @neo.create_node
94
+ new_node3 = @neo.create_node
95
+ new_node4 = @neo.create_node
96
+ new_node5 = @neo.create_node
97
+ @neo.create_relationship("classmates", new_node1, new_node2)
98
+ @neo.create_relationship("classmates", new_node2, new_node5)
99
+ @neo.create_relationship("friends", new_node1, new_node2)
100
+ @neo.create_relationship("friends", new_node2, new_node3)
101
+ @neo.create_relationship("friends", new_node3, new_node4)
102
+ @neo.create_relationship("friends", new_node4, new_node5)
103
+ path = @neo.get_path(new_node1, new_node5, {"type"=> "friends", "direction" => "out"}, depth=4, algorithm="shortestPath")
104
+ expect(path["start"]).to eq(new_node1["self"])
105
+ expect(path["end"]).to eq(new_node5["self"])
106
+ expect(path["nodes"]).to eq([new_node1["self"], new_node2["self"], new_node3["self"], new_node4["self"], new_node5["self"]])
107
+ end
108
+ end
109
+
110
+ describe "get paths" do
111
+ it "can get the shortest paths between two nodes" do
112
+ new_node1 = @neo.create_node
113
+ new_node2 = @neo.create_node
114
+ new_node3 = @neo.create_node
115
+ new_node4 = @neo.create_node
116
+ new_node5 = @neo.create_node
117
+ @neo.create_relationship("friends", new_node1, new_node2)
118
+ @neo.create_relationship("friends", new_node2, new_node5)
119
+ @neo.create_relationship("friends", new_node1, new_node3)
120
+ @neo.create_relationship("friends", new_node3, new_node4)
121
+ @neo.create_relationship("friends", new_node4, new_node5)
122
+ @neo.create_relationship("friends", new_node3, new_node5)
123
+ paths = @neo.get_paths(new_node1, new_node5, {"type"=> "friends", "direction" => "out"}, depth=4, algorithm="shortestPath")
124
+ expect(paths.length).to eq(2)
125
+ expect(paths[0]["length"]).to eq(2)
126
+ expect(paths[0]["start"]).to eq(new_node1["self"])
127
+ expect(paths[0]["end"]).to eq(new_node5["self"])
128
+ expect(paths[1]["length"]).to eq(2)
129
+ expect(paths[1]["start"]).to eq(new_node1["self"])
130
+ expect(paths[1]["end"]).to eq(new_node5["self"])
131
+ end
132
+
133
+ it "can get all paths between two nodes" do
134
+ new_node1 = @neo.create_node
135
+ new_node2 = @neo.create_node
136
+ new_node3 = @neo.create_node
137
+ new_node4 = @neo.create_node
138
+ new_node5 = @neo.create_node
139
+ @neo.create_relationship("friends", new_node1, new_node2)
140
+ @neo.create_relationship("friends", new_node2, new_node5)
141
+ @neo.create_relationship("friends", new_node1, new_node3)
142
+ @neo.create_relationship("friends", new_node3, new_node4)
143
+ @neo.create_relationship("friends", new_node4, new_node5)
144
+ @neo.create_relationship("friends", new_node3, new_node5)
145
+ paths = @neo.get_paths(new_node1, new_node5, {"type"=> "friends", "direction" => "out"}, depth=4, algorithm="allPaths")
146
+ expect(paths.length).to eq(3)
147
+ expect(paths[0]["length"]).to eq(2)
148
+ expect(paths[0]["start"]).to eq(new_node1["self"])
149
+ expect(paths[0]["end"]).to eq(new_node5["self"])
150
+ expect(paths[1]["length"]).to eq(3)
151
+ expect(paths[1]["start"]).to eq(new_node1["self"])
152
+ expect(paths[1]["end"]).to eq(new_node5["self"])
153
+ expect(paths[2]["length"]).to eq(2)
154
+ expect(paths[2]["start"]).to eq(new_node1["self"])
155
+ expect(paths[2]["end"]).to eq(new_node5["self"])
156
+ end
157
+
158
+ it "can get all simple paths between two nodes" do
159
+ new_node1 = @neo.create_node
160
+ new_node2 = @neo.create_node
161
+ new_node3 = @neo.create_node
162
+ new_node4 = @neo.create_node
163
+ new_node5 = @neo.create_node
164
+ @neo.create_relationship("friends", new_node1, new_node2)
165
+ @neo.create_relationship("friends", new_node2, new_node1)
166
+ @neo.create_relationship("friends", new_node2, new_node5)
167
+ @neo.create_relationship("friends", new_node1, new_node3)
168
+ @neo.create_relationship("friends", new_node3, new_node4)
169
+ @neo.create_relationship("friends", new_node4, new_node5)
170
+ @neo.create_relationship("friends", new_node3, new_node5)
171
+ paths = @neo.get_paths(new_node1, new_node5, {"type"=> "friends", "direction" => "out"}, depth=4, algorithm="allSimplePaths")
172
+ expect(paths.length).to eq(3)
173
+ expect(paths[0]["length"]).to eq(2)
174
+ expect(paths[0]["start"]).to eq(new_node1["self"])
175
+ expect(paths[0]["end"]).to eq(new_node5["self"])
176
+ expect(paths[1]["length"]).to eq(3)
177
+ expect(paths[1]["start"]).to eq(new_node1["self"])
178
+ expect(paths[1]["end"]).to eq(new_node5["self"])
179
+ expect(paths[2]["length"]).to eq(2)
180
+ expect(paths[2]["start"]).to eq(new_node1["self"])
181
+ expect(paths[2]["end"]).to eq(new_node5["self"])
182
+ end
183
+
184
+ it "can get paths between two nodes of max depth 2" do
185
+ new_node1 = @neo.create_node
186
+ new_node2 = @neo.create_node
187
+ new_node3 = @neo.create_node
188
+ new_node4 = @neo.create_node
189
+ new_node5 = @neo.create_node
190
+ @neo.create_relationship("friends", new_node1, new_node2)
191
+ @neo.create_relationship("friends", new_node2, new_node5)
192
+ @neo.create_relationship("friends", new_node1, new_node3)
193
+ @neo.create_relationship("friends", new_node3, new_node4)
194
+ @neo.create_relationship("friends", new_node4, new_node5)
195
+ @neo.create_relationship("friends", new_node3, new_node5)
196
+ paths = @neo.get_paths(new_node1, new_node5, {"type"=> "friends", "direction" => "out"}, depth=2, algorithm="allPaths")
197
+ expect(paths.length).to eq(2)
198
+ expect(paths[0]["length"]).to eq(2)
199
+ expect(paths[0]["start"]).to eq(new_node1["self"])
200
+ expect(paths[0]["end"]).to eq(new_node5["self"])
201
+ expect(paths[1]["length"]).to eq(2)
202
+ expect(paths[1]["start"]).to eq(new_node1["self"])
203
+ expect(paths[1]["end"]).to eq(new_node5["self"]) end
204
+
205
+ it "can get paths between two nodes of a specific relationship" do
206
+ new_node1 = @neo.create_node
207
+ new_node2 = @neo.create_node
208
+ new_node3 = @neo.create_node
209
+ new_node4 = @neo.create_node
210
+ new_node5 = @neo.create_node
211
+ @neo.create_relationship("classmates", new_node1, new_node2)
212
+ @neo.create_relationship("classmates", new_node2, new_node5)
213
+ @neo.create_relationship("friends", new_node1, new_node2)
214
+ @neo.create_relationship("friends", new_node2, new_node3)
215
+ @neo.create_relationship("friends", new_node3, new_node4)
216
+ @neo.create_relationship("friends", new_node4, new_node5)
217
+ @neo.create_relationship("classmates", new_node1, new_node3)
218
+ @neo.create_relationship("classmates", new_node3, new_node5)
219
+ paths = @neo.get_paths(new_node1, new_node5, {"type"=> "classmates", "direction" => "out"}, depth=4, algorithm="allPaths")
220
+ expect(paths[0]["length"]).to eq(2)
221
+ expect(paths[0]["start"]).to eq(new_node1["self"])
222
+ expect(paths[0]["end"]).to eq(new_node5["self"])
223
+ expect(paths[1]["length"]).to eq(2)
224
+ expect(paths[1]["start"]).to eq(new_node1["self"])
225
+ expect(paths[1]["end"]).to eq(new_node5["self"])
226
+ end
227
+
228
+ end
229
+
230
+
231
+ end
@@ -0,0 +1,177 @@
1
+ # Encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Neography::Rest do
6
+ before(:each) do
7
+ @neo = Neography::Rest.new
8
+ end
9
+
10
+ describe "execute gremlin script" do
11
+ it "can get the root node id", :gremlin => true do
12
+ root_node = @neo.execute_script("g.v(0)")
13
+ expect(root_node).to have_key("self")
14
+ expect(root_node["self"].split('/').last).to eq("0")
15
+ end
16
+
17
+ it "can get the a node", :gremlin => true do
18
+ new_node = @neo.create_node
19
+ id = new_node["self"].split('/').last
20
+ existing_node = @neo.execute_script("g.v(#{id})")
21
+ expect(existing_node).not_to be_nil
22
+ expect(existing_node).to have_key("self")
23
+ expect(existing_node["self"].split('/').last).to eq(id)
24
+ end
25
+
26
+ it "can get the a node with a variable", :gremlin => true do
27
+ new_node = @neo.create_node
28
+ id = new_node["self"].split('/').last
29
+ existing_node = @neo.execute_script("g.v(id)", {:id => id.to_i})
30
+ expect(existing_node).not_to be_nil
31
+ expect(existing_node).to have_key("self")
32
+ expect(existing_node["self"].split('/').last).to eq(id)
33
+ end
34
+ end
35
+
36
+ describe "execute cypher query" do
37
+ it "can get the root node id" do
38
+ root_node = @neo.execute_query("start n=node(0) return n")
39
+ expect(root_node).to have_key("data")
40
+ expect(root_node).to have_key("columns")
41
+ expect(root_node["data"][0][0]).to have_key("self")
42
+ expect(root_node["data"][0][0]["self"].split('/').last).to eq("0")
43
+ end
44
+
45
+ it "can get the a node" do
46
+ new_node = @neo.create_node
47
+ id = new_node["self"].split('/').last
48
+ existing_node = @neo.execute_query("start n=node(#{id}) return n")
49
+ expect(existing_node).not_to be_nil
50
+ expect(existing_node).to have_key("data")
51
+ expect(existing_node).to have_key("columns")
52
+ expect(existing_node["data"][0][0]).to have_key("self")
53
+ expect(existing_node["data"][0][0]["self"].split('/').last).to eq(id)
54
+ end
55
+
56
+ it "can perform a range query" do
57
+ name = generate_text(6)
58
+ new_node = @neo.create_node({:number => 3})
59
+ id = new_node["self"].split('/').last
60
+ @neo.create_node_index(name, "fulltext","lucene")
61
+ @neo.add_node_to_index(name, "number", 3, new_node)
62
+ existing_node = @neo.find_node_index(name, "number:[1 TO 5]")
63
+ expect(existing_node.first["self"]).to eq(new_node["self"])
64
+ expect(existing_node.first).not_to be_nil
65
+ expect(existing_node.first["data"]["number"]).to eq(3)
66
+ existing_node = @neo.execute_query("start n=node:#{name}(\"number:[1 TO 5]\") return n")
67
+ expect(existing_node).to have_key("data")
68
+ expect(existing_node).to have_key("columns")
69
+ expect(existing_node["data"][0][0]).to have_key("self")
70
+ expect(existing_node["data"][0][0]["self"].split('/').last).to eq(id)
71
+ end
72
+
73
+ it "can perform a range query with a term" do
74
+ name = generate_text(6)
75
+ new_node = @neo.create_node({:number => 3, :name => "Max"})
76
+ id = new_node["self"].split('/').last
77
+ @neo.create_node_index(name, "fulltext","lucene")
78
+ @neo.add_node_to_index(name, "number", 3, new_node)
79
+ @neo.add_node_to_index(name, "name", "max", new_node)
80
+ existing_node = @neo.find_node_index(name, "name:max AND number:[1 TO 5]")
81
+ expect(existing_node.first["self"]).to eq(new_node["self"])
82
+ expect(existing_node.first).not_to be_nil
83
+ expect(existing_node.first["data"]["number"]).to eq(3)
84
+ expect(existing_node.first["data"]["name"]).to eq("Max")
85
+ existing_node = @neo.execute_query("start n=node:#{name}(\"name:max AND number:[1 TO 5]\") return n")
86
+ expect(existing_node).to have_key("data")
87
+ expect(existing_node).to have_key("columns")
88
+ expect(existing_node["data"][0][0]).to have_key("self")
89
+ expect(existing_node["data"][0][0]["self"].split('/').last).to eq(id)
90
+ end
91
+
92
+
93
+ it "can get a node with a tilde" do
94
+ new_node = @neo.create_node("name" => "Ateísmo Sureño")
95
+ id = new_node["self"].split('/').last
96
+ existing_node = @neo.execute_query("start n=node(#{id}) return n")
97
+ expect(existing_node).not_to be_nil
98
+ expect(existing_node).to have_key("data")
99
+ expect(existing_node).to have_key("columns")
100
+ expect(existing_node["data"][0][0]["self"].split('/').last).to eq(id)
101
+ expect(existing_node["data"][0][0]["data"]["name"]).to eq("Ateísmo Sureño")
102
+ end
103
+
104
+ it "can get the a node with a variable" do
105
+ new_node = @neo.create_node
106
+ id = new_node["self"].split('/').last
107
+ existing_node = @neo.execute_query("start n=node({id}) return n", {:id => id.to_i})
108
+ expect(existing_node).not_to be_nil
109
+ expect(existing_node).to have_key("data")
110
+ expect(existing_node).to have_key("columns")
111
+ expect(existing_node["data"][0][0]).to have_key("self")
112
+ expect(existing_node["data"][0][0]["self"].split('/').last).to eq(id)
113
+ end
114
+
115
+ it "can get the stats of a cypher query" do
116
+ root_node = @neo.execute_query("start n=node(0) return n", nil, {:stats => true})
117
+ expect(root_node).to have_key("data")
118
+ expect(root_node).to have_key("columns")
119
+ expect(root_node).to have_key("stats")
120
+ expect(root_node["data"][0][0]).to have_key("self")
121
+ expect(root_node["data"][0][0]["self"].split('/').last).to eq("0")
122
+ end
123
+
124
+ it "can get the profile of a cypher query" do
125
+ root_node = @neo.execute_query("start n=node(0) return n", nil, {:profile => true})
126
+ expect(root_node).to have_key("data")
127
+ expect(root_node).to have_key("columns")
128
+ expect(root_node).to have_key("plan")
129
+ expect(root_node["data"][0][0]).to have_key("self")
130
+ expect(root_node["data"][0][0]["self"].split('/').last).to eq("0")
131
+ end
132
+
133
+ it "can get the stats and profile of a cypher query" do
134
+ root_node = @neo.execute_query("start n=node(0) return n", nil, {:stats => true, :profile => true})
135
+ expect(root_node).to have_key("data")
136
+ expect(root_node).to have_key("columns")
137
+ expect(root_node).to have_key("stats")
138
+ expect(root_node).to have_key("plan")
139
+ expect(root_node["data"][0][0]).to have_key("self")
140
+ expect(root_node["data"][0][0]["self"].split('/').last).to eq("0")
141
+ end
142
+
143
+
144
+ it "can delete everything but start node", :reference => true do
145
+ @neo.execute_query("START n=node(*) MATCH n-[r?]-() WHERE ID(n) <> 0 DELETE n,r")
146
+ expect {
147
+ @neo.execute_query("start n=node({id}) return n", {:id => 1})
148
+ }.to raise_error(Neography::BadInputException)
149
+ root_node = @neo.execute_query("start n=node({id}) return n", {:id => 0})
150
+ expect(root_node).not_to be_nil
151
+ end
152
+
153
+ it "throws an error for an invalid query" do
154
+ expect {
155
+ @neo.execute_query("this is not a query")
156
+ }.to raise_error(Neography::SyntaxException)
157
+ end
158
+
159
+ it "throws an error for not unique paths in unique path creation" do
160
+ node1 = @neo.create_node
161
+ node2 = @neo.create_node
162
+
163
+ id1 = node1["self"].split('/').last.to_i
164
+ id2 = node2["self"].split('/').last.to_i
165
+
166
+ # create two 'FOO' relationships
167
+ @neo.execute_query("START a=node({id1}), b=node({id2}) CREATE a-[r:FOO]->b RETURN r", { :id1 => id1, :id2 => id2 })
168
+ @neo.execute_query("START a=node({id1}), b=node({id2}) CREATE a-[r:FOO]->b RETURN r", { :id1 => id1, :id2 => id2 })
169
+
170
+ expect {
171
+ @neo.execute_query("START a=node({id1}), b=node({id2}) CREATE UNIQUE a-[r:FOO]->b RETURN r", { :id1 => id1, :id2 => id2 })
172
+ }.to raise_error(Neography::UniquePathNotUniqueException)
173
+ end
174
+
175
+ end
176
+
177
+ end
@@ -0,0 +1,354 @@
1
+ require 'spec_helper'
2
+
3
+ describe Neography::Rest do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+ describe "create_relationship" do
9
+ it "can create an empty relationship" do
10
+ new_node1 = @neo.create_node
11
+ new_node2 = @neo.create_node
12
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
13
+ expect(new_relationship["start"]).not_to be_nil
14
+ expect(new_relationship["end"]).not_to be_nil
15
+ end
16
+
17
+ it "can create a relationship with one property" do
18
+ new_node1 = @neo.create_node
19
+ new_node1[:id] = new_node1["self"].split('/').last
20
+ new_node2 = @neo.create_node
21
+ new_node2[:id] = new_node2["self"].split('/').last
22
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010'})
23
+ expect(new_relationship["data"]["since"]).to eq('10-1-2010')
24
+ end
25
+
26
+ it "can create a relationship with more than one property" do
27
+ new_node1 = @neo.create_node
28
+ new_node2 = @neo.create_node
29
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college"})
30
+ expect(new_relationship["data"]["since"]).to eq('10-1-2010')
31
+ expect(new_relationship["data"]["met"]).to eq("college")
32
+ end
33
+
34
+ it "can create a unique node with more than one property" do
35
+ index_name = generate_text(6)
36
+ key = generate_text(6)
37
+ value = generate_text
38
+ @neo.create_node_index(index_name)
39
+ new_node = @neo.create_unique_node(index_name, key, value, {"age" => 31, "name" => "Max"})
40
+ expect(new_node["data"]["name"]).to eq("Max")
41
+ expect(new_node["data"]["age"]).to eq(31)
42
+ end
43
+
44
+ it "can create a unique relationship" do
45
+ index_name = generate_text(6)
46
+ key = generate_text(6)
47
+ value = generate_text
48
+ new_node1 = @neo.create_node
49
+ new_node2 = @neo.create_node
50
+ new_relationship = @neo.create_unique_relationship(index_name, key, value, "friends", new_node1, new_node2)
51
+ expect(new_relationship["data"][key]).to eq(value)
52
+ end
53
+
54
+ end
55
+
56
+ describe "get_relationship" do
57
+ it "can get a relationship that exists" do
58
+ new_node1 = @neo.create_node
59
+ new_node2 = @neo.create_node
60
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
61
+ existing_relationship = @neo.get_relationship(new_relationship)
62
+ expect(existing_relationship).not_to be_nil
63
+ expect(existing_relationship).to have_key("self")
64
+ expect(existing_relationship["self"]).to eq(new_relationship["self"])
65
+ end
66
+
67
+ it "raises error if it tries to get a relationship that does not exist" do
68
+ new_node1 = @neo.create_node
69
+ new_node2 = @neo.create_node
70
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
71
+ fake_relationship = new_relationship["self"].split('/').last.to_i + 1000
72
+ expect {
73
+ existing_relationship = @neo.get_relationship(fake_relationship)
74
+ }.to raise_error Neography::RelationshipNotFoundException
75
+ end
76
+ end
77
+
78
+ describe "set_relationship_properties" do
79
+ it "can set a relationship's properties" do
80
+ new_node1 = @neo.create_node
81
+ new_node2 = @neo.create_node
82
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
83
+ @neo.set_relationship_properties(new_relationship, {"since" => '10-1-2010', "met" => "college"})
84
+ @neo.set_relationship_properties(new_relationship, {"roommates" => "no"})
85
+ relationship_properties = @neo.get_relationship_properties(new_relationship)
86
+ expect(relationship_properties["since"]).to eq('10-1-2010')
87
+ expect(relationship_properties["met"]).to eq("college")
88
+ expect(relationship_properties["roommates"]).to eq("no")
89
+ end
90
+
91
+ it "it fails to set properties on a relationship that does not exist" do
92
+ new_node1 = @neo.create_node
93
+ new_node2 = @neo.create_node
94
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
95
+ fake_relationship = new_relationship["self"].split('/').last.to_i + 1000
96
+ expect {
97
+ @neo.set_relationship_properties(fake_relationship, {"since" => '10-1-2010', "met" => "college"})
98
+ }.to raise_error Neography::RelationshipNotFoundException
99
+ end
100
+ end
101
+
102
+ describe "reset_relationship_properties" do
103
+ it "can reset a relationship's properties" do
104
+ new_node1 = @neo.create_node
105
+ new_node2 = @neo.create_node
106
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
107
+ @neo.set_relationship_properties(new_relationship, {"since" => '10-1-2010', "met" => "college"})
108
+ @neo.reset_relationship_properties(new_relationship, {"roommates" => "no"})
109
+ relationship_properties = @neo.get_relationship_properties(new_relationship)
110
+ expect(relationship_properties["since"]).to be_nil
111
+ expect(relationship_properties["met"]).to be_nil
112
+ expect(relationship_properties["roommates"]).to eq("no")
113
+ end
114
+
115
+ it "it fails to reset properties on a relationship that does not exist" do
116
+ new_node1 = @neo.create_node
117
+ new_node2 = @neo.create_node
118
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
119
+ fake_relationship = new_relationship["self"].split('/').last.to_i + 1000
120
+ expect {
121
+ @neo.reset_relationship_properties(fake_relationship, {"since" => '10-1-2010', "met" => "college"})
122
+ }.to raise_error Neography::RelationshipNotFoundException
123
+ end
124
+ end
125
+
126
+ describe "get_relationship_properties" do
127
+ it "can get all of a relationship's properties" do
128
+ new_node1 = @neo.create_node
129
+ new_node2 = @neo.create_node
130
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college"})
131
+ relationship_properties = @neo.get_relationship_properties(new_relationship)
132
+ expect(relationship_properties["since"]).to eq('10-1-2010')
133
+ expect(relationship_properties["met"]).to eq("college")
134
+ end
135
+
136
+ it "can get some of a relationship's properties" do
137
+ new_node1 = @neo.create_node
138
+ new_node2 = @neo.create_node
139
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college", "roommates" => "no"})
140
+ relationship_properties = @neo.get_relationship_properties(new_relationship, ["since", "roommates"])
141
+ expect(relationship_properties["since"]).to eq('10-1-2010')
142
+ expect(relationship_properties["met"]).to be_nil
143
+ expect(relationship_properties["roommates"]).to eq("no")
144
+ end
145
+
146
+ it "returns nil if it gets the properties on a relationship that does not have any" do
147
+ new_node1 = @neo.create_node
148
+ new_node2 = @neo.create_node
149
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
150
+ relationship_properties = @neo.get_relationship_properties(new_relationship)
151
+ expect(relationship_properties).to be_nil
152
+ end
153
+
154
+ it "raises error if it tries to get some of the properties on a relationship that does not have any" do
155
+ new_node1 = @neo.create_node
156
+ new_node2 = @neo.create_node
157
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
158
+ expect {
159
+ @neo.get_relationship_properties(new_relationship, ["since", "roommates"])
160
+ }.to raise_error Neography::NoSuchPropertyException
161
+ end
162
+
163
+ it "raises error if it fails to get properties on a relationship that does not exist" do
164
+ new_node1 = @neo.create_node
165
+ new_node2 = @neo.create_node
166
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
167
+ fake_relationship = new_relationship["self"].split('/').last.to_i + 1000
168
+ expect {
169
+ @neo.get_relationship_properties(fake_relationship)
170
+ }.to raise_error Neography::RelationshipNotFoundException
171
+ end
172
+ end
173
+
174
+ describe "remove_relationship_properties" do
175
+ it "can remove a relationship's properties" do
176
+ new_node1 = @neo.create_node
177
+ new_node2 = @neo.create_node
178
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college"})
179
+ @neo.remove_relationship_properties(new_relationship)
180
+ expect(@neo.get_relationship_properties(new_relationship)).to be_nil
181
+ end
182
+
183
+ it "raises error if it fails to remove the properties of a relationship that does not exist" do
184
+ new_node1 = @neo.create_node
185
+ new_node2 = @neo.create_node
186
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college"})
187
+ fake_relationship = new_relationship["self"].split('/').last.to_i + 1000
188
+ expect {
189
+ @neo.remove_relationship_properties(fake_relationship)
190
+ }.to raise_error Neography::RelationshipNotFoundException
191
+ end
192
+
193
+ it "can remove a specific relationship property" do
194
+ new_node1 = @neo.create_node
195
+ new_node2 = @neo.create_node
196
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college"})
197
+ @neo.remove_relationship_properties(new_relationship, "met")
198
+ relationship_properties = @neo.get_relationship_properties(new_relationship)
199
+ expect(relationship_properties["met"]).to be_nil
200
+ expect(relationship_properties["since"]).to eq('10-1-2010')
201
+ end
202
+
203
+ it "can remove more than one relationship property" do
204
+ new_node1 = @neo.create_node
205
+ new_node2 = @neo.create_node
206
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college", "roommates" => "no"})
207
+ @neo.remove_relationship_properties(new_relationship, ["met", "since"])
208
+ relationship_properties = @neo.get_relationship_properties(new_relationship)
209
+ expect(relationship_properties["met"]).to be_nil
210
+ expect(relationship_properties["since"]).to be_nil
211
+ expect(relationship_properties["roommates"]).to eq("no")
212
+ end
213
+ end
214
+
215
+ describe "delete_relationship" do
216
+ it "can delete an existing relationship" do
217
+ new_node1 = @neo.create_node
218
+ new_node2 = @neo.create_node
219
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college"})
220
+ @neo.delete_relationship(new_relationship)
221
+ relationships = @neo.get_node_relationships(new_node1)
222
+ expect(relationships).to be_empty
223
+ end
224
+
225
+ it "raises error if it tries to delete a relationship that does not exist" do
226
+ new_node1 = @neo.create_node
227
+ new_node2 = @neo.create_node
228
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college"})
229
+ fake_relationship = new_relationship["self"].split('/').last.to_i + 1000
230
+ expect {
231
+ existing_relationship = @neo.delete_relationship(fake_relationship)
232
+ }.to raise_error Neography::RelationshipNotFoundException
233
+ end
234
+
235
+ it "returns nil if it tries to delete a relationship that has already been deleted" do
236
+ new_node1 = @neo.create_node
237
+ new_node2 = @neo.create_node
238
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2010', "met" => "college"})
239
+ existing_relationship = @neo.delete_relationship(new_relationship)
240
+ expect(existing_relationship).to be_nil
241
+ expect {
242
+ existing_relationship = @neo.delete_relationship(new_relationship)
243
+ }.to raise_error Neography::RelationshipNotFoundException
244
+ end
245
+ end
246
+
247
+ describe "get_node_relationships" do
248
+ it "can get a node's relationship" do
249
+ new_node1 = @neo.create_node
250
+ new_node2 = @neo.create_node
251
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
252
+ relationships = @neo.get_node_relationships(new_node1)
253
+ expect(relationships).not_to be_nil
254
+ expect(relationships[0]["start"]).to eq(new_node1["self"])
255
+ expect(relationships[0]["end"]).to eq(new_node2["self"])
256
+ expect(relationships[0]["type"]).to eq("friends")
257
+ expect(relationships[0]["data"]["met"]).to eq("college")
258
+ expect(relationships[0]["data"]["since"]).to eq('10-1-2005')
259
+ end
260
+
261
+ it "can get a node's multiple relationships" do
262
+ new_node1 = @neo.create_node
263
+ new_node2 = @neo.create_node
264
+ new_node3 = @neo.create_node
265
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
266
+ new_relationship = @neo.create_relationship("enemies", new_node1, new_node3, {"since" => '10-2-2010', "met" => "work"})
267
+ relationships = @neo.get_node_relationships(new_node1)
268
+ expect(relationships).not_to be_nil
269
+ expect(relationships[0]["start"]).to eq(new_node1["self"])
270
+ expect(relationships[0]["end"]).to eq(new_node2["self"])
271
+ expect(relationships[0]["type"]).to eq("friends")
272
+ expect(relationships[0]["data"]["met"]).to eq("college")
273
+ expect(relationships[0]["data"]["since"]).to eq('10-1-2005')
274
+ expect(relationships[1]["start"]).to eq(new_node1["self"])
275
+ expect(relationships[1]["end"]).to eq(new_node3["self"])
276
+ expect(relationships[1]["type"]).to eq("enemies")
277
+ expect(relationships[1]["data"]["met"]).to eq("work")
278
+ expect(relationships[1]["data"]["since"]).to eq('10-2-2010')
279
+ end
280
+
281
+ it "can get a node's outgoing relationship" do
282
+ new_node1 = @neo.create_node
283
+ new_node2 = @neo.create_node
284
+ new_node3 = @neo.create_node
285
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
286
+ new_relationship = @neo.create_relationship("enemies", new_node3, new_node1, {"since" => '10-2-2010', "met" => "work"})
287
+ relationships = @neo.get_node_relationships(new_node1, "out")
288
+ expect(relationships).not_to be_nil
289
+ expect(relationships[0]["start"]).to eq(new_node1["self"])
290
+ expect(relationships[0]["end"]).to eq(new_node2["self"])
291
+ expect(relationships[0]["type"]).to eq("friends")
292
+ expect(relationships[0]["data"]["met"]).to eq("college")
293
+ expect(relationships[0]["data"]["since"]).to eq('10-1-2005')
294
+ expect(relationships[1]).to be_nil
295
+ end
296
+
297
+ it "can get a node's incoming relationship" do
298
+ new_node1 = @neo.create_node
299
+ new_node2 = @neo.create_node
300
+ new_node3 = @neo.create_node
301
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
302
+ new_relationship = @neo.create_relationship("enemies", new_node3, new_node1, {"since" => '10-2-2010', "met" => "work"})
303
+ relationships = @neo.get_node_relationships(new_node1, "in")
304
+ expect(relationships).not_to be_nil
305
+ expect(relationships[0]["start"]).to eq(new_node3["self"])
306
+ expect(relationships[0]["end"]).to eq(new_node1["self"])
307
+ expect(relationships[0]["type"]).to eq("enemies")
308
+ expect(relationships[0]["data"]["met"]).to eq("work")
309
+ expect(relationships[0]["data"]["since"]).to eq('10-2-2010')
310
+ expect(relationships[1]).to be_nil
311
+ end
312
+
313
+ it "can get a specific type of node relationships" do
314
+ new_node1 = @neo.create_node
315
+ new_node2 = @neo.create_node
316
+ new_node3 = @neo.create_node
317
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
318
+ new_relationship = @neo.create_relationship("enemies", new_node1, new_node3, {"since" => '10-2-2010', "met" => "work"})
319
+ relationships = @neo.get_node_relationships(new_node1, "all", "friends")
320
+ expect(relationships).not_to be_nil
321
+ expect(relationships[0]["start"]).to eq(new_node1["self"])
322
+ expect(relationships[0]["end"]).to eq(new_node2["self"])
323
+ expect(relationships[0]["type"]).to eq("friends")
324
+ expect(relationships[0]["data"]["met"]).to eq("college")
325
+ expect(relationships[0]["data"]["since"]).to eq('10-1-2005')
326
+ expect(relationships[1]).to be_nil
327
+ end
328
+
329
+ it "can get a specific type and direction of a node relationships" do
330
+ new_node1 = @neo.create_node
331
+ new_node2 = @neo.create_node
332
+ new_node3 = @neo.create_node
333
+ new_node4 = @neo.create_node
334
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
335
+ new_relationship = @neo.create_relationship("enemies", new_node1, new_node3, {"since" => '10-2-2010', "met" => "work"})
336
+ new_relationship = @neo.create_relationship("enemies", new_node4, new_node1, {"since" => '10-3-2010', "met" => "gym"})
337
+ relationships = @neo.get_node_relationships(new_node1, "in", "enemies")
338
+ expect(relationships).not_to be_nil
339
+ expect(relationships[0]["start"]).to eq(new_node4["self"])
340
+ expect(relationships[0]["end"]).to eq(new_node1["self"])
341
+ expect(relationships[0]["type"]).to eq("enemies")
342
+ expect(relationships[0]["data"]["met"]).to eq("gym")
343
+ expect(relationships[0]["data"]["since"]).to eq('10-3-2010')
344
+ expect(relationships[1]).to be_nil
345
+ end
346
+
347
+ it "returns nil if there are no relationships" do
348
+ new_node1 = @neo.create_node
349
+ relationships = @neo.get_node_relationships(new_node1)
350
+ expect(relationships).to be_empty
351
+ end
352
+ end
353
+
354
+ end