Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Read a WRITEME

  • Loading branch information...
commit 0f8318a4d23bbbf82b4ff0d809e2934f4286408c 1 parent 5744692
Jannis Hermanns jayniz authored
Showing with 151 additions and 20 deletions.
  1. +89 −0 README.markdown
  2. +0 −19 README.rdoc
  3. +1 −1  Rakefile
  4. +61 −0 pacer-jogger.gemspec
89 README.markdown
View
@@ -0,0 +1,89 @@
+# Jogger
+
+Jogger is a JRuby library that enables lazy people to do very expressive graph traversals with the great [pacer gem](https://github.com/pangloss/pacer). If you don't know what the pacer gem is, you should probably not be here and check pacer out first.
+
+# What does it do?
+
+Jogger does two things:
+
+1. Keep the current pacer traversal in an instance variable and allow for method chaining as well as changing the internal state of the traversal
+2. Allows you to group together parts of a traversal (single pipes or groups of them) and give them a name. Named traversals. Helps to stay DRY.
+
+The former is really just a syntax thing, whereas the latter can help you a great deal modeling semantics of your business logic as parts of traversals. These sentences confuse me, so I will give you:
+
+# Example time!
+
+## 1. Keep the current traversal
+
+To demonstrate why point 1) in the list above can be useful, look at this traversal. It helps me find out what movies my female friends like the most, so I can impress them in a conversation:
+
+ t = my_pacer_vertex.in(:friends)
+ t = t.filter{|v| v.properties['gender'] == 'female}
+ t = t.out(:likes)
+ t = t.filter{ |v| v.properties['type'] == 'Movie' }
+ t = t.sort_by{ |v, c| -c }
+ t = t.group_count{ |v| v }
+
+Since I'm a very lazy person, I would prefer to write it a little shorter. Especially, since these multi step traversals are a pattern I found in our code at [moviepilot.com](http://moviepilot.com)) a lot.
+
+So here's the Jogger way of expressing this:
+
+ t = Jogger.new(my_pacer_vertex)
+ t.in(:friends)
+ t.filter{ |v| v.properties['gender'] == 'female' }
+ t.out(:likes)
+ t.filter{ |v| v.properties['type'] == 'Movie' }
+ t.sort_by{ |v, c| -c }
+ t.group_count{ |v| v }
+
+See what I did there? Jogger keeps the current pacer traversal and forwards all method calls to that traversal, and then returns itself. So you could also write (in jogger as well as pacer):
+
+ Jogger.new(my_pacer_node).in(:friends).filter{ … }.out(:likes).group_count{…}
+
+Just saying, you can chain your methods, but I don't like it cause I can only focus on 72 characters per line at max. If you want the current traversal, just call `result` on your Jogger instance.
+
+## 2. Named traversals
+
+So that traversal above, traversing from a node to all its friends, is pretty simple, but it could be simpler. Especially if it does things that you want to reuse in many other places. How cool would it be if I just had to write this:
+
+ t = Jogger.new(my_pacer_vertex)
+ t.friends(:female)
+ t.top_list(:movies)
+
+No problem. Just define a named traversal that does it.
+
+ class Jogger
+ module NamedTraversals
+
+ # Traverse to somebody's woman friends
+ def self.friends(current_traversal, gender)
+ t = current_traversal.in(:friends)
+ t = t.filter{|v| v.properties['gender'] == gender}
+ end
+
+ # Group and sort
+ def self.top_list(current_traversal, type)
+ t = current_traversal.out(type)
+ t = t.filter{ |v| v.properties['type'] == 'Movie' }
+ t = t.group_count{ |v| v }
+ end
+ end
+ end
+
+These are silly examples, but if you look at your traversals I guarantee that you will find repeated patterns all over the place, and Jogger can help you stop repeating these and making the actual traversals much easier on the eyes.
+
+# Installation
+
+First, you need to load pacer and whatever graph db connector you need (we use neo4j, by the way) and define your named traversals as above. Jogger doesn't include these on purpose. Then, you have to
+
+ gem install pacer-jogger
+
+and
+
+ require 'jogger'
+
+or for your Gemfile
+
+ gem "pacer-jogger", :require => "jogger"
+
+That's it!
19 README.rdoc
View
@@ -1,19 +0,0 @@
-= jogger
-
-Description goes here.
-
-== Contributing to jogger
-
-* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
-* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
-* Fork the project.
-* Start a feature/bugfix branch.
-* Commit and push until you are happy with your contribution.
-* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
-* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
-
-== Copyright
-
-Copyright (c) 2012 Jannis Hermanns. See LICENSE.txt for
-further details.
-
2  Rakefile
View
@@ -15,7 +15,7 @@ require 'rspec/core/rake_task'
require 'jeweler'
Jeweler::Tasks.new do |gem|
- gem.name = "jogger"
+ gem.name = "pacer-jogger"
gem.homepage = "http://github.com/jayniz/jogger"
gem.license = "MIT"
gem.summary = %Q{Pacer traversals for lazy people}
61 pacer-jogger.gemspec
View
@@ -0,0 +1,61 @@
+# Generated by jeweler
+# DO NOT EDIT THIS FILE DIRECTLY
+# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = "pacer-jogger"
+ s.version = "0.0.1"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Jannis Hermanns"]
+ s.date = "2012-01-23"
+ s.description = "Allows to group traversal fragments/pipes to named traversals and call them like they were pacer pipes."
+ s.email = "jannis@gmail.com"
+ s.extra_rdoc_files = [
+ "LICENSE.txt",
+ "README.markdown"
+ ]
+ s.files = [
+ ".document",
+ "Gemfile",
+ "Gemfile.lock",
+ "LICENSE.txt",
+ "README.markdown",
+ "Rakefile",
+ "VERSION",
+ "lib/jogger.rb",
+ "spec/lib/jogger_spec.rb",
+ "spec/spec_helper.rb"
+ ]
+ s.homepage = "http://github.com/jayniz/jogger"
+ s.licenses = ["MIT"]
+ s.require_paths = ["lib"]
+ s.rubygems_version = "1.8.10"
+ s.summary = "Pacer traversals for lazy people"
+
+ if s.respond_to? :specification_version then
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
+ s.add_development_dependency(%q<jeweler>, ["~> 1.7.0"])
+ s.add_development_dependency(%q<rspec>, [">= 0"])
+ s.add_development_dependency(%q<yard>, [">= 0"])
+ else
+ s.add_dependency(%q<shoulda>, [">= 0"])
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
+ s.add_dependency(%q<jeweler>, ["~> 1.7.0"])
+ s.add_dependency(%q<rspec>, [">= 0"])
+ s.add_dependency(%q<yard>, [">= 0"])
+ end
+ else
+ s.add_dependency(%q<shoulda>, [">= 0"])
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
+ s.add_dependency(%q<jeweler>, ["~> 1.7.0"])
+ s.add_dependency(%q<rspec>, [">= 0"])
+ s.add_dependency(%q<yard>, [">= 0"])
+ end
+end
+
Please sign in to comment.
Something went wrong with that request. Please try again.