pacer-jogger 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.markdown +30 -18
  2. data/VERSION +1 -1
  3. data/lib/jogger.rb +14 -10
  4. data/pacer-jogger.gemspec +2 -2
  5. metadata +13 -13
@@ -1,56 +1,61 @@
1
- # Jogger
1
+ # Jogger - almost like named scopes
2
2
 
3
3
  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.
4
4
 
5
- # What does it do?
5
+ # What does Jogger do? TL;DR
6
+
7
+ Remember the _named scopes_ from back in the days when you were using rails? They were handy, weren't they? Jogger gives you _named traversals_ and is a little bit like named scopes. Jogger groups multiple pacer traversals together and give them a name. Pacer traversals are are like pipes. What are pipes? [Pipes are great!](http://markorodriguez.com/2011/08/03/on-the-nature-of-pipes/)!
8
+
9
+ The most important conceptual difference is, that the order in which named traversals are called matter, while it usually doesn't matter in which order you call named scopes.
6
10
 
7
11
  Jogger does two things:
8
12
 
9
13
  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
10
14
  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.
11
15
 
12
- 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 examples.
16
+ 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 a TL;DR gif followed by some hands on examples.
13
17
 
14
- # Example time!
18
+ ![TL;DR](http://dl.dropbox.com/u/1953503/gifs/berneydidnotread.gif)
15
19
 
16
- ## 1. Keep track of the current traversal
20
+
21
+ # Feature #1 (not so important): keep the current traversal
17
22
 
18
23
  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:
19
24
 
20
25
  t = my_pacer_vertex.in(:friends)
21
- t = t.filter{ |v| v.properties['gender'] == 'female}
26
+ t = t.filter{|v| v.properties['gender'] == 'female}
22
27
  t = t.out(:likes)
23
28
  t = t.filter{ |v| v.properties['type'] == 'Movie' }
24
- t = t.group_count{ |v| v }
25
29
  t = t.sort_by{ |v, c| -c }
30
+ t = t.group_count{ |v| v }
26
31
 
27
32
  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.
28
33
 
29
- So here's the Jogger way of expressing the same traversal:
34
+ So here's the Jogger way of expressing this:
30
35
 
31
36
  t = Jogger.new(my_pacer_vertex)
32
37
  t.in(:friends)
33
38
  t.filter{ |v| v.properties['gender'] == 'female' }
34
39
  t.out(:likes)
35
40
  t.filter{ |v| v.properties['type'] == 'Movie' }
36
- t.group_count{ |v| v }
37
41
  t.sort_by{ |v, c| -c }
42
+ t.group_count{ |v| v }
38
43
 
39
44
  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):
40
45
 
41
46
  Jogger.new(my_pacer_node).in(:friends).filter{ … }.out(:likes).group_count{…}
42
47
 
43
- Just saying, you can chain your methods, but I don't like it because I can only focus on 72 characters per line at max. If you want to access the current traversal, just call `result` on your Jogger instance.
48
+ 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.
44
49
 
45
- ## 2. Named traversals
50
+ ## Feature #2 (pretty useful): Named Traversals
46
51
 
47
- 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. If you would explain the traveral to somebody, you'd say something along the lines of "The most popular movies amongst my friends, but only girls". How cool would it be if I just had to write this:
52
+ 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:
48
53
 
49
54
  t = Jogger.new(my_pacer_vertex)
50
55
  t.friends(:female)
51
56
  t.top_list(:movies)
52
57
 
53
- No problem. Just define a few named traversals that do exactly this.
58
+ No problem. Just define named traversals that aggregate different pipes and give them a name:
54
59
 
55
60
  class Jogger
56
61
  module NamedTraversals
@@ -60,13 +65,12 @@ No problem. Just define a few named traversals that do exactly this.
60
65
  t = current_traversal.in(:friends)
61
66
  t = t.filter{|v| v.properties['gender'] == gender}
62
67
  end
63
-
68
+
64
69
  # Group and sort
65
70
  def self.top_list(current_traversal, type)
66
71
  t = current_traversal.out(type)
67
72
  t = t.filter{ |v| v.properties['type'] == 'Movie' }
68
73
  t = t.group_count{ |v| v }
69
- t = t.sort_by{ |v, c| -c }
70
74
  end
71
75
  end
72
76
  end
@@ -75,16 +79,24 @@ These are silly examples, but if you look at your traversals I guarantee that yo
75
79
 
76
80
  # Installation
77
81
 
78
- First, you need to load pacer and whatever graph db connector you need (we use pacer-neo4j, by the way) and define your named traversals as above. Jogger doesn't include these on purpose. Then, you have to:
82
+ 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
79
83
 
80
84
  gem install pacer-jogger
81
85
 
82
- and
86
+ and
83
87
 
84
88
  require 'jogger'
85
89
 
86
- or if you're using bundler, add this to your Gemfile and bundle:
90
+ or for your Gemfile
87
91
 
88
92
  gem "pacer-jogger", :require => "jogger"
89
93
 
90
94
  That's it!
95
+
96
+ # Documentation
97
+
98
+ I gave YARD a shot, so to open the documentation in your browser just do this in the jogger directory:
99
+
100
+ yard server & sleep 3 && open http://localhost:8808/docs/file/README.markdown
101
+
102
+ Or you can (browse the documentation online)[http://rubydoc.info/github/jayniz/jogger/master/frames]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -2,21 +2,25 @@
2
2
  # Allows to formulate traversals by using predefined
3
3
  # named traversals. Also allows for method chaining.
4
4
  #
5
- # All named traversals are defined in {PacerTraversal::NamedTraversals}
6
- # and new ones can be added using {Jogger.add_traversal}.
5
+ # All named traversals are defined in {Jogger::NamedTraversals},
6
+ # so that's where you should define your own.
7
7
  #
8
8
  # Instances have a @current_traversal variable that is
9
- # updated with each chained call of {#traverse}.
9
+ # updated with each call. Beware: Jogger uses method missing to
10
+ # delegate unknown methods to the current traversal. So after
11
+ # you're done chaining things, you can do more stuff with it,
12
+ # e.g. call count on it:
10
13
  #
11
- # Beware, it also uses method missing to delegate unknown methods to
12
- # the current traversal. So after you're done chaining things, you can
13
- # do more stuff with it after you're done, e.g. call count on it:
14
+ # t = Jogger.new(some_node)
15
+ # t.go.some.where.count
16
+ #
17
+ # Everything except for {Jogger#result} is called on the
18
+ # `@current_traversal`, so what you really want to do to get the
19
+ # count of your traversal would be
14
20
  #
15
21
  # t = Jogger.new(some_node)
16
- # t.traverse(:some).traverse(:where).count
22
+ # t.go.some.where.result.count
17
23
  #
18
- # So everything except for {#traverse} is called on the
19
- # @current_traversal
20
24
  class Jogger
21
25
 
22
26
 
@@ -40,7 +44,7 @@ class Jogger
40
44
  # This is useful for more traversals after named routes.
41
45
  #
42
46
  # @return [Jogger] Returns itself so you can chain multiple
43
- # {#traverse} calls
47
+ # calls just like you would do with pacer
44
48
  def method_missing(method, *args, &block)
45
49
  begin
46
50
  traversal_args = [method, args].flatten.compact
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "pacer-jogger"
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jannis Hermanns"]
12
- s.date = "2012-01-23"
12
+ s.date = "2012-01-25"
13
13
  s.description = "Allows to group traversal fragments/pipes to named traversals and call them like they were pacer pipes."
14
14
  s.email = "jannis@gmail.com"
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pacer-jogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-23 00:00:00.000000000Z
12
+ date: 2012-01-25 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: shoulda
16
- requirement: &70246624766620 !ruby/object:Gem::Requirement
16
+ requirement: &70106294753680 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70246624766620
24
+ version_requirements: *70106294753680
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70246624765680 !ruby/object:Gem::Requirement
27
+ requirement: &70106294753160 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70246624765680
35
+ version_requirements: *70106294753160
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jeweler
38
- requirement: &70246624765080 !ruby/object:Gem::Requirement
38
+ requirement: &70106294752640 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.7.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70246624765080
46
+ version_requirements: *70106294752640
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
- requirement: &70246624764500 !ruby/object:Gem::Requirement
49
+ requirement: &70106294752040 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70246624764500
57
+ version_requirements: *70106294752040
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: yard
60
- requirement: &70246624763920 !ruby/object:Gem::Requirement
60
+ requirement: &70106294751440 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70246624763920
68
+ version_requirements: *70106294751440
69
69
  description: Allows to group traversal fragments/pipes to named traversals and call
70
70
  them like they were pacer pipes.
71
71
  email: jannis@gmail.com
@@ -101,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
101
  version: '0'
102
102
  segments:
103
103
  - 0
104
- hash: -4043812696808555855
104
+ hash: 3011242392760856399
105
105
  required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements: