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