active_node 2.0.4 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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