active_node 2.2.6 → 2.2.7
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/lib/active_node/graph.rb +31 -34
- data/lib/active_node/persistence.rb +16 -13
- data/lib/active_node/version.rb +1 -1
- data/lib/ext/rails/generators/generated_attribute.rb +9 -0
- data/lib/generators/active_node/model/USAGE +55 -0
- data/lib/generators/active_node/model/model_generator.rb +25 -0
- data/lib/generators/active_node/model/templates/model.rb.erb +10 -0
- data/spec/functional/graph_spec.rb +8 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b61a35ae17f4598504c8840a398430f85c0a6a3
|
4
|
+
data.tar.gz: 4ee34af5defc7d4e94f201ffac233ff0ab30344b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f100b6302c72bc460b5f8149adaaf5bf179bb3dd6b2a84ad5db8bacb12db160ae4ad366243c19bb20a1bee3f90b20b0b11515f9fbd5d97f8c117bc52d5710fd
|
7
|
+
data.tar.gz: 7547f7c6a17f49dc5ad264843b16007cd17a1dc28b8f785c9fdb1fb519770eee51ff73a7a4e0b15e82b1ba889a6f4efd3facb3a60bc3d159ba483fae97409c2b
|
data/lib/active_node/graph.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module ActiveNode
|
2
2
|
class Graph
|
3
|
-
MULTI_VALUE_METHODS
|
4
|
-
|
5
|
-
|
3
|
+
MULTI_VALUE_METHODS = [:includes, :eager_load, :preload, :select, :group,
|
4
|
+
:order, :joins, :where, :having, :bind, :references,
|
5
|
+
:extending, :unscope]
|
6
6
|
|
7
7
|
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reordering,
|
8
8
|
:reverse_order, :distinct, :create_with, :uniq]
|
@@ -15,6 +15,8 @@ module ActiveNode
|
|
15
15
|
attr_reader :reflections, :matches, :klass, :loaded
|
16
16
|
alias :loaded? :loaded
|
17
17
|
|
18
|
+
delegate :data, :extract_id, to: ActiveNode::Base
|
19
|
+
|
18
20
|
def initialize klass, *includes
|
19
21
|
@klass = klass if klass < ActiveNode::Base
|
20
22
|
@matches = []
|
@@ -51,7 +53,7 @@ module ActiveNode
|
|
51
53
|
end
|
52
54
|
|
53
55
|
def load
|
54
|
-
parse_results execute unless loaded?
|
56
|
+
parse_results execute['data'] unless loaded?
|
55
57
|
self
|
56
58
|
end
|
57
59
|
|
@@ -159,30 +161,27 @@ module ActiveNode
|
|
159
161
|
end
|
160
162
|
|
161
163
|
def sanitize_where
|
162
|
-
@where.each { |key, value| @where[key] = extract_id(value) if key.to_s == 'id'}
|
164
|
+
@where.each { |key, value| @where[key] = extract_id(value) if key.to_s == 'id' }
|
163
165
|
end
|
164
166
|
|
165
167
|
def to_cypher
|
166
168
|
[initial_match, conditions, "with n0", order_list, skip_cond, limit_cond, query, 'return', list_with_rel(@reflections.size), order_list_with_defaults].compact.join ' '
|
167
169
|
end
|
168
170
|
|
169
|
-
def parse_results
|
170
|
-
records = Set.new
|
171
|
-
|
172
|
-
|
171
|
+
def parse_results data
|
172
|
+
@records = data.reduce(Set.new) { |set, record| set << wrap(record.first, @klass) }.to_a
|
173
|
+
alternate_cells(data, 2) { |node, reflection| wrap node, reflection.klass }
|
174
|
+
alternate_cells(data, 1) { |rel, reflection| wrap_rel [rel].flatten.last, reflection }
|
175
|
+
@loaded = true
|
176
|
+
end
|
177
|
+
|
178
|
+
def alternate_cells data, shift
|
179
|
+
data.each do |row|
|
173
180
|
@reflections.each_with_index do |reflection, index|
|
174
|
-
|
175
|
-
|
176
|
-
next unless node_rel
|
177
|
-
owner = @object_cache[owner_id node_rel, reflection.direction]
|
178
|
-
node = wrap record[2*index + 2], reflection.klass
|
179
|
-
rel = reflection.klass.create_rel node_rel, node
|
180
|
-
assoc = owner.association(reflection.name)
|
181
|
-
assoc.rels_writer((assoc.rel_target || []) << rel) unless previously_loaded?(assoc)
|
181
|
+
cell = row[2*index + shift]
|
182
|
+
yield cell, reflection if cell
|
182
183
|
end
|
183
184
|
end
|
184
|
-
@loaded = true
|
185
|
-
@records = records.to_a
|
186
185
|
end
|
187
186
|
|
188
187
|
def previously_loaded?(assoc)
|
@@ -194,8 +193,19 @@ module ActiveNode
|
|
194
193
|
@object_cache[extract_id record] ||= ActiveNode::Base.wrap(record, klass)
|
195
194
|
end
|
196
195
|
|
197
|
-
def
|
198
|
-
extract_id
|
196
|
+
def wrap_rel(rel, reflection)
|
197
|
+
@relationship_cache[extract_id rel] ||= create_rel(rel, reflection)
|
198
|
+
end
|
199
|
+
|
200
|
+
def create_rel(rel, reflection)
|
201
|
+
ActiveNode::Relationship.new(@object_cache[node_id rel, reflection, :other], data(rel)).tap do |relationship|
|
202
|
+
assoc = @object_cache[node_id rel, reflection, :owner].association(reflection.name)
|
203
|
+
assoc.rels_writer((assoc.rel_target || []) << relationship) unless previously_loaded?(assoc)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def node_id relationship, reflection, side
|
208
|
+
extract_id relationship[reflection.direction == {owner: :outgoing, other: :incoming}[side] ? 'start' : 'end']
|
199
209
|
end
|
200
210
|
|
201
211
|
def parse_paths as, klass, includes
|
@@ -256,18 +266,5 @@ module ActiveNode
|
|
256
266
|
end
|
257
267
|
"order by #{build_order(:n0)}"
|
258
268
|
end
|
259
|
-
|
260
|
-
def extract_id(id)
|
261
|
-
case id
|
262
|
-
when Array
|
263
|
-
id.map { |i| extract_id(i) }
|
264
|
-
when ActiveNode::Base
|
265
|
-
id.id
|
266
|
-
else
|
267
|
-
get_id(id).to_i
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
|
272
269
|
end
|
273
270
|
end
|
@@ -31,14 +31,6 @@ module ActiveNode
|
|
31
31
|
node.is_a?(Array) ? new_instances(node, klass) : new_instance(node, klass)
|
32
32
|
end
|
33
33
|
|
34
|
-
def wrap_rel rel, node, klass
|
35
|
-
create_rel rel, wrap(node, klass)
|
36
|
-
end
|
37
|
-
|
38
|
-
def create_rel rel, node
|
39
|
-
ActiveNode::Relationship.new node, rel['data'].merge(id: get_id(rel).to_i)
|
40
|
-
end
|
41
|
-
|
42
34
|
def active_node_class(class_name, default_klass=nil)
|
43
35
|
klass = Module.const_get(class_name) rescue nil
|
44
36
|
klass && klass < ActiveNode::Base && klass || default_klass
|
@@ -48,15 +40,26 @@ module ActiveNode
|
|
48
40
|
ActiveNode::Graph.new(self)
|
49
41
|
end
|
50
42
|
|
43
|
+
def data hash
|
44
|
+
hash['data'].merge(id: extract_id(hash))
|
45
|
+
end
|
46
|
+
|
47
|
+
def extract_id(id)
|
48
|
+
case id
|
49
|
+
when Array
|
50
|
+
id.map { |i| extract_id(i) }
|
51
|
+
when ActiveNode::Base
|
52
|
+
id.id
|
53
|
+
else
|
54
|
+
get_id(id).to_i
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
51
58
|
private
|
52
59
|
def new_instance node, klass=nil
|
53
60
|
node && (klass || find_suitable_class(Neo.db.get_node_labels(node))).try(:new, data(node), :declared?)
|
54
61
|
end
|
55
62
|
|
56
|
-
def data hash
|
57
|
-
hash['data'].merge(id: get_id(hash).to_i)
|
58
|
-
end
|
59
|
-
|
60
63
|
def new_instances nodes, klass=nil
|
61
64
|
nodes.map { |node| new_instance(node, klass) }.compact
|
62
65
|
end
|
@@ -203,7 +206,7 @@ module ActiveNode
|
|
203
206
|
end
|
204
207
|
|
205
208
|
def create_node_with_label
|
206
|
-
self.id =
|
209
|
+
self.id = self.class.extract_id(Neo.db.create_node(all_attributes))
|
207
210
|
Neo.db.set_label(id, self.class.label)
|
208
211
|
end
|
209
212
|
|
data/lib/active_node/version.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
Description:
|
2
|
+
Creates a new ActiveNode model, using the given NAME. Similar to with
|
3
|
+
active_record, pass the model name, either CamelCased or under_scored, and
|
4
|
+
an optional list of attribute pairs as arguments.
|
5
|
+
|
6
|
+
Attribute pairs are attribute:type arguments specifying the model's
|
7
|
+
attributes. The +timestamps+ call is added by default, so you don't have to
|
8
|
+
a) specify them as explicit attributes, nor b) add the +timestamps+ call
|
9
|
+
yourself. You can, however, turn this off by using the +--no-timestamps+
|
10
|
+
option.
|
11
|
+
|
12
|
+
This generator invokes your configured test framework and will, thus,
|
13
|
+
create tests for your generated model.
|
14
|
+
|
15
|
+
|
16
|
+
Available field types:
|
17
|
+
|
18
|
+
Just after the field name you can specify a type like String or boolean.
|
19
|
+
It will generate the property key with the associated Neo4J value type. You
|
20
|
+
can use the following types:
|
21
|
+
|
22
|
+
* big_decimal
|
23
|
+
* boolean
|
24
|
+
* date
|
25
|
+
* date_time
|
26
|
+
* float
|
27
|
+
* integer
|
28
|
+
* object
|
29
|
+
* string
|
30
|
+
|
31
|
+
Examples:
|
32
|
+
|
33
|
+
`rails generate active_node:model Car`
|
34
|
+
|
35
|
+
Creates:
|
36
|
+
|
37
|
+
Model: +app/models/car.rb+
|
38
|
+
Test: +test/models/car_test.rb+
|
39
|
+
|
40
|
+
`rails generate active_node:model Car make engine_displacement`
|
41
|
+
|
42
|
+
This will...
|
43
|
+
|
44
|
+
...create app/models/car.rb
|
45
|
+
...add ActiveNode attributes +make+ and +engine_displacement+,
|
46
|
+
without specifying the attribute type.
|
47
|
+
|
48
|
+
`rails generate active_node:model Car make:string engine_displacement:short`
|
49
|
+
|
50
|
+
This will...
|
51
|
+
|
52
|
+
* ...app/models/car.rb
|
53
|
+
* ...add ActiveNode attributes +make+ as type String, and
|
54
|
+
+engine_displacement+ as type short.
|
55
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative '../../../ext/rails/generators/generated_attribute'
|
2
|
+
|
3
|
+
module ActiveNode
|
4
|
+
class ModelGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
check_class_collision
|
7
|
+
|
8
|
+
class_option :timestamps,
|
9
|
+
type: :boolean,
|
10
|
+
default: true
|
11
|
+
|
12
|
+
hook_for :test_framework,
|
13
|
+
as: :model,
|
14
|
+
aliases: '-t'
|
15
|
+
|
16
|
+
argument :attributes,
|
17
|
+
type: :array,
|
18
|
+
default: [],
|
19
|
+
banner: 'attribute[:type] attribute[:type]'
|
20
|
+
|
21
|
+
def create_model_file
|
22
|
+
template 'model.rb.erb', File.join('app/models', class_path, "#{file_name}.rb")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% module_namespacing do -%>
|
2
|
+
class <%= class_name %> < ActiveNode::Base
|
3
|
+
<% attributes.reject(&:reference?).each do |attribute| -%>
|
4
|
+
attribute :<%= attribute.name %>, type: <%= attribute.type_class %>
|
5
|
+
<% end -%>
|
6
|
+
<% if options[:timestamps] -%>
|
7
|
+
timestamps
|
8
|
+
<% end -%>
|
9
|
+
end
|
10
|
+
<% end -%>
|
@@ -50,5 +50,13 @@ describe ActiveNode::Graph do
|
|
50
50
|
p = Person.create! father: Person.create!
|
51
51
|
Person.where(id: p.id).includes(:father).first.should == p
|
52
52
|
end
|
53
|
+
|
54
|
+
it "should return correct associated objects" do
|
55
|
+
child1 = Person.create! children: [Person.create!, Person.create!]
|
56
|
+
person = Person.create! children: [child1]
|
57
|
+
Person.includes(children: :children).find(person.id).children.should == [child1]
|
58
|
+
Person.includes(children: 2).find(person.id).children.should == [child1]
|
59
|
+
Person.includes(children: '*').find(person.id).children.should == [child1]
|
60
|
+
end
|
53
61
|
end
|
54
62
|
end
|
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.2.
|
4
|
+
version: 2.2.7
|
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-09-
|
11
|
+
date: 2014-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_attr
|
@@ -180,6 +180,10 @@ files:
|
|
180
180
|
- lib/active_node/validations.rb
|
181
181
|
- lib/active_node/validations/uniqueness.rb
|
182
182
|
- lib/active_node/version.rb
|
183
|
+
- lib/ext/rails/generators/generated_attribute.rb
|
184
|
+
- lib/generators/active_node/model/USAGE
|
185
|
+
- lib/generators/active_node/model/model_generator.rb
|
186
|
+
- lib/generators/active_node/model/templates/model.rb.erb
|
183
187
|
- spec/functional/associations_spec.rb
|
184
188
|
- spec/functional/base_spec.rb
|
185
189
|
- spec/functional/graph/query_methods_spec.rb
|