geoff 0.0.2.beta → 0.0.3.beta

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.
data/.gitignore CHANGED
@@ -16,3 +16,7 @@ tmp
16
16
  .yardoc
17
17
  _yardoc
18
18
  doc/
19
+ *.swp
20
+ *.swo
21
+ lib/jars
22
+ .DS_Store
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use jruby
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- geoff (0.2.4.beta)
4
+ geoff (0.0.3.beta)
5
5
  activesupport (~> 3.2.3)
6
6
  json
7
7
  neo4j
@@ -9,20 +9,20 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- actionpack (3.2.6)
13
- activemodel (= 3.2.6)
14
- activesupport (= 3.2.6)
12
+ actionpack (3.2.8)
13
+ activemodel (= 3.2.8)
14
+ activesupport (= 3.2.8)
15
15
  builder (~> 3.0.0)
16
16
  erubis (~> 2.7.0)
17
- journey (~> 1.0.1)
17
+ journey (~> 1.0.4)
18
18
  rack (~> 1.4.0)
19
19
  rack-cache (~> 1.2)
20
20
  rack-test (~> 0.6.1)
21
21
  sprockets (~> 2.1.3)
22
- activemodel (3.2.6)
23
- activesupport (= 3.2.6)
22
+ activemodel (3.2.8)
23
+ activesupport (= 3.2.8)
24
24
  builder (~> 3.0.0)
25
- activesupport (3.2.6)
25
+ activesupport (3.2.8)
26
26
  i18n (~> 0.6)
27
27
  multi_json (~> 1.0)
28
28
  builder (3.0.0)
@@ -48,7 +48,7 @@ GEM
48
48
  neo4j-community (>= 1.7.0)
49
49
  neo4j-wrapper (2.0.1-java)
50
50
  neo4j-core (= 2.0.1)
51
- orm_adapter (0.3.0)
51
+ orm_adapter (0.4.0)
52
52
  pry (0.9.10)
53
53
  coderay (~> 1.0.5)
54
54
  method_source (~> 0.8)
@@ -65,9 +65,9 @@ GEM
65
65
  rack
66
66
  rack-test (0.6.1)
67
67
  rack (>= 1.0)
68
- railties (3.2.6)
69
- actionpack (= 3.2.6)
70
- activesupport (= 3.2.6)
68
+ railties (3.2.8)
69
+ actionpack (= 3.2.8)
70
+ activesupport (= 3.2.8)
71
71
  rack-ssl (~> 1.3.2)
72
72
  rake (>= 0.8.7)
73
73
  rdoc (~> 3.4)
data/README.md CHANGED
@@ -1,18 +1,39 @@
1
1
  geoff
2
2
  =====
3
3
 
4
- Ruby Geoff DSL
4
+ Geoff is "a declarative notation for representing graph data within concise
5
+ human-readable text, designed specifically with Neo4j in mind"
5
6
 
7
+ http://geoff.nigelsmall.net/
6
8
 
7
- Preview
8
- =======
9
+
10
+ This gem is a Ruby DSL for
11
+ * generating geoff syntax files
12
+ * batch inserting data into Neo4j
13
+
14
+ The reason for creating this gem is to:
15
+ * easily build data sets for tests
16
+ * that are readable and maintainable
17
+ * quickly batch insert the whole data set in one transaction
18
+
19
+ Prerequesites/ Caveats
20
+ ---------------------
21
+ * A ruby project
22
+ * Gemfile with `gem 'geoff', '0.0.2.beta'`
23
+ * neo4j jar and geoff jar files in lib/jars (not included, but required!)
24
+ * Current implementation assumes usage of the neo4j wrapper gem
25
+ * Neo4j::Rails::Model classes or a class that includes the Neo4j::NodeMixin
26
+
27
+ Usage
28
+ -------
9
29
 
10
30
 
11
31
  ```ruby
12
32
 
13
33
  #Basic tree like structure for DSL
14
34
  #the first line generates the class nodes used by Neo4jWrapper
15
- Geoff(Company, Person) do
35
+
36
+ Geoff(Company, Person) do # NB 'Company' and 'Person' are classes with the Neo4j::NodeMixin
16
37
  company 'Acme' do
17
38
  address "13 Something Road"
18
39
 
@@ -38,6 +59,31 @@ end
38
59
 
39
60
  ```
40
61
 
62
+
63
+ ###Using a ramdisk see http://neo4j.rubyforge.org/guides/configuration.html
64
+
65
+ ```sh
66
+ diskutil erasevolume HFS+ "ramdisk" `hdiutil attach -nomount ram://1165430`
67
+ ```
68
+
69
+ ```ruby
70
+
71
+ #in spec helper
72
+ Neo4j::Config[:storage_path] = '/Volumes/ramdisk'
73
+
74
+ #in rspec
75
+ before do
76
+ geoff = Geoff(Company) do
77
+ company 'Acme' do
78
+ address "13 Something Road"
79
+ end
80
+ end
81
+
82
+ #Don't display output, and delete existing database
83
+ Geoff::Importer.import geoff, silent: false, delete: true
84
+ end
85
+
86
+
41
87
  ```
42
88
  (ROOT)-[:Company]->(Company)
43
89
  (ROOT)-[:Person]->(Person)
@@ -122,7 +168,7 @@ end
122
168
  ```
123
169
 
124
170
 
125
- #Using the outer bindings scope
171
+ #Using the outer scope
126
172
  ```ruby
127
173
  @hours = SomeFancyAttributeParser.parse <<-EOF
128
174
  Monday 09:00-15:00
@@ -131,7 +177,7 @@ Saturday 09:00-16:00
131
177
  Sunday closed
132
178
  EOF
133
179
 
134
- Geoff(Company, binding: binding) do
180
+ Geoff(Company, target: self) do
135
181
  company 'Amazon' do
136
182
  opening_hours ->{ @hours }
137
183
  end
data/lib/geoff.rb CHANGED
@@ -10,3 +10,4 @@ end
10
10
 
11
11
  class Geoff::Error < StandardError; end
12
12
  class Geoff::MissingNodeDefinition < Geoff::Error ; end
13
+ class Geoff::DslSyntaxError < Geoff::Error; end
@@ -1,19 +1,23 @@
1
1
  require 'geoff/node_dsl'
2
2
  require 'geoff/container'
3
+ require 'geoff/dsl_exception_handling'
3
4
  require 'active_support/core_ext/string'
4
5
 
5
6
  class ChildrenDsl
7
+ include DslExceptionHandling
8
+
6
9
  def initialize options, &block
7
10
  @parent_node_name = options[:parent_node_name]
8
11
  @parent_rel_type = options[:type]
9
- @outer_binding = options[:binding]
12
+ @target = options[:target]
10
13
  @outer_geoff = options[:geoff]
11
14
 
12
15
  @write_mode = false
13
16
 
14
17
  @node_dsls = {}
15
18
  @container = options[:container] || Container.new
16
- write_mode { instance_eval(&block) }
19
+
20
+ eval_with_exceptions(&block)
17
21
  end
18
22
 
19
23
  def to_geoff
@@ -51,14 +55,6 @@ class ChildrenDsl
51
55
 
52
56
  private
53
57
 
54
- #prevent very confusing method_missing calls during debugging by
55
- #only writing to the object when expected
56
- def write_mode
57
- @write_mode = true
58
- yield
59
- @write_mode = false
60
- end
61
-
62
58
  # e.g.
63
59
  #company "ACME" do
64
60
  # children "works_at" do
@@ -72,7 +68,7 @@ class ChildrenDsl
72
68
  return super unless @write_mode
73
69
  relationship, options = parse_method_missing m, *args
74
70
 
75
- options.merge!(binding: @outer_binding)
71
+ options.merge!(target: @target)
76
72
  NodeDsl.new(options, &blk).tap do |n|
77
73
  @node_dsls[n] = relationship
78
74
  end
@@ -0,0 +1,52 @@
1
+ module DslExceptionHandling
2
+ #prevent very confusing method_missing calls during debugging by
3
+ #only writing to the object when expected
4
+ def write_mode
5
+ @write_mode = true
6
+ yield
7
+ @write_mode = false
8
+ end
9
+
10
+ def eval_with_exceptions &block
11
+ write_mode do
12
+ begin
13
+ instance_eval(&block)
14
+
15
+ rescue Exception => e
16
+ #don't swallow exceptions further down the tree
17
+ raise e if e.is_a? Geoff::DslSyntaxError
18
+
19
+ lines = caller.select{|c| (c !~ /geoff\/lib\/geoff/)and (c !~ /ruby-debug/) }
20
+
21
+ file, number, method = lines.first.split ":"
22
+ message = "Syntax Error in #{method} in Geoff DSL block for:\n#{file}:#{number}\n"
23
+
24
+ message << lines_around(file, number) do |m|
25
+ "\n\n#{e.message}\n\n"
26
+ end
27
+
28
+ raise Geoff::DslSyntaxError, message
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ def lines_around file, number, context = 10
35
+ number = number.to_i
36
+ range = (number - context) .. (number + context)
37
+ lines = File.read(file).split("\n")
38
+
39
+ filtered_lines = range.inject({}) do |l, i|
40
+ l[i] = lines[i]
41
+ l
42
+ end
43
+
44
+ filtered_lines.map do |line_number, line|
45
+ if line_number == number
46
+ yield + ">#{line_number} #{line}"
47
+ else
48
+ " #{line_number} #{line}"
49
+ end
50
+ end.join "\n"
51
+ end
52
+ end
@@ -3,12 +3,19 @@ require 'fileutils'
3
3
  Dir["lib/jars/*"].each {|file| require file }
4
4
 
5
5
  module Geoff
6
- class MissingIndexedProperty < StandardError; end
6
+ class Error < StandardError ; end
7
+ class MissingIndexedProperty < Geoff::Error ; end
8
+ class InvalidRules < Geoff::Error ; end
9
+
10
+ def self.import *args
11
+ Importer.import *args
12
+ end
7
13
 
8
14
  class Importer
9
- class << self
15
+ Subgraph = org.neo4j.geoff.Subgraph
10
16
 
11
- def import_files *files, options
17
+ class << self
18
+ def import_files(*files, options)
12
19
  concatenated = files.map{|f|File.read f}.join "\n"
13
20
 
14
21
  import concatenated, options
@@ -20,10 +27,6 @@ module Geoff
20
27
  end
21
28
 
22
29
  def import(geoff, options = {})
23
- db_path = options[:test] ? 'db/test' : 'db/development'
24
-
25
- Neo4j::Config[:storage_path] = db_path
26
-
27
30
  geoff = geoff.to_geoff unless geoff.is_a? String
28
31
 
29
32
  geoff = geoff.split "\n" if geoff.is_a? String
@@ -39,7 +42,7 @@ module Geoff
39
42
  end
40
43
 
41
44
  def go
42
- raise 'Invalid rules' unless validate_rules(@rules)
45
+ raise Geoff::InvalidRules.new('Invalid rules') unless validate_rules(@rules)
43
46
  delete_database if drop?
44
47
 
45
48
  log 'importing the database'
@@ -68,7 +71,7 @@ module Geoff
68
71
  end
69
72
 
70
73
  def import_geoff_rules(rules)
71
- sub_graph = org.neo4j.geoff.Subgraph.new(rules)
74
+ sub_graph = Subgraph.new(rules)
72
75
  node_map = { '0' => root_node }
73
76
  org.neo4j.geoff.Geoff.insertIntoNeo4j(sub_graph, Neo4j.db.graph, node_map );
74
77
  end
@@ -101,12 +104,12 @@ module Geoff
101
104
 
102
105
  rescue NativeException => e
103
106
  log "-" * 80
104
- message = "Exception during re-indexing #{type} with #{@current_node} and index #{@current_index}"
107
+ message = "#{type} missing indexed attribute #{@current_index}, on node: #{@current_node.attributes}"
105
108
  log message
106
109
  log "-" * 80
107
110
  log e.message
108
111
  log "-" * 80
109
- #raise Geoff::MissingIndexedProperty, message
112
+ raise Geoff::MissingIndexedProperty, message
110
113
  end
111
114
 
112
115
  def tx
@@ -138,16 +141,19 @@ module Geoff
138
141
  end
139
142
 
140
143
  def validate_rules(rules)
141
- invalid = Array(rules).reject{ |r| validate_rule(r) }
142
- invalid.each { |r| log "Rule '#{r}' is invalid" }
143
- invalid.empty?
144
+ @invalid = Array(rules).map do |r|
145
+ validate_rule(r)
146
+ end.compact
147
+
148
+ @invalid.each { |r, message| log "Rule '#{r}' is invalid: #{message}" }
149
+ @invalid.empty?
144
150
  end
145
151
 
146
152
  def validate_rule(rule)
147
- org.neo4j.geoff.Subgraph.new(Array(rule))
148
- true
149
- rescue
150
- false
153
+ Subgraph.new(Array(rule))
154
+ nil
155
+ rescue Exception => e
156
+ return [rule, e.message]
151
157
  end
152
158
 
153
159
  end
@@ -21,6 +21,10 @@ class Neo4jWrapperDsl
21
21
  geoff.chomp
22
22
  end
23
23
 
24
+ def <=> other
25
+ to_geoff == other.to_geoff ? 0 : -1
26
+ end
27
+
24
28
  def to_s
25
29
  to_geoff
26
30
  end
@@ -1,6 +1,9 @@
1
1
  require 'geoff/children_dsl'
2
+ require 'geoff/dsl_exception_handling'
2
3
 
3
4
  class NodeDsl
5
+ include DslExceptionHandling
6
+
4
7
  attr_reader :node_name
5
8
 
6
9
  def initialize(options, &block)
@@ -8,19 +11,20 @@ class NodeDsl
8
11
  @klass_name = options[:klass_name] || 'ROOT'
9
12
  @container = options[:container] || Container.new
10
13
  @rel_type = options[:rel_type]
11
- @outer_binding = options[:binding]
14
+ @target = options[:target]
12
15
  @properties = {}
13
16
  @children_dsls = []
14
17
 
15
18
  @rendered = false
16
19
 
17
- write_mode { instance_eval(&block) } if block_given?
20
+ eval_with_exceptions(&block) if block_given?
18
21
  end
19
22
 
20
23
  def to_geoff
21
24
  geoff_lines.join "\n"
22
25
  end
23
26
 
27
+
24
28
  def geoff_lines
25
29
  #we need this to prevent rendering same node which is rendered already
26
30
  return [] if @rendered
@@ -59,14 +63,6 @@ class NodeDsl
59
63
  end
60
64
  end
61
65
 
62
- #prevent very confusing method_missing calls during debugging by
63
- #only writing to the object when expected
64
- def write_mode
65
- @write_mode = true
66
- yield
67
- @write_mode = false
68
- end
69
-
70
66
  # e.g.
71
67
  #sandwich "BLT", type: :on_menu do
72
68
  # filling 'bacon'
@@ -80,7 +76,7 @@ class NodeDsl
80
76
  else
81
77
  return super unless @write_mode
82
78
  val = if args.first.is_a? Proc
83
- eval("@#{m}", @outer_binding)
79
+ @target.instance_exec &args.first
84
80
  else
85
81
  args.first
86
82
  end
@@ -94,13 +90,13 @@ class NodeDsl
94
90
 
95
91
  private
96
92
 
97
- def children type=nil, &block
98
- options = {
93
+ def children type=nil, options={}, &block
94
+ options.merge!({
99
95
  parent_node_name: @node_name,
100
96
  type: type,
101
97
  container: @container,
102
- binding: @outer_binding
103
- }
98
+ target: @target
99
+ })
104
100
 
105
101
  @children_dsls << ChildrenDsl.new(options, &block)
106
102
  end
data/lib/geoff/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Geoff
2
- VERSION = "0.0.2.beta"
2
+ VERSION = "0.0.3.beta"
3
3
  end
@@ -38,9 +38,9 @@ describe ChildrenDsl do
38
38
  let(:top) {ChildrenDsl.new(parent_node_name: 'starbucks', type: :x ){area 'Luton' } }
39
39
  let(:on_node){ChildrenDsl.new(parent_node_name: 'starbucks') {area 'Luton', type: :x }}
40
40
 
41
- specify { ->{missing }.should raise_error ArgumentError}
42
- specify { ->{ top }.should_not raise_error ArgumentError }
43
- specify { ->{ on_node}.should_not raise_error ArgumentError }
41
+ specify { ->{missing }.should raise_error Geoff::DslSyntaxError}
42
+ specify { ->{ top }.should_not raise_error }
43
+ specify { ->{ on_node}.should_not raise_error }
44
44
  end
45
45
 
46
46
  describe 'with special node' do
@@ -58,20 +58,20 @@ describe NodeDsl do
58
58
  strip_whitespace <<-EOS
59
59
  (starbucks) {"_classname":"Cafe"}
60
60
  (Cafe)-[:all]->(starbucks)
61
- (starbucks_branch_1) {"_classname":"Branch","delay_time":15,"hours":"3"}
61
+ (starbucks_branch_1) {"_classname":"Branch","delay_time":15,"opening_hours":3}
62
62
  (Branch)-[:all]->(starbucks_branch_1)
63
63
  (starbucks)-[:owns]->(starbucks_branch_1) {"some":"property"}
64
64
  EOS
65
65
  end
66
66
 
67
67
  specify do
68
- @hours = "3"
68
+ @hours = 3
69
69
 
70
- node = NodeDsl.new(node_name: 'starbucks', klass_name: 'Cafe', binding: binding) do
70
+ node = NodeDsl.new(node_name: 'starbucks', klass_name: 'Cafe', target: self) do
71
71
  children do
72
72
  branch 'starbucks_branch_1', type: 'owns', some: 'property' do
73
73
  delay_time 15
74
- hours ->{@hours}
74
+ opening_hours ->{@hours}
75
75
  end
76
76
  end
77
77
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: geoff
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 6
5
- version: 0.0.2.beta
5
+ version: 0.0.3.beta
6
6
  platform: ruby
7
7
  authors:
8
8
  - David Rouchy
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2012-08-10 00:00:00.000000000 Z
16
+ date: 2012-08-15 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: neo4j
@@ -123,6 +123,7 @@ extensions: []
123
123
  extra_rdoc_files: []
124
124
  files:
125
125
  - .gitignore
126
+ - .rvmrc
126
127
  - Gemfile
127
128
  - Gemfile.lock
128
129
  - LICENSE
@@ -132,6 +133,7 @@ files:
132
133
  - lib/geoff.rb
133
134
  - lib/geoff/children_dsl.rb
134
135
  - lib/geoff/container.rb
136
+ - lib/geoff/dsl_exception_handling.rb
135
137
  - lib/geoff/importer.rb
136
138
  - lib/geoff/neo4j_wrapper_dsl.rb
137
139
  - lib/geoff/neo4j_wrapper_validator.rb