arangorb 1.4.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/ArangoRB.gemspec +20 -18
  3. data/Gemfile +3 -0
  4. data/README.md +1079 -908
  5. data/lib/AQL.rb +155 -0
  6. data/lib/Batch.rb +97 -0
  7. data/lib/Cache.rb +71 -0
  8. data/lib/Collection.rb +852 -0
  9. data/lib/Database.rb +417 -0
  10. data/lib/Document.rb +346 -0
  11. data/lib/Edge.rb +104 -0
  12. data/lib/Error.rb +125 -0
  13. data/lib/Foxx.rb +277 -0
  14. data/lib/Graph.rb +325 -0
  15. data/lib/Index.rb +126 -0
  16. data/lib/Replication.rb +235 -0
  17. data/lib/Request.rb +143 -0
  18. data/lib/Server.rb +466 -0
  19. data/lib/Task.rb +120 -0
  20. data/lib/Transaction.rb +115 -0
  21. data/lib/Traversal.rb +224 -0
  22. data/lib/User.rb +197 -0
  23. data/lib/Vertex.rb +127 -0
  24. data/lib/View.rb +151 -0
  25. data/lib/arangorb.rb +23 -15
  26. data/lib/helpers/Error.rb +28 -0
  27. data/lib/helpers/Return.rb +53 -0
  28. metadata +64 -45
  29. data/lib/ArangoRB_AQL.rb +0 -181
  30. data/lib/ArangoRB_Cache.rb +0 -174
  31. data/lib/ArangoRB_Col.rb +0 -526
  32. data/lib/ArangoRB_DB.rb +0 -363
  33. data/lib/ArangoRB_Doc.rb +0 -319
  34. data/lib/ArangoRB_Edg.rb +0 -184
  35. data/lib/ArangoRB_Gra.rb +0 -201
  36. data/lib/ArangoRB_Index.rb +0 -135
  37. data/lib/ArangoRB_Replication.rb +0 -261
  38. data/lib/ArangoRB_Ser.rb +0 -446
  39. data/lib/ArangoRB_Task.rb +0 -129
  40. data/lib/ArangoRB_Tra.rb +0 -169
  41. data/lib/ArangoRB_Tran.rb +0 -68
  42. data/lib/ArangoRB_User.rb +0 -157
  43. data/lib/ArangoRB_Ver.rb +0 -162
  44. data/spec/arangoRB_helper.rb +0 -4
  45. data/spec/arangoRestart_helper.rb +0 -14
  46. data/spec/arangorb-1.3.0.gem +0 -0
  47. data/spec/lib/0.1.0/arangoAQL_helper.rb +0 -64
  48. data/spec/lib/0.1.0/arangoC_helper.rb +0 -170
  49. data/spec/lib/0.1.0/arangoDB_helper.rb +0 -119
  50. data/spec/lib/0.1.0/arangoDoc_helper.rb +0 -79
  51. data/spec/lib/0.1.0/arangoE_helper.rb +0 -50
  52. data/spec/lib/0.1.0/arangoG_helper.rb +0 -78
  53. data/spec/lib/0.1.0/arangoS_helper.rb +0 -37
  54. data/spec/lib/0.1.0/arangoT_helper.rb +0 -48
  55. data/spec/lib/0.1.0/arangoV_helper.rb +0 -65
  56. data/spec/lib/1.0.0/arangoC_helper.rb +0 -73
  57. data/spec/lib/1.0.0/arangoDB_helper.rb +0 -48
  58. data/spec/lib/1.0.0/arangoI_helper.rb +0 -43
  59. data/spec/lib/1.0.0/arangoS_helper.rb +0 -192
  60. data/spec/lib/1.0.0/arangoTa_helper.rb +0 -49
  61. data/spec/lib/1.0.0/arangoTr_helper.rb +0 -15
  62. data/spec/lib/1.0.0/arangoU_helper.rb +0 -72
  63. data/spec/lib/1.1.0/arangoRB_helper.rb +0 -144
  64. data/spec/lib/1.1.0/arangoRB_walks_helper.rb +0 -19
  65. data/spec/lib/1.2.0/arangoCache_helper.rb +0 -66
  66. data/spec/lib/1.3.0/arangoHash_helper.rb +0 -30
  67. data/spec/lib/arangoRB_0.1.0_helper.rb +0 -9
  68. data/spec/lib/arangoRB_1.0.0_helper.rb +0 -6
  69. data/spec/lib/arangoRB_1.1.0_helper.rb +0 -2
  70. data/spec/lib/arangoRB_1.2.0_helper.rb +0 -2
  71. data/spec/spec_helper.rb +0 -42
data/lib/ArangoRB_Task.rb DELETED
@@ -1,129 +0,0 @@
1
- # === AQL ===
2
-
3
- class ArangoTask < ArangoServer
4
- def initialize(database: @@database, id: nil, name: nil, type: nil, period: nil, command: nil, params: {}, created: nil) # TESTED
5
- if database.is_a?(String)
6
- @database = database
7
- elsif database.is_a?(ArangoDatabase)
8
- @database = database.database
9
- else
10
- raise "database should be a String or an ArangoDatabase instance, not a #{database.class}"
11
- end
12
- @id = id
13
- @name = name
14
- @type = type
15
- @period = period
16
- @command = command
17
- @params = params
18
- @created = created
19
- @idCache = "IND_#{@id}"
20
- end
21
-
22
- attr_reader :id, :name, :type, :period, :created, :command, :params, :idCache
23
-
24
- def to_hash
25
- {
26
- "id" => @id,
27
- "name" => @name,
28
- "database" => @database,
29
- "type" => @type,
30
- "period" => @period,
31
- "create" => @created,
32
- "command" => @command,
33
- "params" => @params,
34
- "idCache" => @idCache
35
- }.delete_if{|k,v| v.nil?}
36
- end
37
- alias to_h to_hash
38
-
39
- def database
40
- ArangoDatabase.new(database: @database)
41
- end
42
-
43
- def retrieve # TESTED
44
- result = self.class.get("/_db/#{@database}/_api/tasks/#{@id}")
45
- return result.headers["x-arango-async-id"] if @@async == "store"
46
- return true if @@async
47
- result = result.parsed_response
48
- if @@verbose
49
- unless result.is_a?(Hash) && result["error"]
50
- @name = result["name"]
51
- @type = result["type"]
52
- @period = result["period"]
53
- @created = result["created"]
54
- @command = result["command"]
55
- @database = result["database"]
56
- end
57
- result
58
- else
59
- if result.is_a?(Hash) && result["error"]
60
- result["errorMessage"]
61
- else
62
- @name = result["name"]
63
- @type = result["type"]
64
- @period = result["period"]
65
- @created = result["created"]
66
- @command = result["command"]
67
- @database = result["database"]
68
- self
69
- end
70
- end
71
- end
72
-
73
- def self.tasks # TESTED
74
- result = get("/_db/#{@@database}/_api/tasks", @@request)
75
- return result.headers["x-arango-async-id"] if @@async == "store"
76
- return true if @@async
77
- result = result.parsed_response
78
- @@verbose ? result : (result.is_a?(Hash) && result["error"]) ? result["errorMessage"] : result.map{|x| ArangoTask.new(id: x["id"], name: x["name"], type: x["type"], period: x["period"], created: x["created"], command: x["command"], database: x["database"])}
79
- end
80
-
81
- def create offset: nil # TESTED
82
- body = {
83
- "name" => @name,
84
- "command" => @command,
85
- "period" => @period,
86
- "offset" => offset,
87
- "params" => @params
88
- }.delete_if{|k,v| v.nil?}.to_json
89
- request = @@request.merge({ :body => body })
90
- if @id.nil?
91
- result = self.class.post("/_db/#{@database}/_api/tasks", request)
92
- else
93
- result = self.class.put("/_db/#{@database}/_api/tasks/#{@id}", request)
94
- end
95
- return result.headers["x-arango-async-id"] if @@async == "store"
96
- return true if @@async
97
- result = result.parsed_response
98
- if @@verbose
99
- unless result.is_a?(Hash) && result["error"]
100
- @id = result["id"]
101
- @name = result["name"]
102
- @type = result["type"]
103
- @period = result["period"]
104
- @created = result["created"]
105
- @command = result["command"]
106
- @database = result["database"]
107
- end
108
- result
109
- else
110
- return result["errorMessage"] if result.is_a?(Hash) && result["error"]
111
- @id = result["id"]
112
- @name = result["name"]
113
- @type = result["type"]
114
- @period = result["period"]
115
- @created = result["created"]
116
- @command = result["command"]
117
- @database = result["database"]
118
- self
119
- end
120
- end
121
-
122
- def destroy # TESTED
123
- result = self.class.delete("/_db/#{@database}/_api/tasks/#{@id}", @@request)
124
- return result.headers["x-arango-async-id"] if @@async == "store"
125
- return true if @@async
126
- result = result.parsed_response
127
- @@verbose ? result : (result.is_a?(Hash) && result["error"]) ? result["errorMessage"] : true
128
- end
129
- end
data/lib/ArangoRB_Tra.rb DELETED
@@ -1,169 +0,0 @@
1
- # === TRAVERSAL ===
2
-
3
- class ArangoTraversal < ArangoServer
4
- def initialize(body: {}, database: @@database, graph: nil, edgeCollection: nil) # TESTED
5
- @sort = body["sort"]
6
- @direction = body["direction"]
7
- @maxDepth = body["maxDepth"]
8
- @minDepth = body["minDepth"]
9
- @startVertex = body["startVertex"]
10
- @visitor = body["visitor"]
11
- @itemOrder = body["itemOrder"]
12
- @strategy = body["strategy"]
13
- @filter = body["filter"]
14
- @init = body["init"]
15
- @maxiterations = body["maxiterations"]
16
- @uniqueness = body["uniqueness"]
17
- @order = body["order"]
18
- @graphName = body["graphName"].nil? ? graph : body["graphName"]
19
- @expander = body["expander"]
20
- @edgeCollection = body["edgeCollection"].nil? ? edgeCollection : body["edgeCollection"]
21
- @database = database
22
- @vertices = nil
23
- @paths = nil
24
- @idCache = "ATR_#{@database}_#{@direction}_#{@startVertex}_" + (@graphName.nil? ? "#{@edgeCollection}" : "#{@graphName}")
25
- end
26
-
27
- attr_accessor :sort, :direction, :maxDepth, :minDepth, :visitor, :itemOrder, :strategy, :filter, :init, :maxiterations, :uniqueness, :order, :expander
28
- attr_reader :idCache, :vertices, :paths
29
-
30
- ### RETRIEVE ###
31
-
32
- def to_hash
33
- {
34
- "database" => @database,
35
- "sort" => @sort,
36
- "direction" => @direction,
37
- "maxDepth" => @maxDepth,
38
- "minDepth" => @minDepth,
39
- "startVertex" => @startVertex,
40
- "visitor" => @visitor,
41
- "itemOrder" => @itemOrder,
42
- "strategy" => @strategy,
43
- "filter" => @filter,
44
- "init" => @init,
45
- "maxiterations" => @maxiterations,
46
- "uniqueness" => @uniqueness,
47
- "order" => @order,
48
- "graphName" => @graphName,
49
- "expander" => @expander,
50
- "edgeCollection" => @edgeCollection,
51
- "vertices" => @vertices.map{|x| x.id},
52
- "paths" => @paths.map{|x| {"edges" => x["edges"].map{|e| e.id}, "vertices" => x["vertices"].map{|v| v.id} } },
53
- "idCache" => @idCache
54
- }.delete_if{|k,v| v.nil?}
55
- end
56
- alias to_h to_hash
57
-
58
- def startVertex
59
- val = @startVertex.split("/")
60
- ArangoDocument.new(database: @database, collection: val[0], key: val[1])
61
- end
62
-
63
- def edgeCollection
64
- ArangoCollection.new(collection: @edgeCollection, database: @database)
65
- end
66
-
67
- def database
68
- ArangoDatabase.new(database: @database)
69
- end
70
-
71
- def graphName
72
- ArangoGraph.new(graph: @graphName, database: @database).retrieve
73
- end
74
-
75
- def startVertex=(startVertex) # TESTED
76
- if startVertex.is_a?(String)
77
- @startVertex = startVertex
78
- elsif startVertex.is_a?(ArangoDocument)
79
- @startVertex = startVertex.id
80
- else
81
- raise "startVertex should be a String or an ArangoDocument instance, not a #{startVertex.class}"
82
- end
83
- @idCache = "ATR_#{@database}_#{@direction}_#{@startVertex}_" + (@graphName.nil? ? "#{@edgeCollection}" : "#{@graphName}")
84
- end
85
-
86
- def graphName=(graphName) # TESTED
87
- if graphName.is_a?(String) || graphName.nil?
88
- @graphName = graphName
89
- elsif graphName.is_a?(ArangoGraph)
90
- @graphName = graphName.graph
91
- else
92
- raise "graphName should be a String or an ArangoGraph instance, not a #{graphName.class}"
93
- end
94
- @idCache = "ATR_#{@database}_#{@direction}_#{@startVertex}_" + (@graphName.nil? ? "#{@edgeCollection}" : "#{@graphName}")
95
- end
96
-
97
- def edgeCollection=(edgeCollection) # TESTED
98
- if edgeCollection.is_a?(String) || edgeCollection.nil?
99
- @edgeCollection = edgeCollection
100
- elsif edgeCollection.is_a?(ArangoCollection)
101
- @edgeCollection = edgeCollection.collection
102
- else
103
- raise "edgeCollection should be a String or an ArangoCollection instance, not a #{edgeCollection.class}"
104
- end
105
- @idCache = "ATR_#{@database}_#{@direction}_#{@startVertex}_" + (@graphName.nil? ? "#{@edgeCollection}" : "#{@graphName}")
106
- end
107
-
108
- def in # TESTED
109
- @direction = "inbound"
110
- @idCache = "ATR_#{@database}_#{@direction}_#{@startVertex}_" + (@graphName.nil? ? "#{@edgeCollection}" : "#{@graphName}")
111
- end
112
-
113
- def out # TESTED
114
- @direction = "outbound"
115
- @idCache = "ATR_#{@database}_#{@direction}_#{@startVertex}_" + (@graphName.nil? ? "#{@edgeCollection}" : "#{@graphName}")
116
- end
117
-
118
- def any # TESTED
119
- @direction = "any"
120
- @idCache = "ATR_#{@database}_#{@direction}_#{@startVertex}_" + (@graphName.nil? ? "#{@edgeCollection}" : "#{@graphName}")
121
- end
122
-
123
- alias vertex= startVertex=
124
- alias vertex startVertex
125
- alias max maxDepth
126
- alias max= maxDepth=
127
- alias min minDepth
128
- alias min= minDepth=
129
- alias collection edgeCollection
130
- alias collection= edgeCollection=
131
- alias graph graphName
132
- alias graph= graphName=
133
-
134
- def execute # TESTED
135
- body = {
136
- "sort" => @sort,
137
- "direction" => @direction,
138
- "maxDepth" => @maxDepth,
139
- "minDepth" => @minDepth,
140
- "startVertex" => @startVertex,
141
- "visitor" => @visitor,
142
- "itemOrder" => @itemOrder,
143
- "strategy" => @strategy,
144
- "filter" => @filter,
145
- "init" => @init,
146
- "maxiterations" => @maxiterations,
147
- "uniqueness" => @uniqueness,
148
- "order" => @order,
149
- "graphName" => @graphName,
150
- "expander" => @expander,
151
- "edgeCollection" => @edgeCollection
152
- }.delete_if{|k,v| v.nil?}
153
- request = @@request.merge({ :body => body.to_json })
154
- result = self.class.post("/_db/#{@database}/_api/traversal", request)
155
- return result.headers["x-arango-async-id"] if @@async == "store"
156
- return true if @@async
157
- result = result.parsed_response
158
- return @@verbose ? result : result["errorMessage"] if result["error"]
159
- @vertices = result["result"]["visited"]["vertices"].map{|x| ArangoDocument.new(key: x["_key"], collection: x["_id"].split("/")[0], database: @database, body: x)}
160
- @paths = result["result"]["visited"]["paths"].map{|x|
161
- {
162
- "edges" => x["edges"].map{|e| ArangoDocument.new(key: e["_key"], collection: e["_id"].split("/")[0], database: @database, body: e, from: e["_from"], to: e["_to"] )},
163
- "vertices" => x["vertices"].map{|v| ArangoDocument.new(key: v["_key"], collection: v["_id"].split("/")[0], database: @database, body: v )}
164
- }
165
- }
166
- @idCache = "ATR_#{@database}_#{@direction}_#{@startVertex}_" + (@graphName.nil? ? "#{@edgeCollection}" : "#{@graphName}")
167
- @@verbose ? result : self
168
- end
169
- end
data/lib/ArangoRB_Tran.rb DELETED
@@ -1,68 +0,0 @@
1
- # === TRANSACTION ===
2
-
3
- class ArangoTransaction < ArangoServer
4
- def initialize(database: @@database, action:, write: [], read: [], params: nil, lockTimeout: nil, waitForSync: nil) # TESTED
5
- if database.is_a?(String)
6
- @database = database
7
- elsif database.is_a?(ArangoDatabase)
8
- @database = database.database
9
- else
10
- raise "database should be a String or an ArangoDatabase instance, not a #{database.class}"
11
- end
12
- @action = action
13
- @collections = {}
14
- @collections["write"] = write.is_a?(Array) ? write.map{ |x| x.is_a?(String) ? x : x.is_a?(ArangoCollection) ? x.collection : nil } : write.is_a?(String) ? [write] : write.is_a?(ArangoCollection) ? [write.collection] : []
15
- @collections["read"] = read.is_a?(Array) ? read.map{ |x| x.is_a?(String) ? x : x.is_a?(ArangoCollection) ? x.collection : nil } : read.is_a?(String) ? [read] : read.is_a?(ArangoCollection) ? [read.collection] : []
16
- @params = params
17
- @lockTimeout = lockTimeout
18
- @waitForSync = waitForSync
19
- @result = nil
20
- @idCache = "AT_#{@database}_#{Random.rand(0..10^12)}"
21
- end
22
-
23
- attr_reader :action, :params, :lockTimeout, :waitForSync, :idCache
24
-
25
- ### RETRIEVE ###
26
-
27
- def to_hash
28
- {
29
- "database" => @database,
30
- "action" => @action,
31
- "collections" => @collections,
32
- "result" => @result,
33
- "params" => @params,
34
- "lockTimeout" => @lockTimeout,
35
- "waitForSync" => @waitForSync,
36
- "idCache" => @idCache
37
- }.delete_if{|k,v| v.nil?}
38
- end
39
- alias to_h to_hash
40
-
41
- def collections
42
- result = {}
43
- result["write"] = @collections["write"].map{|x| ArangoCollection.new(database: @database, collection: x)} unless @collections["write"].nil?
44
- result["read"] = @collections["read"].map{|x| ArangoCollection.new(database: @database, collection: x)} unless @collections["read"].nil?
45
- result
46
- end
47
-
48
- def database
49
- ArangoDatabase.new(database: @database)
50
- end
51
-
52
- def execute # TESTED
53
- body = {
54
- "action" => @action,
55
- "collections" => @collections,
56
- "params" => @params,
57
- "lockTimeout" => @lockTimeout,
58
- "waitForSync" => @waitForSync
59
- }.delete_if{|k,v| v.nil?}.to_json
60
- request = @@request.merge({ :body => body })
61
- result = self.class.post("/_db/#{@database}/_api/transaction", request)
62
- return result.headers["x-arango-async-id"] if @@async == "store"
63
- return true if @@async
64
- result = result.parsed_response
65
- @result = result["result"] unless result["error"]
66
- @@verbose ? result : result["error"] ? {"message": result["errorMessage"], "stacktrace": result["stacktrace"]} : result["result"]
67
- end
68
- end
data/lib/ArangoRB_User.rb DELETED
@@ -1,157 +0,0 @@
1
- # === USER ===
2
-
3
- class ArangoUser < ArangoServer
4
- def initialize(user: @@user, password: nil, active: nil, extra: nil) # TESTED
5
- @password = password
6
- @user = user
7
- @active = active
8
- @extra = extra
9
- @idCache = "USER_#{@user}"
10
- end
11
-
12
- attr_reader :user, :active, :extra, :idCache
13
- alias name user
14
-
15
- def to_hash
16
- {
17
- "user" => @user,
18
- "active" => @active,
19
- "extra" => @extra,
20
- "idCache" => @idCache
21
- }.delete_if{|k,v| v.nil?}
22
- end
23
- alias to_h to_hash
24
-
25
- def [](database)
26
- if self.databases[database] == "rw"
27
- ArangoDatabase.new database: database
28
- else
29
- "This User does not have access to Database #{database}."
30
- end
31
- end
32
- alias database []
33
-
34
- def create # TESTED
35
- body = {
36
- "user" => @user,
37
- "passwd" => @password,
38
- "active" => @active,
39
- "extra" => @extra
40
- }.delete_if{|k,v| v.nil?}.to_json
41
- request = @@request.merge({ :body => body })
42
- result = self.class.post("/_api/user", request)
43
- return_result result: result
44
- end
45
-
46
- def retrieve # TESTED
47
- result = self.class.get("/_api/user/#{@user}", @@request)
48
- return_result result: result
49
- end
50
-
51
- def grant(database: @@database) # TESTED
52
- database = database.database if database.is_a?(ArangoDatabase)
53
- body = { "grant" => "rw" }.to_json
54
- request = @@request.merge({ :body => body })
55
- result = self.class.put("/_api/user/#{@user}/database/#{database}", request)
56
- return_result result: result, caseTrue: true
57
- end
58
-
59
- def grant_read(database: @@database) # TESTED
60
- database = database.database if database.is_a?(ArangoDatabase)
61
- body = { "grant" => "ro" }.to_json
62
- request = @@request.merge({ :body => body })
63
- result = self.class.put("/_api/user/#{@user}/database/#{database}", request)
64
- return_result result: result, caseTrue: true
65
- end
66
-
67
- def revoke(database: @@database) # TESTED
68
- database = database.database if database.is_a?(ArangoDatabase)
69
- body = { "grant" => "none" }.to_json
70
- request = @@request.merge({ :body => body })
71
- result = self.class.put("/_api/user/#{@user}/database/#{database}", request)
72
- return_result result: result, caseTrue: true
73
- end
74
-
75
- def databases # TESTED
76
- result = self.class.get("/_api/user/#{@user}/database/", @@request)
77
- return_result result: result, key: "result"
78
- end
79
-
80
- def replace(password:, active: nil, extra: nil) # TESTED
81
- body = {
82
- "passwd" => password,
83
- "active" => active,
84
- "extra" => extra
85
- }.delete_if{|k,v| v.nil?}.to_json
86
- request = @@request.merge({ :body => body })
87
- result = self.class.put("/_api/user/#{@user}", request)
88
- return result.headers["x-arango-async-id"] if @@async == "store"
89
- return true if @@async
90
- result = result.parsed_response
91
- if @@verbose
92
- unless result["error"]
93
- @password = password
94
- @active = active.nil? || active
95
- @extra = extra
96
- end
97
- result
98
- else
99
- return result["errorMessage"] if result["error"]
100
- @password = password
101
- @active = active.nil? || active
102
- @extra = extra
103
- self
104
- end
105
- end
106
-
107
- def update(password: , active: nil, extra: nil) # TESTED
108
- body = {
109
- "passwd" => password,
110
- "active" => active,
111
- "extra" => extra
112
- }.delete_if{|k,v| v.nil?}.to_json
113
- request = @@request.merge({ :body => body })
114
- result = self.class.patch("/_api/user/#{@user}", request)
115
- return result.headers["x-arango-async-id"] if @@async == "store"
116
- return true if @@async
117
- result = result.parsed_response
118
- if @@verbose
119
- unless result["error"]
120
- @password = password
121
- @active = active.nil? || active
122
- @extra = extra
123
- end
124
- result
125
- else
126
- return result["errorMessage"] if result["error"]
127
- @password = password
128
- @active = active.nil? || active
129
- @extra = extra
130
- self
131
- end
132
- end
133
-
134
- def destroy # TESTED
135
- result = self.class.delete("/_api/user/#{@user}", @@request)
136
- return_result result: result, caseTrue: true
137
- end
138
-
139
- def return_result(result:, caseTrue: false, key: nil)
140
- return result.headers["x-arango-async-id"] if @@async == "store"
141
- return true if @@async
142
- result = result.parsed_response
143
- if @@verbose || !result.is_a?(Hash)
144
- unless result["error"]
145
- @active = result["active"]
146
- @extra = result["extra"]
147
- end
148
- result
149
- else
150
- return result["errorMessage"] if result["error"]
151
- @active = result["active"]
152
- @extra = result["extra"]
153
- return true if caseTrue
154
- key.nil? ? self : result[key]
155
- end
156
- end
157
- end