Module: Pacer::Core::Route
- Included in:
- PacerGraph, Route
- Defined in:
- lib/pacer/core/route.rb,
lib/pacer/transform/path.rb,
lib/pacer/transform/branch.rb,
lib/pacer/transform/gather.rb,
lib/pacer/transform/scatter.rb,
lib/pacer/filter/random_filter.rb,
lib/pacer/filter/collection_filter.rb
Overview
The basic internal logic for routes and core route shared methods are defined here. Many of these methods are designed to be specialized by other modules included after Core::Route is included.
Defined Under Namespace
Classes: DetachedPipe, DetachedRoute
Instance Attribute Summary collapse
-
#hide_elements ⇒ true, false
If true, elements won’t be printed to STDOUT when #inspect is called on this route.
-
#info ⇒ Object
Returns the value of attribute info.
-
#lookahead_replacement ⇒ Object
If a route’s function won’t do the expected thing in a lookahead, set a proc here that will correct the route.
-
#pipe_args ⇒ [Object]
The arguments passed to the pipe constructor.
-
#pipe_class ⇒ Object
Specify which pipe class will be instantiated when an iterator is created.
-
#remove_from_lookahead ⇒ Object
If this piece of the route is useless in a lookahead, set this to true and when it is at the tail of a lookahead, it will be removed automatically.
-
#route_name ⇒ Object
Replace the generated class name of this route with a specific one by setting route_name.
Instance Method Summary collapse
- #-(other) ⇒ Object
-
#==(other) ⇒ true, false
Returns true if the other route is defined the same as the current route.
-
#add_extensions(exts) ⇒ self
If any objects in the given array are modules that contain a Route submodule, extend this route with the Route module.
- #branch(&block) ⇒ Object
- #chain_route(args_hash) ⇒ Object
- #cond(where, &block) ⇒ Object
- #description(join = ' -> ') ⇒ Object
-
#detach ⇒ Object
Returns an outer proc that returns an inner proc that will execute the given route for a given input data or element.
-
#each {|item| ... } ⇒ Enumerator
Iterates over each element or object resulting from traversing the route up to this point.
-
#empty? ⇒ Boolean
Returns true if this route currently has no elements.
- #except(excluded) ⇒ Object
-
#from_graph?(g) ⇒ Boolean
Returns true if the given graph is the one this route operates on.
- #gather(into = nil, &block) ⇒ Object
-
#graph ⇒ PacerGraph
Return which graph this route operates on.
- #help(section = nil) ⇒ Object
-
#inspect(limit = nil) ⇒ String
Returns a string representation of the route definition.
- #no_extensions ⇒ Object
- #only(included) ⇒ Object
- #paths(*exts) ⇒ Object
-
#pipe {|java.util.Iterator| ... } ⇒ java.util.Iterator
Returns a single use pipe iterator based on this route.
-
#random(bias = 0.5) ⇒ Object
Return elements based on a bias:1 chance.
-
#root? ⇒ Boolean
Return true if this route is at the beginning of the route definition.
-
#route ⇒ self
Prevents the route from being evaluated when it is inspected.
- #scatter(args = {}) ⇒ Object
- #set_extensions(exts) ⇒ Object
-
#set_pipe_source(src) ⇒ Object
Change the source of this route.
- #set_wrapper(wrapper) ⇒ Object
-
#vars ⇒ Hash
Returns the hash of variables used during the previous evaluation of the route.
Instance Attribute Details
#hide_elements ⇒ true, false
If true, elements won’t be printed to STDOUT when #inspect is called on this route.
27 28 29 |
# File 'lib/pacer/core/route.rb', line 27 def hide_elements @hide_elements end |
#info ⇒ Object
Returns the value of attribute info.
19 20 21 |
# File 'lib/pacer/core/route.rb', line 19 def info @info end |
#lookahead_replacement ⇒ Object
If a route’s function won’t do the expected thing in a lookahead, set a proc here that will correct the route. For instance:
g.v.lookahead { |v| v[:prop] }
gets transformed to:
g.v.lookahead { |v| v.property?(:prop) }
43 44 45 |
# File 'lib/pacer/core/route.rb', line 43 def lookahead_replacement @lookahead_replacement end |
#pipe_args ⇒ [Object] #pipe_args=(args) ⇒ [Object] #pipe_args=(args) ⇒ [Object]
The arguments passed to the pipe constructor.
73 74 75 |
# File 'lib/pacer/core/route.rb', line 73 def pipe_args @pipe_args end |
#pipe_class ⇒ Object
Specify which pipe class will be instantiated when an iterator is created.
22 23 24 |
# File 'lib/pacer/core/route.rb', line 22 def pipe_class @pipe_class end |
#remove_from_lookahead ⇒ Object
If this piece of the route is useless in a lookahead, set this to true and when it is at the tail of a lookahead, it will be removed automatically. (for instance the property decoder, or wrap/unwrap)
32 33 34 |
# File 'lib/pacer/core/route.rb', line 32 def remove_from_lookahead @remove_from_lookahead end |
#route_name ⇒ Object
Replace the generated class name of this route with a specific one by setting route_name.
18 19 20 |
# File 'lib/pacer/core/route.rb', line 18 def route_name @route_name end |
Instance Method Details
#-(other) ⇒ Object
12 13 14 |
# File 'lib/pacer/filter/collection_filter.rb', line 12 def -(other) chain_route :filter => :collection, :except => other end |
#==(other) ⇒ true, false
Returns true if the other route is defined the same as the current route.
Note that block filters will prevent matches even with identically defined routes unless the routes are actually the same object.
351 352 353 354 355 356 357 |
# File 'lib/pacer/core/route.rb', line 351 def ==(other) other.class == self.class and other.function == function and other.element_type == element_type and other.back == back and other.pacer_source == pacer_source end |
#add_extensions(exts) ⇒ self
If any objects in the given array are modules that contain a Route submodule, extend this route with the Route module.
371 372 373 |
# File 'lib/pacer/core/route.rb', line 371 def add_extensions(exts) chain_route extensions: (extensions - exts) + exts end |
#branch(&block) ⇒ Object
4 5 6 7 |
# File 'lib/pacer/transform/branch.rb', line 4 def branch(&block) route = chain_route transform: ::Pacer::Transform::Branch route.add_block! &block end |
#chain_route(args_hash) ⇒ Object
60 61 62 |
# File 'lib/pacer/core/route.rb', line 60 def chain_route(args_hash) Pacer::RouteBuilder.current.chain self, args_hash end |
#cond(where, &block) ⇒ Object
9 10 11 12 |
# File 'lib/pacer/transform/branch.rb', line 9 def cond(where, &block) route = chain_route transform: ::Pacer::Transform::Branch route.add_cond! where, &block end |
#description(join = ' -> ') ⇒ Object
296 297 298 |
# File 'lib/pacer/core/route.rb', line 296 def description(join = ' -> ') "#<#{inspect_strings.join(join)}>" end |
#detach ⇒ Object
Returns an outer proc that returns an inner proc that will execute the given route for a given input data or element.
The outer proc contains the already-compiled route (the most expensive part of the process). When you call it, it returns the inner proc. If you call it with no arguments, it will prepare the proc in the context of the original route used to create it. In a multi-tenant or multi-graph system, call the outer proc with the current graph to prepare so that it correctly wraps returned elements.
The inner proc contains a non-thread-safe data pipeline compiled from the route. Call it with an item of input data for the detached pipe and it will execute the pipeline for that piece of data and return the result or results.
A detached route can be configured with or without gather enabled. If enabled (default), the result will be an ArrayList of all result data produced by the detached route. If not, the result will be either the first thing produced by the route or null if nothing was produced.
396 397 398 399 |
# File 'lib/pacer/core/route.rb', line 396 def detach route = yield Pacer::Route.empty(self) DetachedRoute.new route end |
#each {|item| ... } ⇒ Enumerator
Iterates over each element or object resulting from traversing the route up to this point.
125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/pacer/core/route.rb', line 125 def each iter = iterator iter = configure_iterator(iter) if block_given? while true yield iter.next end else iter end rescue Pacer::EmptyPipe, java.util.NoSuchElementException self end |
#empty? ⇒ Boolean
Returns true if this route currently has no elements.
360 361 362 |
# File 'lib/pacer/core/route.rb', line 360 def empty? none? end |
#except(excluded) ⇒ Object
4 5 6 7 8 9 10 |
# File 'lib/pacer/filter/collection_filter.rb', line 4 def except(excluded) if excluded.is_a? Symbol chain_route :filter => :collection, :except_var => excluded else chain_route :filter => :collection, :except => excluded end end |
#from_graph?(g) ⇒ Boolean
Returns true if the given graph is the one this route operates on.
56 57 58 |
# File 'lib/pacer/core/route.rb', line 56 def from_graph?(g) graph.equals g end |
#gather(into = nil, &block) ⇒ Object
4 5 6 |
# File 'lib/pacer/transform/gather.rb', line 4 def gather(into = nil, &block) aggregate(into, &block).cap(element_type: :array) end |
#graph ⇒ PacerGraph
Return which graph this route operates on.
48 49 50 51 52 53 |
# File 'lib/pacer/core/route.rb', line 48 def graph config.fetch :graph do src = @back || @pacer_source src.graph if src.respond_to? :graph end end |
#help(section = nil) ⇒ Object
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/pacer/core/route.rb', line 154 def help(section = nil) general_topics = <<HELP Some general help sections: :routes What are Pacer's routes? :basics Simple usage examples :creation How to create records :tools Some things you can do :graphs Available graphs :help How to contribute to Pacer's inline help HELP if section == :help puts <<HELP Contributions of help topics will be greatly apreciated. Help topics should be added to the modules that they describe. General topics help can be added here for now but will likely be moved eventually. See lib/pacer/transform/map.rb for an example of how to define contextual help topics. If you add a general topic, remember to add it to the list above. Remember to call super for unrecognized sections! :) HELP elsif section == :routes puts <<HELP Pacer's routes are a very efficient and fast way to deal with data. The fundamental thing about them is that they are lazily evaluated, which allows very expensive traversals to be defined, yet nearly always produces results immediately with very low memory requirements, too. HELP elsif section == :basics puts <<HELP Pacer basics: g = Pacer.tg # create an in-memory graph # - help(:graphs) for other types g.v # create a route to all vertices in the graph # vertices are your basic documents. g.e # ... or all edges # edges connect documents. They can have properties, too! g.v(name: 'Sue', gender: 'male') # find all boys named Sue # all elements are schemaless, so you # can specify any properties g.v(name: 'Sue', gender: 'male').count # how many are there? # see how we can chain calls? Powerful # traversals can be defined this way. g.v.out_e(:friend) # see Sue's 'friend' relationships g.v.out_e(:friend).in_v # continue on to his friends g.v.out_e(:friend).in_v.out(:friends) # continue on to his friends-of-friends g.v.in(:friend) # see who has friended Sue. # all edges are directional to follow an # edge, use #out or #out_e; to go # backwards along an edge, use #in or # #in_e #{general_topics} HELP elsif section == :creation puts <<HELP How we can create records in a Pacer graph: g = Pacer.tg # create a new in-memory graph to play with sue = g.create_vertex name: 'Sue', gender: 'male' # create a record with properties ghost = g.create_vertex # get lazy and create an empty one sue.add_edges_to :friend, ghost # Sue has friended the ghost. # This relationship can be traversed in # both directions so a reverse # relationship is *not* required, but can # be created: ghost.add_edges_to :friend, sue, type: 'spooky' # We can also create edges with properties sue[:age] = 27 # It's that easy to add or change a property sue['fav foods'] = [pie, donuts] # Pacer can shoehorn any data into the # graph as long as it's serializable. #{general_topics} HELP elsif section == :tools puts <<HELP HELP elsif section == :graphs or section == :plugins puts <<HELP Various graphs are supported in their own Rubygems. Check out pacer-neo4j, pacer-orient, pacer-dex for now. New graphs emerge frequently and I hope to support many of them. Search rubygems.org or github for projects that start with "pacer-" to see what other plugins exist as well. #{general_topics} HELP else if section puts "Unrecognized help section specified" puts elsif not is_a? Graph puts "No specialized help has been defined for this step yet." puts end puts <<HELP How to use Pacer's inline help: You can use Pacer.help(:section) to print help on general topics, or get context-specific help by calling help on any route. For example: graph.v.out_e.map.help # will give you help about the map command. #{general_topics} General options (may not be available for all methods) element_type: Symbol Set what type of element is emitted from this step. registered types: #{ Pacer::RouteBuilder.current.element_types.keys.map(&:inspect).join ', ' } graph: PacerGraph If the route contains graph elements, specify that they are from this graph route_name: String Name for this route when inspecting it in IRB. info: String Put what you want here. Appears when the route is inspected. extensions: [Module] Extra extensions to add to the route. wrapper: Class Wrap elements in this class. For each element, wrapper.new(graph, element) happens HELP end description end |
#inspect(limit = nil) ⇒ String
Returns a string representation of the route definition. If there are less than Graph#inspect_limit matches, it will also output all matching elements formatted in columns up to a maximum character width of Graph#columns. If this output behaviour is undesired, it may be turned off by calling #route on the current route.
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
# File 'lib/pacer/core/route.rb', line 307 def inspect(limit = nil) if Pacer.hide_route_elements or hide_elements or source_iterator.nil? description else graph_read_transaction do Pacer.hide_route_elements do count = 0 limit ||= Pacer.inspect_limit results = collect do |v| count += 1 if count > limit puts "Total: > #{ limit } (Pacer.inspect_limit)" return route.inspect end v.inspect end if count > 0 lens = results.collect { |r| r.length } max = lens.max cols = (Pacer.columns / (max + 1).to_f).floor cols = 1 if cols < 1 if cols == 1 template_part = ['%s'] else template_part = ["%-#{max}s"] end template = (template_part * cols).join(' ') results.each_slice(cols) do |row| template = (template_part * row.count).join(' ') if row.count < cols puts template % row end end puts "Total: #{ count }" description end end end end |
#no_extensions ⇒ Object
379 380 381 |
# File 'lib/pacer/core/route.rb', line 379 def no_extensions chain_route(:extensions => [], :wrapper => nil) end |
#only(included) ⇒ Object
16 17 18 19 20 21 22 |
# File 'lib/pacer/filter/collection_filter.rb', line 16 def only(included) if included.is_a? Symbol chain_route :filter => :collection, :only_var => included else chain_route :filter => :collection, :only => included end end |
#paths(*exts) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 |
# File 'lib/pacer/transform/path.rb', line 4 def paths(*exts) route = chain_route :transform => :path, :element_type => :path if exts.any? exts = exts.map { |e| Array.wrap(e) if e } route.map(element_type: :path) do |path| path.zip(exts).map { |element, ext| ext ? element.add_extensions(ext) : element } end else route end end |
#pipe {|java.util.Iterator| ... } ⇒ java.util.Iterator
Returns a single use pipe iterator based on this route.
143 144 145 146 147 148 149 150 151 152 |
# File 'lib/pacer/core/route.rb', line 143 def pipe iterator = each if block_given? yield iterator if block_given? else iterator end rescue Pacer::EmptyPipe, java.util.NoSuchElementException nil end |
#random(bias = 0.5) ⇒ Object
Return elements based on a bias:1 chance.
If given an integer (n) > 0, bias is calcualated at 1 / n.
7 8 9 10 |
# File 'lib/pacer/filter/random_filter.rb', line 7 def random(bias = 0.5) bias = 1 / bias.to_f if bias.is_a? Fixnum and bias > 0 chain_route :pipe_class => Pacer::Pipes::RandomFilterPipe, :pipe_args => bias end |
#root? ⇒ Boolean
Return true if this route is at the beginning of the route definition.
84 85 86 |
# File 'lib/pacer/core/route.rb', line 84 def root? !@pacer_source.nil? or @back.nil? end |
#route ⇒ self
rename this method
Prevents the route from being evaluated when it is inspected. Useful for computationally expensive or one-time routes.
94 95 96 97 |
# File 'lib/pacer/core/route.rb', line 94 def route @hide_elements = true self end |
#scatter(args = {}) ⇒ Object
4 5 6 |
# File 'lib/pacer/transform/scatter.rb', line 4 def scatter(args = {}) chain_route({transform: :scatter, element_type: :object}.merge(args)) end |
#set_extensions(exts) ⇒ Object
375 376 377 |
# File 'lib/pacer/core/route.rb', line 375 def set_extensions(exts) chain_route extensions: exts, wrapper: nil end |
#set_pipe_source(src) ⇒ Object
all routes derived from any route in the chain will be affected so use with caution.
Change the source of this route.
408 409 410 411 412 413 414 |
# File 'lib/pacer/core/route.rb', line 408 def set_pipe_source(src) if @back @back.set_pipe_source src else self.pacer_source = src end end |
#set_wrapper(wrapper) ⇒ Object
364 365 366 |
# File 'lib/pacer/core/route.rb', line 364 def set_wrapper(wrapper) chain_route wrapper: wrapper end |
#vars ⇒ Hash
It would maybe be better if the vars were tied to the thread context or preferably to the actual pipe instance in use. The current implementation of vars is not threadsafe if the same route is being used in multiple threads concurrently.
Returns the hash of variables used during the previous evaluation of the route.
The contents of vars is expected to be in a state relevant to the latest route being evaluated and is primarily meant for internal use, but YMMV.
112 113 114 115 116 117 118 |
# File 'lib/pacer/core/route.rb', line 112 def vars if @back @back.vars else @vars ||= {} end end |