active_node 2.0.4 → 2.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: caa007d44ee08eba702076849cea0c799428c3b6
4
- data.tar.gz: a5df8569e661a75c6291db2dc3803df0bcfe2f51
3
+ metadata.gz: 2b740f77651e77a06827ae6f01ab6a6592c3f8ad
4
+ data.tar.gz: 03ecfa69835cae01a75c82fb869d263020fbc5d9
5
5
  SHA512:
6
- metadata.gz: 24731c0ae1f393568ac28a1c06f924105e530dcf60d82b96b56dedbab10016bd02e6c067bea482633283acb9415e5e601007e85855432fcf3a999d526c75143c
7
- data.tar.gz: b3060005f8751aa730546ddf3ec72e1168b8400b8ce8eb7c72f7bc4a6ae591cc60e148ffaff508a37af58fe817d5a6ae5f581ebb2072c836082a9ec684a778b3
6
+ metadata.gz: 189c5d2da767a7ea045aa5973bfac329177863280490f30d8e380255c4afed57f763726845a878778f6c742931d6d0f26945d763467dd82eda5d66208608332b
7
+ data.tar.gz: 74300a45a8374d76f946cc77fd0f59dd606aa5b2c437053d40813bf0f6475eee9cf84a5eaf38d3eb22a43a23aea6f4f5aa04de9d91414877853cb0381a6da9cb
data/.travis.yml CHANGED
@@ -1,4 +1,4 @@
1
- script: "bundle exec rake neo4j:install['enterprise','2.0.1'] neo4j:start spec --trace"
1
+ script: "CODECLIMATE_REPO_TOKEN=88fa9b8eb0bfc48e8c5077253d829e94af9f76aca60df9e75ae0e50a4c7cd9f0 bundle exec rake neo4j:install['enterprise','2.0.2'] neo4j:start spec --trace"
2
2
  language: ruby
3
3
  rvm:
4
- - 1.9.3
4
+ - 2.0.0
data/README.md CHANGED
@@ -1,73 +1,107 @@
1
- active_node
2
- ===========
1
+ ActiveNode
2
+ ==========
3
3
 
4
- ActiveRecord style Object Graph Mapping for neo4j
4
+ - [![Gem Version](https://badge.fury.io/rb/active_node.png)](https://rubygems.org/gems/active_node)
5
+ - [![Build Status](https://travis-ci.org/klobuczek/active_node.png?branch=master)](https://travis-ci.org/klobuczek/active_node)
6
+ - [![Code Climate](https://codeclimate.com/github/klobuczek/active_node.png)](https://codeclimate.com/github/klobuczek/active_node)
7
+ - [![Coverage Status](https://coveralls.io/repos/klobuczek/active_node/badge.png?branch=master)](https://coveralls.io/r/klobuczek/active_node?branch=master)
5
8
 
6
9
 
7
- gem install active_node
10
+ ActiveNode is object graph mapping layer for neo4j deployed as standalone server. It is implemented on top of [neography](http://github.com/maxdemarzi/neography) by Max De Marzi.
8
11
 
12
+ If you use neo4j in embedded mode with JRuby please refer to the Neo4j.rb gem at https://github.com/andreasronge/neo4j by Andreas Ronge.
13
+
14
+ ## Installation
15
+
16
+ ### Gemfile
17
+
18
+ Add `active_node` to your Gemfile:
9
19
 
10
20
  ```ruby
11
- require 'rubygems'
12
- require 'active_node'
13
- require 'neography'
14
-
15
- Neography.configure do |config|
16
- config.protocol = "http://"
17
- config.server = "localhost"
18
- config.port = 7474
19
- config.directory = "" # prefix this path with '/'
20
- config.cypher_path = "/cypher"
21
- config.gremlin_path = "/ext/GremlinPlugin/graphdb/execute_script"
22
- config.log_file = "neography.log"
23
- config.log_enabled = false
24
- config.slow_log_threshold = 0 # time in ms for query logging
25
- config.max_threads = 20
26
- config.authentication = nil # 'basic' or 'digest'
27
- config.username = nil
28
- config.password = nil
29
- config.parser = MultiJsonParser
30
- end
21
+ gem 'active_node'
22
+ ```
31
23
 
32
- class NeoUser < ActiveNode::Base
33
- attribute :name, type: String
34
- has_many :clients
35
- validates :name, presence: true
24
+ In case of default neo4j installation no further configuration is required. Otherwise refer to https://github.com/maxdemarzi/neography for further configuration options.
36
25
 
37
- def self.label
38
- 'User'
39
- end
40
- end
26
+ ## Usage
41
27
 
42
- class Client < ActiveNode::Base
43
- attribute :name, type: String
28
+ ActiveNode is inspired by ActiveRecord, but it implements only some of its features and if necessary provides some extensions to work with a graph database.
44
29
 
45
- has_many :users, direction: :incoming, class_name: 'NeoUser'
46
- has_one :address
30
+ ### Creating and Retrieving Nodes
47
31
 
48
- validates :name, presence: true
32
+ ```ruby
33
+ class Client < ActiveNode::Base
49
34
  end
50
35
 
51
- class Address < ActiveNode::Base
52
- end
36
+ client = Client.create! name: 'Abc' # Creates a neo4j node with label Client and property 'name' == 'Abc'
37
+ client = Client.find client.id
38
+ client[:name] # 'Abc'
39
+ client[:name] = 'Abc Inc.'
40
+ client.save
53
41
 
54
- class Person < ActiveNode::Base
55
- attribute :name, type: String
56
- attribute :multi
57
- timestamps
42
+ Client.all # returns array of all clients
43
+ Client.find_by_cypher('match (c:Client) where c.name = {name}', name: 'Abc') # array of all Clients meeting given criteria
44
+ ```
58
45
 
59
- has_many :people
60
- has_many :children, class_name: "Person"
61
- #has_many :sons, class_name: "Person"
62
- has_one :father, type: :child, direction: :incoming, class_name: "Person"
63
- has_one :address
46
+ ### Declared Attrribues
64
47
 
65
- validates :name, uniqueness: true
48
+ ```ruby
49
+ class Client < ActiveNode::Base
50
+ attribute :name, type: String #typed
51
+ attribute :code #untyped
52
+ attribute :keywords # leave array attributes untyped
53
+ timestamps # will automatically add and maintain created_at and updated_at
66
54
  end
67
55
 
56
+ client.name = 'Abc'
57
+ client.keywords = ['finance', 'investment']
68
58
 
69
- user = NeoUser.new(name: 'Heinrich')
70
- user.save
71
- client = Client.new(name: 'a', users: [user])
72
- client.save
73
59
  ```
60
+
61
+ ### Validation
62
+ Validation is similar to ActiveModel e.g.
63
+
64
+ ```ruby
65
+ validates :name, presence: true
66
+ ```
67
+
68
+ ### Association
69
+
70
+ There are 2 types of associations: has_many and has_one. With additional options they can cover all possible relationships between nodes.
71
+
72
+ ```ruby
73
+ # label, class name, relationship type are derived from the association name, direction is by default outgoing
74
+ has_one :user # node with label User connected with outgoing relationship of type 'user'
75
+ has_many :users # multiple nodes with label User connected with outgoing relationship of type 'user'
76
+ # all option customized
77
+ has_one :father, type: :child, direction: :incoming, class_name: "Person"
78
+ ```
79
+
80
+ The association declarations generate readers and writers.
81
+ ```ruby
82
+ Client.create!(name: 'Abc', users: [User.create!, User.create!])
83
+ Client.create!(name: 'Abc', user_id: User.create!.id)
84
+ ...
85
+ client.user_ids = [user1.id, user2.id]
86
+ save
87
+ client.users # [user1, user2]
88
+ ```
89
+ ### Custom Label
90
+
91
+ ```ruby
92
+ class Client < ActiveNode::Base
93
+ def label
94
+ 'Company'
95
+ end
96
+ end
97
+ ```
98
+
99
+ Instances of Client will correspond to nodes with label Company.
100
+
101
+ ## More
102
+
103
+ ActiveNode works nicely with [neography](http://github.com/maxdemarzi/neography). If at any point you need more control or want to leverage some advanced features of the neo4j REST API you can easily take advantage of the lower layer calls.
104
+
105
+ Please create a [new issue](https://github.com/klobuczek/active_node/issues) if you are missing any important feature in active_node.
106
+
107
+ In case of any questions don't hesitate to contact me at heinrich@mail.com
data/active_node.gemspec CHANGED
@@ -26,5 +26,5 @@ Gem::Specification.new do |s|
26
26
  s.add_development_dependency "net-http-spy", "0.2.1"
27
27
  s.add_development_dependency "rake", ">= 0.8.7"
28
28
  s.add_development_dependency "coveralls"
29
-
29
+ s.add_development_dependency "codeclimate-test-reporter"
30
30
  end
data/lib/active_node.rb CHANGED
@@ -11,6 +11,7 @@ module ActiveNode
11
11
  autoload :VERSION
12
12
  autoload :Neo
13
13
  autoload :Relationship
14
+ autoload :Graph
14
15
 
15
16
  eager_autoload do
16
17
  autoload :ActiveNodeError, 'active_node/errors'
@@ -17,7 +17,7 @@ module ActiveNode
17
17
  # HasManyAssociation
18
18
  # HasManyThroughAssociation + ThroughAssociation
19
19
  class Association #:nodoc:
20
- attr_reader :owner, :target, :reflection
20
+ attr_reader :owner, :target, :rel_target, :reflection
21
21
 
22
22
  delegate :options, :to => :reflection
23
23
 
@@ -51,6 +51,7 @@ module ActiveNode
51
51
  @rel_target = nil
52
52
  @target = records
53
53
  end
54
+
54
55
  alias :super_writer :writer
55
56
 
56
57
  # Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items
@@ -71,7 +72,8 @@ module ActiveNode
71
72
 
72
73
 
73
74
  def rels_reader(*args)
74
- @rel_target ||= rel(*args)
75
+ rel(*args) unless @rel_target
76
+ @rel_target ||= []
75
77
  end
76
78
 
77
79
  def rels_writer(rels)
@@ -83,7 +85,7 @@ module ActiveNode
83
85
  def save(fresh=false)
84
86
  #return unless @dirty
85
87
  #delete all relations missing in new target
86
- original_rels = fresh ? [] : rel
88
+ original_rels = fresh ? [] : ActiveNode::Graph::Builder.new(owner.class, reflection.name).build(owner.id).first.association(reflection.name).rels_reader
87
89
  original_rels.each do |r|
88
90
  unless ids_reader.include? r.other.id
89
91
  Neo.db.delete_relationship(r.id)
@@ -0,0 +1,7 @@
1
+ module ActiveNode
2
+ module Graph
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :Builder, 'active_node/graph/builder'
6
+ end
7
+ end
@@ -0,0 +1,119 @@
1
+ module ActiveNode
2
+ module Graph
3
+ class Builder
4
+ include Neography::Rest::Helpers
5
+
6
+ attr_reader :reflections, :matches, :klass
7
+
8
+ def initialize klass, *includes
9
+ @klass = klass if klass < ActiveNode::Base
10
+ @matches = []
11
+ @reflections =[]
12
+ @object_cache = {}
13
+ @relationship_cache = {}
14
+ @loaded_assoc_cache = {}
15
+ parse_paths(:n0, klass, includes)
16
+ end
17
+
18
+ def build *objects
19
+ ids = objects.map { |o| o.is_a?(ActiveNode::Base) ? o.id.tap { |id| @object_cache[id]=o } : o }
20
+ parse_results execute(ids.compact)
21
+ @object_cache.slice(*ids).values
22
+ end
23
+
24
+ private
25
+ def query
26
+ @matches.join " "
27
+ end
28
+
29
+ def execute(ids)
30
+ q="start n0=node({ids}) #{query}#{"where n0#{label @klass}" if @klass} return #{list_with_rel(@reflections.size)} order by #{created_at_list(@reflections.size)}"
31
+ Neo.db.execute_query(q, ids: ids)
32
+ end
33
+
34
+ def parse_results results
35
+ results['data'].each do |record|
36
+ wrap(record.first, @klass)
37
+ @reflections.each_with_index do |reflection, index|
38
+ node_rel = record[2*index+1]
39
+ node_rel = node_rel.last if node_rel.is_a? Array
40
+ next unless node_rel
41
+ owner = @object_cache[owner_id node_rel, reflection.direction]
42
+ node = wrap record[2*index + 2], reflection.klass
43
+ rel = reflection.klass.create_rel node_rel, node
44
+ assoc = owner.association(reflection.name)
45
+ assoc.rels_writer((assoc.rel_target || []) << rel) unless previously_loaded?(assoc)
46
+ end
47
+ end
48
+ end
49
+
50
+ def previously_loaded?(assoc)
51
+ @loaded_assoc_cache[assoc] = assoc.rel_target unless @loaded_assoc_cache.key? assoc
52
+ @loaded_assoc_cache[assoc]
53
+ end
54
+
55
+ def wrap(record, klass)
56
+ @object_cache[extract_id record] ||= ActiveNode::Base.wrap(record, klass)
57
+ end
58
+
59
+ def owner_id relationship, direction
60
+ extract_id relationship[direction == :incoming ? 'end' : 'start']
61
+ end
62
+
63
+ def parse_paths as, klass, includes
64
+ if includes.is_a?(Hash)
65
+ includes.each do |key, value|
66
+ if (value.is_a?(String) || value.is_a?(Numeric))
67
+ add_match(as, klass, key, value)
68
+ else
69
+ parse_paths(as, klass, key)
70
+ parse_paths(latest_alias, @reflections.last.klass, value)
71
+ end
72
+ end
73
+ elsif includes.is_a?(Array)
74
+ includes.each { |inc| parse_paths(as, klass, inc) }
75
+ else
76
+ add_match(as, klass, includes)
77
+ end
78
+ end
79
+
80
+ def add_match from, klass, key, multiplicity=nil
81
+ reflection = klass.reflect_on_association(key)
82
+ @reflections << reflection
83
+ matches << match(from, reflection, multiplicity)
84
+ end
85
+
86
+ def latest_alias
87
+ "n#{@reflections.size}"
88
+ end
89
+
90
+ def match(start_var, reflection, multiplicity)
91
+ "optional match (#{start_var})#{'<' if reflection.direction == :incoming}-[r#{@reflections.size}:#{reflection.type}#{multiplicity(multiplicity)}]-#{'>' if reflection.direction == :outgoing}(#{latest_alias}#{label reflection.klass})"
92
+ end
93
+
94
+ def label klass
95
+ ":#{klass.label}" if klass
96
+ end
97
+
98
+ def multiplicity multiplicity
99
+ multiplicity.is_a?(Numeric) ? "*1..#{multiplicity}" : multiplicity
100
+ end
101
+
102
+ def list_with_rel num
103
+ comma_sep_list(num) { |i| [("r#{i}" if i>0), "n#{i}"] }
104
+ end
105
+
106
+ def comma_sep_list num, &block
107
+ (0..num).map(&block).flatten.compact.join(', ')
108
+ end
109
+
110
+ def created_at_list num
111
+ comma_sep_list(num) { |i| "n#{i}.created_at" }
112
+ end
113
+
114
+ def extract_id(id)
115
+ get_id(id).to_i
116
+ end
117
+ end
118
+ end
119
+ end
@@ -16,8 +16,8 @@ module ActiveNode
16
16
  attribute :updated_at, type: String
17
17
  end
18
18
 
19
- def find ids
20
- array = new_instances(Neo.db.get_nodes([ids].flatten))
19
+ def find ids, options={}
20
+ array = ActiveNode::Graph::Builder.new(self, *options[:include]).build(*ids)
21
21
  ids.is_a?(Array) ? array : array.first
22
22
  end
23
23
 
@@ -38,7 +38,11 @@ module ActiveNode
38
38
  end
39
39
 
40
40
  def wrap_rel rel, node, klass
41
- ActiveNode::Relationship.new wrap(node, klass), rel['data'].merge(id: get_id(rel).to_i)
41
+ create_rel rel, wrap(node, klass)
42
+ end
43
+
44
+ def create_rel rel, node
45
+ ActiveNode::Relationship.new node, rel['data'].merge(id: get_id(rel).to_i)
42
46
  end
43
47
 
44
48
  def active_node_class(class_name, default_klass=nil)
@@ -126,50 +130,10 @@ module ActiveNode
126
130
  end
127
131
 
128
132
  def relationships(reflection, *associations)
129
- id ?
130
- Neo.db.execute_query(
131
- "start n=node({id}) match #{match reflection}#{optional_match reflection, associations} return #{list_with_rel reflection.name, *associations} order by #{created_at_list reflection.name, *associations}",
132
- {id: id})['data'].map { |rel_node| self.class.wrap_rel rel_node[0], rel_node[1], reflection.klass } :
133
- []
133
+ ActiveNode::Graph::Builder.new(self.class, reflection.name => associations).build(self)
134
134
  end
135
135
 
136
136
  private
137
- def parse_result klass, result, associations
138
- node_map = {}
139
- result.each do |record|
140
- (node_map[extract_id(record[1])] ||= wrap_rel(record[0], record[1], klass))
141
- end
142
- end
143
-
144
- def extract_id(id)
145
- get_id(id).to_i
146
- end
147
-
148
- def match(reflection, start_var='n')
149
- "(#{start_var})#{'<' if reflection.direction == :incoming}-[#{reflection.name}_rel:#{reflection.type}]-#{'>' if reflection.direction == :outgoing}(#{reflection.name}#{label reflection.klass})"
150
- end
151
-
152
- def optional_match reflection, associations
153
- return if associations.empty?
154
- " optional match " + comma_sep_list(associations.map { |association| match(reflection.klass.reflect_on_association(association), association) })
155
- end
156
-
157
- def label klass
158
- ":#{klass.label}" if klass
159
- end
160
-
161
- def list_with_rel *names
162
- comma_sep_list names.map { |name| ["#{name}_rel", name] }.flatten
163
- end
164
-
165
- def comma_sep_list *items
166
- items.join(', ')
167
- end
168
-
169
- def created_at_list *names
170
- comma_sep_list names.map { |name| "#{name}.created_at" }
171
- end
172
-
173
137
  def split_hash hash, method, split_by
174
138
  hash.try(method) { |k, _| send split_by, k }
175
139
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveNode
2
- VERSION = "2.0.4"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -16,5 +16,5 @@ describe ActiveNode::Base do
16
16
  end
17
17
  end
18
18
 
19
- it_behaves_like "ActiveModel"
19
+ # it_behaves_like "ActiveModel"
20
20
  end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveNode::Graph::Builder do
4
+ describe "#path" do
5
+ it "should parse includes" do
6
+ ActiveNode::Graph::Builder.new(Person, :father).send(:query).should == "optional match (n0)<-[r1:child]-(n1:Person)"
7
+ ActiveNode::Graph::Builder.new(Person, :father, :children).send(:query).should == "optional match (n0)<-[r1:child]-(n1:Person) optional match (n0)-[r2:child]->(n2:Person)"
8
+ ActiveNode::Graph::Builder.new(Person, children: 2).send(:query).should == "optional match (n0)-[r1:child*1..2]->(n1:Person)"
9
+ ActiveNode::Graph::Builder.new(Person, {children: :address}, :address).send(:query).should == "optional match (n0)-[r1:child]->(n1:Person) optional match (n1)-[r2:address]->(n2:Address) optional match (n0)-[r3:address]->(n3:Address)"
10
+ ActiveNode::Graph::Builder.new(Person, children: [:address, :father]).send(:query).should == "optional match (n0)-[r1:child]->(n1:Person) optional match (n1)-[r2:address]->(n2:Address) optional match (n1)<-[r3:child]-(n3:Person)"
11
+ ActiveNode::Graph::Builder.new(Person, {children: 2} => [:address, :father]).send(:query).should == "optional match (n0)-[r1:child*1..2]->(n1:Person) optional match (n1)-[r2:address]->(n2:Address) optional match (n1)<-[r3:child]-(n3:Person)"
12
+ ActiveNode::Graph::Builder.new(Person, {children: '*'} => [:address, :father]).send(:query).should == "optional match (n0)-[r1:child*]->(n1:Person) optional match (n1)-[r2:address]->(n2:Address) optional match (n1)<-[r3:child]-(n3:Person)"
13
+ end
14
+
15
+ it "should build graph" do
16
+ person = Person.create! children: [c1=Person.create!, c2=Person.create!(address: a=Address.create!)]
17
+ g_person = ActiveNode::Graph::Builder.new(Person, {children: '*'} => [:address, :father]).build(person).first
18
+ g_person.should == person
19
+ g_person.object_id.should == person.object_id
20
+ ActiveNode::Neo.should_not_receive(:db)
21
+ g_person.children.last.address.should == a
22
+ g_person.children.first.father = person
23
+ g_person.children.should == [c1, c2]
24
+ end
25
+
26
+ it "should not query db twice" do
27
+ pending
28
+ person = Person.create!
29
+ ActiveNode::Graph::Builder.new(Person, :children).build(person)
30
+ ActiveNode::Neo.should_not_receive(:db)
31
+ person.children
32
+ end
33
+ end
34
+ end
@@ -89,9 +89,22 @@ describe ActiveNode::Persistence do
89
89
  person = Person.create!(multi: [1, 2, 3])
90
90
  Person.find(person.id).multi.should == [1, 2, 3]
91
91
  end
92
+ end
93
+
94
+ describe "#find" do
95
+ it 'should find an object by id' do
96
+ person = Person.create!
97
+ Person.find(person.id).should == person
98
+ end
99
+
100
+ it 'should find objects passing multiple ids' do
101
+ person1 = Person.create!
102
+ person2 = Person.create!
103
+ Person.find([person1.id, person2.id]).should == [person1, person2]
104
+ end
92
105
 
93
- it 'should find an object with id of a different model' do
94
- Client.find(Person.create!.id).class.should == Person
106
+ it 'should find an object with id of an unknown model' do
107
+ ActiveNode::Base.find(Person.create!.id).class.should == Person
95
108
  end
96
109
  end
97
110
 
@@ -22,5 +22,11 @@ describe ActiveNode::Validations do
22
22
  person.should be_valid
23
23
  end
24
24
  end
25
+
26
+ it "should validate presence on has_one" do
27
+ House.new.should_not be_valid
28
+ house = House.create! address_id: Address.create!.id
29
+ House.find(house.id).should be_valid
30
+ end
25
31
  end
26
32
  end
@@ -0,0 +1,5 @@
1
+ class House < ActiveNode::Base
2
+ has_one :address
3
+
4
+ validates :address, presence: true
5
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
1
3
  #require 'rubygems'
2
4
  #require 'bundler/setup'
3
5
  require 'active_node'
@@ -41,8 +43,8 @@ RSpec.configure do |c|
41
43
  c.before(:each) do
42
44
  @neo=Neography::Rest.new
43
45
  @neo.execute_query("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r")
44
- @neo.set_node_auto_index_status(true)
45
- @neo.add_node_auto_index_property('type')
46
+ #@neo.set_node_auto_index_status(true)
47
+ #@neo.add_node_auto_index_property('type')
46
48
  end
47
49
  end
48
50
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_node
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Heinrich Klobuczek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-10 00:00:00.000000000 Z
11
+ date: 2014-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_attr
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - '>='
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: codeclimate-test-reporter
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  description: ActiveRecord style Object Graph Mapping for neo4j
126
140
  email:
127
141
  - heinrich@mail.com
@@ -152,6 +166,8 @@ files:
152
166
  - lib/active_node/callbacks.rb
153
167
  - lib/active_node/core.rb
154
168
  - lib/active_node/errors.rb
169
+ - lib/active_node/graph.rb
170
+ - lib/active_node/graph/builder.rb
155
171
  - lib/active_node/neo.rb
156
172
  - lib/active_node/persistence.rb
157
173
  - lib/active_node/reflection.rb
@@ -161,10 +177,12 @@ files:
161
177
  - lib/active_node/version.rb
162
178
  - spec/functional/associations_spec.rb
163
179
  - spec/functional/base_spec.rb
180
+ - spec/functional/graph/builder_spec.rb
164
181
  - spec/functional/persistence_spec.rb
165
182
  - spec/functional/validations_spec.rb
166
183
  - spec/models/address.rb
167
184
  - spec/models/client.rb
185
+ - spec/models/house.rb
168
186
  - spec/models/neo_user.rb
169
187
  - spec/models/person.rb
170
188
  - spec/spec_helper.rb
@@ -195,10 +213,12 @@ summary: ActiveRecord style Object Graph Mapping for neo4j
195
213
  test_files:
196
214
  - spec/functional/associations_spec.rb
197
215
  - spec/functional/base_spec.rb
216
+ - spec/functional/graph/builder_spec.rb
198
217
  - spec/functional/persistence_spec.rb
199
218
  - spec/functional/validations_spec.rb
200
219
  - spec/models/address.rb
201
220
  - spec/models/client.rb
221
+ - spec/models/house.rb
202
222
  - spec/models/neo_user.rb
203
223
  - spec/models/person.rb
204
224
  - spec/spec_helper.rb