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