arcadedb 0.4 → 0.5.0

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.
@@ -23,34 +23,38 @@ module Arcade
23
23
  if response.is_a? Hash
24
24
  # save rid to a safe place
25
25
  temp_rid = response.delete :"@rid"
26
- type = response.delete :"@type"
27
- cat = response.delete :"@cat"
26
+ type = response.delete :"@type"
27
+ cat = response.delete :"@cat"
28
28
 
29
29
  return response if type.nil?
30
30
  temp_rid = "#0:0" if temp_rid.nil?
31
31
  type = "d" if type.nil?
32
32
  # extract type infos and convert to database-name
33
- n, type_name = type.camelcase_and_namespace
34
- n = self.namespace if n.nil?
33
+ namespace, type_name = type.camelcase_and_namespace
34
+ namespace = self.namespace if namespace.nil?
35
35
  # autoconvert rid's in attributes to model-records (exclude edges!)
36
36
  if auto && !(cat.to_s =='e')
37
37
  response.transform_values! do |x|
38
38
  case x
39
39
  when String
40
- x.rid? ? x.load_rid : x
40
+ x.rid? ? x.load_rid : x # follow links
41
41
  when Array
42
+ a =[]
42
43
  x.map do| y |
43
- if y.is_a?(Hash) && y.include?(:@type) # if embedded documents are present, load them
44
- y.allocate_model(false)
45
- elsif y.rid? # if links are present, load the object
46
- y.load_rid(false) # do not autoload further records, prevents from recursive locking
47
- else
48
- y
49
- end
44
+ # Thread.new do ## thread or fiber decrease the performance significantly.
45
+ if y.is_a?(Hash) && y.include?(:@type) # if embedded documents are present, load them
46
+ y.allocate_model(false)
47
+ elsif y.rid? # if links are present, load the object
48
+ y.load_rid(false) # do not autoload further records, prevents from recursive locking
49
+ else
50
+ y
51
+ end
52
+ # end
50
53
  end
51
54
  when Hash
52
55
  if x.include?(:@type)
53
- x.allocate_model(false)
56
+ #x.allocate_model(false)
57
+ _allocate_model(x,false)
54
58
  else
55
59
  x.transform_values!{|z| z.rid? ? z.load_rid(false) : z }
56
60
  end
@@ -60,7 +64,7 @@ module Arcade
60
64
  end
61
65
  end
62
66
  # choose the appropriate class
63
- klass= Dry::Core::ClassBuilder.new( name: type_name, parent: nil, namespace: n).call
67
+ klass= Dry::Core::ClassBuilder.new( name: type_name, parent: nil, namespace: namespace ).call
64
68
  #
65
69
  begin
66
70
  # create a new object of that class with the appropriate attributes
@@ -74,10 +78,11 @@ module Arcade
74
78
  elsif response.is_a? Array
75
79
  puts "Allocate_model..detected array"
76
80
  ## recursive behavior, just in case
77
- response.map{ | y | _allocate_model y }
81
+ response.map{ | y | _allocate_model y, auto }
78
82
  elsif response.rid?
79
83
  # Autoload rid's
80
84
  response.load_rid
85
+ # auto ? response.load_rid : response
81
86
  else
82
87
  response
83
88
  end
@@ -1,3 +1,3 @@
1
1
  module Arcade
2
- VERSION = "0.4"
2
+ VERSION = "0.5.0"
3
3
  end
data/lib/arcade.rb CHANGED
@@ -16,21 +16,21 @@ require 'yaml'
16
16
  require 'securerandom'
17
17
  require 'httpx'
18
18
  require 'arcade/errors'
19
- require_relative '../lib/support/object'
20
- require_relative '../lib/support/string'
21
- require_relative '../lib/support/class'
22
- require_relative '../lib/support/sql'
23
- require_relative '../lib/support/model'
24
- require_relative '../lib/arcade/logging'
25
- require_relative '../lib/config'
26
- require_relative '../lib/support/conversions'
19
+ require_relative '../lib/arcade/support/object'
20
+ require_relative '../lib/arcade/support/string'
21
+ require_relative '../lib/arcade/support/class'
22
+ require_relative '../lib/arcade/support/sql'
23
+ require_relative '../lib/arcade/support/model'
24
+ require_relative '../lib/arcade/support/conversions'
27
25
  require_relative '../lib/arcade/api/primitives'
28
26
  require_relative '../lib/arcade/api/operations'
29
27
  require_relative '../lib/arcade/base'
28
+ require_relative '../lib/arcade/logging'
29
+ require_relative '../lib/arcade/config'
30
30
  require_relative '../lib/arcade/database'
31
- require_relative '../lib/init'
31
+ require_relative '../lib/arcade/match'
32
+ require_relative '../lib/arcade/query'
33
+ require_relative '../lib/arcade/init'
32
34
  require_relative "../lib/models"
33
- require_relative '../lib/query'
34
- require_relative '../lib/match'
35
35
  require_relative '../lib/railtie' if defined? Rails::Railtie
36
36
 
@@ -6,5 +6,27 @@ module Arcade
6
6
  # def accepted_methods
7
7
  #
8
8
  # end
9
+ def self.create **attributes
10
+ Api.create_document db.database, database_name, session_id: db.session, **attributes
11
+ end
12
+
13
+ =begin
14
+ Document.delete fires a "delete vertex" command to the database.
15
+ To remove all records use »all: true« as argument
16
+
17
+ The "where" parameter is optional
18
+ =end
19
+ def self.delete where: {} , **args
20
+ if args[:all] == true
21
+ where = {}
22
+ else
23
+ where.merge!(args) if where.is_a?(Hash)
24
+ return 0 if where.empty?
25
+ end
26
+ # query returns [{count => n }]
27
+ # puts "delete from #{database_name} #{compose_where(where)}"
28
+ db.transmit { "delete from `#{database_name}` #{compose_where(where)}" } &.first[:count] rescue 0
29
+ end
30
+
9
31
  end
10
32
  end
data/lib/model/edge.rb CHANGED
@@ -13,6 +13,18 @@ module Arcade
13
13
  #
14
14
  def self.create from:, to:, **attr
15
15
  db.create_edge database_name, from: from, to: to, **attr
16
+ rescue Arcade::QueryError => e
17
+ if e.message =~ /Duplicated key\s+.+\sfound on index/
18
+ if e.args.keys.first == :exceptionArgs
19
+ # return the previously assigned edge
20
+ e.args[:exceptionArgs].split('|').last.load_rid
21
+ else
22
+ raise
23
+ end
24
+ else
25
+ raise
26
+ end
27
+
16
28
  end
17
29
 
18
30
  def delete
data/lib/model/vertex.rb CHANGED
@@ -13,45 +13,46 @@ module Arcade
13
13
  end
14
14
  ## ----------------------------------------- Class Methods------------------------------------ ##
15
15
  # #
16
+
16
17
  =begin
17
- Vertex.delete fires a "delete vertex" command to the database.
18
+ Creates a Vertex-Instance.
19
+ Similar to `Vertex#insert`.
18
20
 
19
- To remove all records use »all: true« as argument
21
+ Difference is the presence of a `created` property, a timestamp set to the time and date of creation.
22
+ =end
23
+
24
+ def self.create timestamp: true, **args
25
+ #t= timestamp ? ", created = Date(#{DateTime.now.to_i}) " : ""
26
+ t= timestamp ? ", created = sysdate() " : ""
27
+ # db.transmit { "create VERTEX #{database_name} set #{args.map{|x,y| [x,y.to_or].join("=")}.join(', ')+t}" } &.first.allocate_model(false)
28
+ Api.create_document db.database, database_name, session_id: db.session, **args
29
+ end
20
30
 
21
- To remove a specific rid, use rid: "#nn:mmm" as argument
22
31
 
23
- "where" parameter is optional
32
+ =begin
33
+ Vertex.delete fires a "delete vertex" command to the database.
34
+ To remove all records use »all: true« as argument
35
+ To remove a specific rid, use rid: "#nn:mmm" as argument
24
36
 
25
- ExtraNode.delete where: { item: 67 } == ExtraNode.delete item: 67
37
+ The "where" parameter is optional
26
38
 
39
+ Example:
40
+ ExtraNode.delete where: { item: 67 } == ExtraNode.delete item: 67
27
41
  =end
28
42
  def self.delete where: {} , **args
29
43
  if args[:all] == true
30
44
  where = {}
31
45
  elsif args[:rid].present?
32
- return db.execute { "delete vertex #{args[:rid]}" }.first["count"]
46
+ return db.transmit { "delete from #{args[:rid]}" }.first["count"]
33
47
  else
34
48
  where.merge!(args) if where.is_a?(Hash)
35
49
  return 0 if where.empty?
36
50
  end
37
51
  # query returns [{count => n }]
38
- db.execute { "delete vertex #{database_name} #{compose_where(where)}" } &.first[:count] rescue 0
52
+ # puts "delete from #{database_name} #{compose_where(where)}"
53
+ db.transmit { "delete from `#{database_name}` #{compose_where(where)}" } &.first[:count] rescue 0
39
54
  end
40
55
 
41
- =begin
42
- Creates a Vertex-Instance.
43
- Similar to `Vertex#insert`.
44
-
45
- Difference is the presence of a `created` property, a timestamp set to the time and date of creation.
46
- =end
47
-
48
- def self.create timestamp: true, **args
49
- #t= timestamp ? ", created = Date(#{DateTime.now.to_i}) " : ""
50
- t= timestamp ? ", created = sysdate() " : ""
51
- db.execute { "create VERTEX #{database_name} set #{args.map{|x,y| [x,y.to_or].join("=")}.join(', ')+t}" } &.first.allocate_model(false)
52
- end
53
-
54
-
55
56
  ## get adjacent nodes based on a query on the actual model
56
57
 
57
58
 
@@ -71,22 +72,41 @@ module Arcade
71
72
  def expand
72
73
  self
73
74
  end
74
- # Supports where: --> Strategie.first nodes where: {size: 10}
75
- # "select both()[ size = 10 ] from #113:8 "
75
+ # --------------------------------- Nodes ----------------------------------------------- #
76
+ # fetches adjacet nodes
77
+ # supported
78
+ # nodes in_or_out = :in, :out, :both, :inE, :outE
79
+ # depth = fetch the n'th node through travese
80
+ # via: = Arcade Database Type (the ruby class)
81
+ # where: = a condition
82
+ # inE, outE --> matches attributes on the edge
83
+ # in, out, both -> matches attributes on the adjacent vertex
84
+ # Example Strategie.first nodes where: {size: 10}
85
+ # "select both()[ size = 10 ] from #113:8 "
86
+ #
76
87
  def nodes in_or_out=:both, depth= 1, via: nil , execute: true, **args
77
- s = Query.new from: rid
78
- s.nodes in_or_out, via: via, **args
79
- if execute
80
- s.query &.select_result
81
- else
82
- s # just return the query
83
- end
88
+ if depth <= 1
89
+ s= query.nodes in_or_out, via: via, **args
90
+ execute ? s.query &.select_result : s
91
+ else
92
+ travese in_or_out, depth: depth, start_at: depth-1, via: via, execute: execute, where: args[:where]
93
+ end
84
94
  end
85
95
 
86
96
  # Supports where: { where condition for edges }
87
- def edges in_or_out = :both, depth= 1, via: nil , execute: true, **args
88
- in_or_out = in_or_out.to_s + "E"
89
- nodes in_or_out, depth, via: via , execute: execute, **args
97
+ def edges in_or_out = :both, depth= 1, via: nil , execute: true
98
+
99
+ v = in_or_out.to_s.delete_suffix 'E'
100
+ e = v + 'E'
101
+ edge_name = via.nil? ? "" : resolve_edge_name( via )
102
+ argument = "#{e}(#{edge_name})"
103
+ q= if depth > 1
104
+ repeated_argument = Array.new(depth -1 , "#{v}(#{edge_name})").join(".")
105
+ query.projection repeated_argument + "." + argument
106
+ else
107
+ query.projection argument
108
+ end
109
+ execute ? q.execute &.allocate_model : q
90
110
  end
91
111
 
92
112
 
@@ -120,17 +140,17 @@ module Arcade
120
140
 
121
141
  # get via-type-edges through in
122
142
  def inE count=1, via:nil
123
- nodes :inE, count, via: via
143
+ edges :in, count, via: via
124
144
  end
125
145
  #
126
146
  # get via-type-edges through out
127
147
  def outE count=1, via:nil
128
- nodes :outE, count, via: via
148
+ edges :out, count, via: via
129
149
  end
130
150
 
131
151
  # get all via-type-edges
132
152
  def bothE count=1, via:nil
133
- nodes :bothE, count, via: via
153
+ edges :both, count, via: via
134
154
  end
135
155
 
136
156
 
@@ -158,34 +178,33 @@ module Arcade
158
178
  the_query.where where if where.present?
159
179
  the_query.while "$depth < #{depth} " unless depth <=0
160
180
  outer_query = Query.new from: the_query, where: "$depth >= #{start_at}"
161
- if execute
162
- outer_query.execute.allocate_model
163
- else
164
- # the_query.from self # complete the query by assigning self
165
- the_query # returns the Query -traverse object
166
- end
181
+ execute ? outer_query.execute.allocate_model : the_query # return only the traverse part
167
182
  end
168
183
 
169
184
  =begin
170
185
  Assigns another Vertex via an EdgeClass. If specified, puts attributes on the edge.
171
186
 
187
+ `Vertex.assign via: Edge to: Vertex`
188
+
172
189
  Returns the reloaded assigned vertex
173
190
 
174
191
  Wrapper for
175
- Edge.create in: self, out: a_vertex, some: attributes. on: the, edge: type }
192
+ Edge.create from: self, to: a_vertex, some: attributes. on: the, edge: type }
176
193
 
177
194
  returns the assigned vertex, thus enabling to chain vertices through
178
195
 
179
- Vertex.assign() via: E , vertex: VertexClass.create()).assign( via: E, ... )
196
+ Vertex.assign() via: E , to: VertexClass.create()).assign( via: E, ... )
180
197
  or
181
198
  (1..100).each{|n| vertex = vertex.assign(via: E2, vertex: V2.create(item: n))}
182
199
  =end
183
200
 
184
- def assign vertex: , via: , **attributes
201
+ def assign vertex: nil , via: Arcade::Edge , **attributes
202
+ vertex = attributes[:to] if attributes.has_key? :to
203
+ raise "vertex not provided" if vertex.nil?
185
204
 
186
205
  via.create from: self, to: vertex, **attributes
187
206
 
188
- db.get vertex.rid # return the assigned vertex
207
+ db.get vertex.rid unless vertex.is_a? Array # return the assigned vertex
189
208
  rescue IndexError => e
190
209
  db.logger.error "Edge not created, already present."
191
210
  vertex # return the vertex (for chaining)
@@ -205,12 +224,12 @@ Format: < Classname: Edges, Attributes >
205
224
  =end
206
225
  def to_human
207
226
 
208
- in_and_out = -> { "{#{self.in.count}->}{->#{self.out.count }}, " }
227
+ in_and_out = "{#{inE.count}->}{->#{outE.count }}, "
209
228
 
210
229
  #Default presentation of Arcade::Base::Model-Objects
211
230
 
212
231
  "<#{self.class.to_s.snake_case}[#{rid}]:" +
213
- in_and_out[] +
232
+ in_and_out +
214
233
  invariant_attributes.map do |attr, value|
215
234
  v= case value
216
235
  when Class
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arcadedb
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.4'
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hartmut Bischoff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-25 00:00:00.000000000 Z
11
+ date: 2023-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -144,17 +144,27 @@ files:
144
144
  - examples/relation_1__1.rb
145
145
  - examples/relation_1__n.rb
146
146
  - examples/relation_n_n.rb
147
+ - iruby/.ipynb_checkpoints/01-start-and-end-of-datarows-checkpoint.ipynb
148
+ - iruby/01-start-and-end-of-datarows.ipynb
149
+ - iruby/db-console.rb
147
150
  - lib/arcade.rb
148
151
  - lib/arcade/api/operations.rb
149
152
  - lib/arcade/api/primitives.rb
150
153
  - lib/arcade/base.rb
154
+ - lib/arcade/config.rb
151
155
  - lib/arcade/database.rb
152
156
  - lib/arcade/errors.rb
157
+ - lib/arcade/init.rb
153
158
  - lib/arcade/logging.rb
159
+ - lib/arcade/match.rb
160
+ - lib/arcade/query.rb
161
+ - lib/arcade/support/class.rb
162
+ - lib/arcade/support/conversions.rb
163
+ - lib/arcade/support/model.rb
164
+ - lib/arcade/support/object.rb
165
+ - lib/arcade/support/sql.rb
166
+ - lib/arcade/support/string.rb
154
167
  - lib/arcade/version.rb
155
- - lib/config.rb
156
- - lib/init.rb
157
- - lib/match.rb
158
168
  - lib/model/basicdocument.rb
159
169
  - lib/model/basicedge.rb
160
170
  - lib/model/basicvertex.rb
@@ -162,13 +172,6 @@ files:
162
172
  - lib/model/edge.rb
163
173
  - lib/model/vertex.rb
164
174
  - lib/models.rb
165
- - lib/query.rb
166
- - lib/support/class.rb
167
- - lib/support/conversions.rb
168
- - lib/support/model.rb
169
- - lib/support/object.rb
170
- - lib/support/sql.rb
171
- - lib/support/string.rb
172
175
  - rails.md
173
176
  - rails/arcade.rb
174
177
  - rails/config.yml
data/lib/match.rb DELETED
@@ -1,216 +0,0 @@
1
- #require 'active_support/inflector'
2
-
3
- module Arcade
4
- ######################## MatchConnection ###############################
5
-
6
- MatchAttributes = Struct.new(:edge, :direction, :as, :count, :where, :while, :max_depth , :depth_alias, :path_alias, :optional )
7
-
8
- # where and while can be composed incremental
9
- # direction, as, connect and edge cannot be changed after initialisation
10
- class MatchConnection
11
- include Support::Sql
12
-
13
- def initialize edge= nil, direction: :both, as: nil, count: 1, **args
14
-
15
- the_edge = edge.is_a?( Class ) ? edge.ref_name : edge.to_s unless edge.nil? || edge == E
16
- @q = MatchAttributes.new the_edge , # class
17
- direction, # may be :both, :in, :out
18
- as, # a string
19
- count, # a number
20
- args[:where],
21
- args[:while],
22
- args[:max_depth],
23
- args[:depth_alias], # not implemented
24
- args[:path_alias], # not implemented
25
- args[:optional] # not implemented
26
- end
27
-
28
- def direction= dir
29
- @q[:direction] = dir
30
- end
31
-
32
-
33
- def direction
34
- fillup = @q[:edge].present? ? @q[:edge] : ''
35
- case @q[:direction]
36
- when :both
37
- ".both(#{fillup})"
38
- when :in
39
- ".in(#{fillup})"
40
- when :out
41
- ".out(#{fillup})"
42
- when :both_vertex, :bothV
43
- ".bothV()"
44
- when :out_vertex, :outV
45
- ".outV()"
46
- when :in_vertex, :inV
47
- ".inV()"
48
- when :both_edge, :bothE
49
- ".bothE(#{fillup})"
50
- when :out_edge, :outE
51
- ".outE(#{fillup})"
52
- when :in_edge, :outE
53
- ".inE(#{fillup})"
54
- end
55
-
56
- end
57
-
58
- def count c=nil
59
- if c
60
- @q[:count] = c
61
- else
62
- @q[:count]
63
- end
64
- end
65
-
66
- def max_depth d=nil
67
- if d.nil?
68
- @q[:max_depth].present? ? "maxDepth: #{@q[:max_depth] }" : nil
69
- else
70
- @q[:max_depth] = d
71
- end
72
- end
73
- def edge
74
- @q[:edge]
75
- end
76
-
77
- def compose
78
- where_statement =( where.nil? || where.size <5 ) ? nil : "where: ( #{ generate_sql_list( @q[:where] ) })"
79
- while_statement =( while_s.nil? || while_s.size <5) ? nil : "while: ( #{ generate_sql_list( @q[:while] )})"
80
-
81
- ministatement = "{"+ [ as, where_statement, while_statement, max_depth].compact.join(', ') + "}"
82
- ministatement = "" if ministatement=="{}"
83
-
84
- (1 .. count).map{|x| direction }.join("") + ministatement
85
-
86
- end
87
- alias :to_s :compose
88
-
89
- end # class
90
-
91
-
92
- ######################## MatchStatement ################################
93
-
94
- MatchSAttributes = Struct.new(:match_class, :as, :where )
95
- class MatchStatement
96
- include Support
97
- def initialize match_class, as: 0, **args
98
- reduce_class = ->(c){ c.is_a?(Class) ? c.ref_name : c.to_s }
99
-
100
- @q = MatchSAttributes.new( reduce_class[match_class], # class
101
- as.respond_to?(:zero?) && as.zero? ? reduce_class[match_class].pluralize : as ,
102
- args[ :where ])
103
-
104
- @query_stack = [ self ]
105
- end
106
-
107
- def match_alias
108
- "as: #{@q[:as]}"
109
- end
110
-
111
-
112
-
113
- # used for the first compose-statement of a compose-query
114
- def compose_simple
115
- where_statement = where.is_a?(String) && where.size <3 ? nil : "where: ( #{ generate_sql_list( @q[:where] ) })"
116
- '{'+ [ "class: #{@q[:match_class]}", as , where_statement].compact.join(', ') + '}'
117
- end
118
-
119
-
120
- def << connection
121
- @query_stack << connection
122
- self # return MatchStatement
123
- end
124
- #
125
- def compile &b
126
- "match " + @query_stack.map( &:to_s ).join + return_statement( &b )
127
- end
128
-
129
-
130
- # executes the standard-case.
131
- # returns
132
- # * as: :hash : an array of hashes
133
- # * as: :array : an array of hash-values
134
- # * as :flatten: a simple array of hash-values
135
- #
136
- # The optional block is used to customize the output.
137
- # All previously defiend »as«-Statements are provided though the control variable.
138
- #
139
- # Background
140
- # A match query "Match {class aaa, as: 'aa'} return aa "
141
- #
142
- # returns [ aa: { result of the query, a Vertex or a value-item }, aa: {}...}, ...] ]
143
- # (The standard case)
144
- #
145
- # A match query "Match {class aaa, as: 'aa'} return aa.name "
146
- # returns [ aa.name: { name }, aa.name: { name }., ...] ]
147
- #
148
- # Now, execute( as: :flatten){ "aa.name" } returns
149
- # [name1, name2 ,. ...]
150
- #
151
- #
152
- # Return statements (examples from https://orientdb.org/docs/3.0.x/sql/SQL-Match.html)
153
- # "person.name as name, friendship.since as since, friend.name as friend"
154
- #
155
- # " person.name + \" is a friend of \" + friend.name as friends"
156
- #
157
- # "$matches"
158
- # "$elements"
159
- # "$paths"
160
- # "$pathElements"
161
- #
162
- #
163
- def execute as: :hash, &b
164
- r = V.db.execute{ compile &b }
165
- case as
166
- when :hash
167
- r
168
- when :array
169
- r.map{|y| y.values}
170
- when :flatten
171
- r.map{|y| y.values}.orient_flatten
172
- else
173
- raise ArgumentError, "Specify parameter «as:» with :hash, :array, :flatten"
174
- end
175
- end
176
- # def compose
177
- #
178
- # '{'+ [ "class: #{@q[:match_class]}",
179
- # "as: #{@as}" , where, while_s,
180
- # @maxdepth >0 ? "maxdepth: #{maxdepth}": nil ].compact.join(', ')+'}'
181
- # end
182
-
183
- alias :to_s :compose_simple
184
-
185
-
186
- ## return_statement
187
- #
188
- # summarizes defined as-statements ready to be included as last parameter
189
- # in the match-statement-stack
190
- #
191
- # They can be modified through a block.
192
- #
193
- # i.e
194
- #
195
- # t= TestQuery.match( where: {a: 9, b: 's'}, as: nil ) << E.connect("<-", as: :test)
196
- # t.return_statement{|y| "#{y.last}.name"}
197
- #
198
- # =>> " return test.name"
199
- #
200
- #return_statement is always called through compile
201
- #
202
- # t.compile{|y| "#{y.last}.name"}
203
-
204
- private
205
- def return_statement
206
- resolve_as = ->{ @query_stack.map{|s| s.as.split(':').last unless s.as.nil? }.compact }
207
- " return " + statement = if block_given?
208
- a= yield resolve_as[]
209
- a.is_a?(Array) ? a.join(', ') : a
210
- else
211
- resolve_as[].join(', ')
212
- end
213
- end
214
- end # class
215
-
216
- end # module
File without changes
File without changes
File without changes
File without changes
File without changes