active_node 0.2 → 2.0.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 +4 -4
- data/.travis.yml +1 -1
- data/lib/active_node.rb +1 -0
- data/lib/active_node/associations/association.rb +5 -4
- data/lib/active_node/associations/singular_association.rb +2 -2
- data/lib/active_node/base.rb +4 -0
- data/lib/active_node/core.rb +2 -2
- data/lib/active_node/neo.rb +7 -0
- data/lib/active_node/persistence.rb +87 -43
- data/lib/active_node/version.rb +1 -1
- data/spec/functional/associations_spec.rb +20 -0
- data/spec/functional/base_spec.rb +18 -0
- data/spec/functional/persistence_spec.rb +10 -5
- data/spec/models/neo_user.rb +2 -2
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2d31741bd5a8017c8fbc4a49a3494d5d4622e6b0
|
|
4
|
+
data.tar.gz: 4fe415aecee9215b53ab04a5e5f031c94fcca1b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 740435b0a5eceb85a52c8c98a0a2068b26c1e17cfb5dde3341bb6075c9f6717478a811e564c48cf1ae2460f7131bea2ef34c8bf2713b3e5a9eb04fbe28255304
|
|
7
|
+
data.tar.gz: ec10984057ef8c34ccfd19e4a1b83359db40b121e02e5d5b400618c78ff565c6f198b67ce8329c1f9f9a2f673dc6969bbedd82f373f3a69cf7a452cf73c44f1d
|
data/.travis.yml
CHANGED
data/lib/active_node.rb
CHANGED
|
@@ -58,13 +58,14 @@ module ActiveNode
|
|
|
58
58
|
def save
|
|
59
59
|
return unless @dirty
|
|
60
60
|
#delete all relations missing in new target
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
node = Neography::Node.load(owner.id)
|
|
62
|
+
node.rels(reflection.type).send(reflection.direction).each do |rel|
|
|
63
|
+
rel.del unless ids_reader.include? rel.other_node(node).neo_id.to_i
|
|
63
64
|
end
|
|
64
|
-
original_target =
|
|
65
|
+
original_target = node.send(reflection.direction, reflection.type)
|
|
65
66
|
original_target_ids = original_target.map(&:neo_id).map(&:to_i)
|
|
66
67
|
#add relations missing in old target
|
|
67
|
-
target_each { |n| original_target << n.
|
|
68
|
+
target_each { |n| original_target << n.id unless original_target_ids.include? n.id }
|
|
68
69
|
end
|
|
69
70
|
end
|
|
70
71
|
end
|
|
@@ -6,7 +6,7 @@ module ActiveNode
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def target_each
|
|
9
|
-
yield target
|
|
9
|
+
yield target if target.present?
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def ids_reader
|
|
@@ -18,7 +18,7 @@ module ActiveNode
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def id_writer(id)
|
|
21
|
-
writer(klass.find(id.to_i))
|
|
21
|
+
writer(id.blank? ? nil : klass.find(id.to_i))
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
end
|
data/lib/active_node/base.rb
CHANGED
data/lib/active_node/core.rb
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
|
2
|
+
|
|
1
3
|
module ActiveNode
|
|
2
4
|
module Persistence
|
|
3
5
|
extend ActiveSupport::Concern
|
|
6
|
+
include Neography::Rest::Helpers
|
|
4
7
|
|
|
5
8
|
included do
|
|
9
|
+
extend Neography::Rest::Helpers
|
|
6
10
|
attribute :id
|
|
7
11
|
end
|
|
8
12
|
|
|
@@ -13,22 +17,24 @@ module ActiveNode
|
|
|
13
17
|
end
|
|
14
18
|
|
|
15
19
|
def find ids
|
|
16
|
-
|
|
20
|
+
array = new_instances(Neo.db.get_nodes([ids].flatten))
|
|
21
|
+
ids.is_a?(Array) ? array : array.first
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def find_by_cypher query, params={}, klass=nil
|
|
25
|
+
wrap(Neo.db.execute_query(query, params)['data'].map(&:first), klass)
|
|
17
26
|
end
|
|
18
27
|
|
|
19
28
|
def all
|
|
20
|
-
|
|
21
|
-
(result.is_a?(Enumerable) ? result : [result]).map { |node| new_instance(node) }.compact
|
|
29
|
+
new_instances(Neo.db.get_nodes_labeled(label), self)
|
|
22
30
|
end
|
|
23
31
|
|
|
24
|
-
def
|
|
25
|
-
name
|
|
32
|
+
def label
|
|
33
|
+
name
|
|
26
34
|
end
|
|
27
35
|
|
|
28
36
|
def wrap node, klass=nil
|
|
29
|
-
node.is_a?(
|
|
30
|
-
node.map { |n| wrap(n, klass) } :
|
|
31
|
-
node.is_a?(Neography::Node) && (active_node_class(node.type.camelize, klass)).try(:new, node) || node
|
|
37
|
+
node.is_a?(Array) ? new_instances(node, klass) : new_instance(node, klass)
|
|
32
38
|
end
|
|
33
39
|
|
|
34
40
|
def active_node_class(class_name, default_klass=nil)
|
|
@@ -36,32 +42,51 @@ module ActiveNode
|
|
|
36
42
|
klass && klass < ActiveNode::Base && klass || default_klass
|
|
37
43
|
end
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
private
|
|
46
|
+
def new_instance node, klass=nil
|
|
47
|
+
(klass || find_suitable_class(Neo.db.get_node_labels(node))).try(:new, data(node), :declared?)
|
|
41
48
|
end
|
|
42
49
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
def data hash
|
|
51
|
+
hash['data'].merge(id: get_id(hash).to_i)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def new_instances nodes, klass=nil
|
|
55
|
+
nodes.map { |node| new_instance(node, klass) }.compact
|
|
46
56
|
end
|
|
57
|
+
|
|
58
|
+
def find_suitable_class labels
|
|
59
|
+
labels.include?(label) ? self : labels.map { |l| active_node_class(l) }.compact.first
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def [](attr)
|
|
64
|
+
declared?(attr) ? send(attr) : @hash[attr]
|
|
47
65
|
end
|
|
48
66
|
|
|
49
|
-
|
|
50
|
-
|
|
67
|
+
def []=(attr, value)
|
|
68
|
+
if declared? attr
|
|
69
|
+
send "#{attr}=", value
|
|
70
|
+
else
|
|
71
|
+
@hash[attr]=value
|
|
72
|
+
end
|
|
73
|
+
end
|
|
51
74
|
|
|
52
|
-
|
|
75
|
+
def neo_id
|
|
76
|
+
id
|
|
77
|
+
end
|
|
53
78
|
|
|
54
|
-
def
|
|
55
|
-
|
|
79
|
+
def to_param
|
|
80
|
+
id
|
|
56
81
|
end
|
|
57
82
|
|
|
58
|
-
|
|
59
|
-
|
|
83
|
+
def persisted?
|
|
84
|
+
id
|
|
85
|
+
end
|
|
60
86
|
|
|
61
|
-
def initialize
|
|
62
|
-
hash
|
|
63
|
-
@
|
|
64
|
-
super hash
|
|
87
|
+
def initialize hash={}, split_by=:respond_to_writer?
|
|
88
|
+
super(split_hash hash, :select, split_by)
|
|
89
|
+
@hash=(split_hash(hash, :reject, split_by) || {}).with_indifferent_access
|
|
65
90
|
end
|
|
66
91
|
|
|
67
92
|
def new_record?
|
|
@@ -76,7 +101,7 @@ module ActiveNode
|
|
|
76
101
|
|
|
77
102
|
def destroy include_relationships=false
|
|
78
103
|
destroyable = destroy_associations include_relationships
|
|
79
|
-
|
|
104
|
+
Neo.db.delete_node(id) if destroyable
|
|
80
105
|
@destroyed = destroyable
|
|
81
106
|
end
|
|
82
107
|
|
|
@@ -84,32 +109,38 @@ module ActiveNode
|
|
|
84
109
|
destroy true
|
|
85
110
|
end
|
|
86
111
|
|
|
87
|
-
def incoming(
|
|
88
|
-
related(:incoming,
|
|
112
|
+
def incoming(type=nil, klass=nil)
|
|
113
|
+
related(:incoming, type, klass)
|
|
89
114
|
end
|
|
90
115
|
|
|
91
|
-
def outgoing(
|
|
92
|
-
related(:outgoing,
|
|
116
|
+
def outgoing(type=nil, klass=nil)
|
|
117
|
+
related(:outgoing, type, klass)
|
|
93
118
|
end
|
|
94
119
|
|
|
95
120
|
private
|
|
96
|
-
def
|
|
97
|
-
hash.try(
|
|
121
|
+
def split_hash hash, method, split_by
|
|
122
|
+
hash.try(method) { |k, _| send split_by, k }
|
|
98
123
|
end
|
|
99
124
|
|
|
100
|
-
def
|
|
101
|
-
|
|
125
|
+
def declared? attr
|
|
126
|
+
self.class.attribute_names.include? attr.to_s
|
|
102
127
|
end
|
|
103
128
|
|
|
104
|
-
def
|
|
105
|
-
|
|
106
|
-
return false unless rels.empty? || include_associations
|
|
107
|
-
rels.each { |rel| rel.del }
|
|
108
|
-
true
|
|
129
|
+
def respond_to_writer? attr
|
|
130
|
+
respond_to? "#{attr}="
|
|
109
131
|
end
|
|
110
132
|
|
|
111
|
-
def
|
|
112
|
-
|
|
133
|
+
def related(direction, type, klass)
|
|
134
|
+
id ?
|
|
135
|
+
self.class.find_by_cypher(
|
|
136
|
+
"start n=node({id}) match (n)#{'<' if direction == :incoming}-[:#{type}]-#{'>' if direction == :outgoing}(m#{":#{klass.label}" if klass}) return m",
|
|
137
|
+
{id: id}, klass) :
|
|
138
|
+
[]
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def destroy_associations include_associations
|
|
142
|
+
rels=Neo.db.get_node_relationships(id)
|
|
143
|
+
rels.nil? || rels.empty? || include_associations && rels.each { |rel| Neo.db.delete_relationship(rel) }
|
|
113
144
|
end
|
|
114
145
|
|
|
115
146
|
def create_or_update
|
|
@@ -120,12 +151,25 @@ module ActiveNode
|
|
|
120
151
|
def write
|
|
121
152
|
now = Time.now.utc.iso8601(3)
|
|
122
153
|
try :updated_at=, now
|
|
123
|
-
if
|
|
124
|
-
|
|
154
|
+
if persisted?
|
|
155
|
+
write_properties
|
|
125
156
|
else
|
|
126
157
|
try :created_at=, now
|
|
127
|
-
|
|
158
|
+
create_node_with_label
|
|
128
159
|
end
|
|
129
160
|
end
|
|
161
|
+
|
|
162
|
+
def create_node_with_label
|
|
163
|
+
self.id = get_id(Neo.db.create_node(all_attributes)).to_i
|
|
164
|
+
Neo.db.set_label(id, self.class.label)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def write_properties
|
|
168
|
+
Neo.db.reset_node_properties(id, all_attributes.select { |_, v| v.present? })
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def all_attributes
|
|
172
|
+
attributes.merge(@hash)
|
|
173
|
+
end
|
|
130
174
|
end
|
|
131
175
|
end
|
data/lib/active_node/version.rb
CHANGED
|
@@ -104,6 +104,26 @@ describe ActiveNode::Associations do
|
|
|
104
104
|
father.children.should == [child]
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
+
it 'can set has_one relationship by id at creation time' do
|
|
108
|
+
father = Person.create!
|
|
109
|
+
child = Person.create! father_id: father.id
|
|
110
|
+
father.children.should == [child]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'does not set has_one relationship by id if id is blank' do
|
|
114
|
+
father = Person.create!
|
|
115
|
+
child = Person.create! father_id: nil
|
|
116
|
+
father.children.should be_empty
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it 'can remove has_one relationship' do
|
|
120
|
+
father = Person.create!
|
|
121
|
+
child = Person.create! father: father
|
|
122
|
+
child.father = nil
|
|
123
|
+
child.save
|
|
124
|
+
Person.find(child.id).father.should be_nil
|
|
125
|
+
end
|
|
126
|
+
|
|
107
127
|
it 'can read has_one relation by id' do
|
|
108
128
|
father = Person.create!
|
|
109
129
|
child = Person.create!
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveNode::Base do
|
|
4
|
+
describe ".subclass" do
|
|
5
|
+
it "should be ActiveNode::Base" do
|
|
6
|
+
ActiveNode::Base.subclass('Abc').should <= ActiveNode::Base
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should have the right label" do
|
|
10
|
+
ActiveNode::Base.subclass('Abc').label.should == 'Abc'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should find object via subclass" do
|
|
14
|
+
p = Person.create! name: 'Heinrich'
|
|
15
|
+
ActiveNode::Base.subclass('Person').find(p.id)[:name].should == p.name
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -2,6 +2,11 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe ActiveNode::Persistence do
|
|
4
4
|
describe "#save" do
|
|
5
|
+
it "should save an object" do
|
|
6
|
+
a=Address.create!
|
|
7
|
+
Address.find(a.id).should == a
|
|
8
|
+
end
|
|
9
|
+
|
|
5
10
|
it "should save not conventionally named object" do
|
|
6
11
|
NeoUser.new(name: 'Heinrich').save.should be_true
|
|
7
12
|
NeoUser.all.map(&:name).should == ['Heinrich']
|
|
@@ -10,10 +15,10 @@ describe ActiveNode::Persistence do
|
|
|
10
15
|
it "should save object with non attribute properties with a name of a relationship" do
|
|
11
16
|
child = Person.create!
|
|
12
17
|
person = Person.create! children: [child]
|
|
13
|
-
person
|
|
14
|
-
person = Person.find person.id
|
|
18
|
+
person[:children] = "Bob"
|
|
15
19
|
person.save
|
|
16
|
-
person.
|
|
20
|
+
person = Person.find person.id
|
|
21
|
+
person[:children].should == "Bob"
|
|
17
22
|
person.children.should == [child]
|
|
18
23
|
end
|
|
19
24
|
|
|
@@ -64,8 +69,8 @@ describe ActiveNode::Persistence do
|
|
|
64
69
|
Person.find(person.id).multi.should == [1, 2, 3]
|
|
65
70
|
end
|
|
66
71
|
|
|
67
|
-
it 'should
|
|
68
|
-
Client.find(Person.create!.id).should
|
|
72
|
+
it 'should find an object with id of a different model' do
|
|
73
|
+
Client.find(Person.create!.id).class.should == Person
|
|
69
74
|
end
|
|
70
75
|
end
|
|
71
76
|
|
data/spec/models/neo_user.rb
CHANGED
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:
|
|
4
|
+
version: 2.0.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-01-
|
|
11
|
+
date: 2014-01-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: active_attr
|
|
@@ -152,11 +152,13 @@ files:
|
|
|
152
152
|
- lib/active_node/callbacks.rb
|
|
153
153
|
- lib/active_node/core.rb
|
|
154
154
|
- lib/active_node/errors.rb
|
|
155
|
+
- lib/active_node/neo.rb
|
|
155
156
|
- lib/active_node/persistence.rb
|
|
156
157
|
- lib/active_node/reflection.rb
|
|
157
158
|
- lib/active_node/validations.rb
|
|
158
159
|
- lib/active_node/version.rb
|
|
159
160
|
- spec/functional/associations_spec.rb
|
|
161
|
+
- spec/functional/base_spec.rb
|
|
160
162
|
- spec/functional/persistence_spec.rb
|
|
161
163
|
- spec/functional/validations_spec.rb
|
|
162
164
|
- spec/models/address.rb
|
|
@@ -189,6 +191,7 @@ specification_version: 4
|
|
|
189
191
|
summary: ActiveRecord style Object Graph Mapping for neo4j
|
|
190
192
|
test_files:
|
|
191
193
|
- spec/functional/associations_spec.rb
|
|
194
|
+
- spec/functional/base_spec.rb
|
|
192
195
|
- spec/functional/persistence_spec.rb
|
|
193
196
|
- spec/functional/validations_spec.rb
|
|
194
197
|
- spec/models/address.rb
|