neo4j 3.0.3 → 3.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/lib/neo4j/active_node/id_property.rb +4 -8
- data/lib/neo4j/active_node/node_wrapper.rb +2 -0
- data/lib/neo4j/active_node/query/query_proxy.rb +50 -2
- data/lib/neo4j/active_node/query/query_proxy_methods.rb +27 -2
- data/lib/neo4j/active_node/query_methods.rb +0 -5
- data/lib/neo4j/active_node/reflection.rb +1 -1
- data/lib/neo4j/active_rel/persistence.rb +11 -7
- data/lib/neo4j/config.rb +5 -2
- data/lib/neo4j/paginated.rb +1 -2
- data/lib/neo4j/shared.rb +1 -1
- data/lib/neo4j/version.rb +1 -1
- data/neo4j.gemspec +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf2546cbe829d338babc703fcecdeff5650e8fd5
|
4
|
+
data.tar.gz: 094b2019bb62cb8e9f5e510eb54cf00f51c6131f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7552de25d876bd2b98038637c517ae77c47c04ae5d3fbd0a14852710998a3549d1ce981a9c35eea94e84cf1dcc04f469497ae7c7eb9be45a76b77f813900bd8
|
7
|
+
data.tar.gz: ba45f543a6cbce758ccfba472789cfb41ba78ce8ee6fe70db8e187371a1a638e83c86a6dae316a4ff786046a61b2ab3a984001993d4150b30e9eee57c4b89fcd
|
data/Gemfile
CHANGED
@@ -2,7 +2,7 @@ source 'http://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
gem 'neo4j-core', github: 'neo4jrb/neo4j-core'
|
5
|
+
#gem 'neo4j-core', github: 'neo4jrb/neo4j-core', branch: 'master'
|
6
6
|
#gem 'neo4j-core', git: 'https://github.com/neo4jrb/neo4j-core'
|
7
7
|
#gem 'orm_adapter', :path => '../orm_adapter'
|
8
8
|
|
@@ -27,25 +27,21 @@ module Neo4j::ActiveNode
|
|
27
27
|
|
28
28
|
module TypeMethods
|
29
29
|
def define_id_methods(clazz, name, conf)
|
30
|
-
|
30
|
+
raise "Expected a Hash, got #{conf.class} (#{conf.to_s}) for id_property" unless conf.is_a?(Hash)
|
31
31
|
if conf[:on]
|
32
32
|
define_custom_method(clazz, name, conf[:on])
|
33
33
|
elsif conf[:auto]
|
34
34
|
raise "only :uuid auto id_property allowed, got #{conf[:auto]}" unless conf[:auto] == :uuid
|
35
35
|
define_uuid_method(clazz, name)
|
36
|
-
|
36
|
+
elsif conf.empty?
|
37
37
|
define_property_method(clazz, name)
|
38
|
+
else
|
39
|
+
raise "Illegal value #{conf.inspect} for id_property, expected :on or :auto"
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
private
|
42
44
|
|
43
|
-
def validate_conf(conf)
|
44
|
-
return if conf.empty?
|
45
|
-
raise "Expected a Hash, got #{conf.class} (#{conf.to_s}) for id_property" unless conf.is_a?(Hash)
|
46
|
-
raise "Illegal value #{conf.inspect} for id_property, expected :on or :auto" unless conf.include?(:auto) || conf.include?(:on)
|
47
|
-
end
|
48
|
-
|
49
45
|
def define_property_method(clazz, name)
|
50
46
|
clear_methods(clazz, name)
|
51
47
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
class Neo4j::Node
|
2
|
+
# The wrapping process is what transforms a raw CypherNode or EmbeddedNode from Neo4j::Core into a healthy ActiveNode (or ActiveRel) object.
|
2
3
|
module Wrapper
|
3
4
|
|
4
5
|
# this is a plugin in the neo4j-core so that the Ruby wrapper will be wrapped around the Neo4j::Node objects
|
@@ -23,6 +24,7 @@ class Neo4j::Node
|
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
27
|
+
# Makes the determination of whether to use <tt>_classname</tt> (or whatever is defined by config) or the node's labels.
|
26
28
|
def sorted_wrapper_classes
|
27
29
|
if self.props.is_a?(Hash) && self.props.has_key?(Neo4j::Config.class_name_property)
|
28
30
|
self.props[Neo4j::Config.class_name_property].constantize
|
@@ -11,6 +11,27 @@ module Neo4j
|
|
11
11
|
# Will be nil when using QueryProxy chains on class methods.
|
12
12
|
attr_reader :caller
|
13
13
|
|
14
|
+
# QueryProxy is ActiveNode's Cypher DSL. While the name might imply that it creates queries in a general sense,
|
15
|
+
# it is actually referring to <tt>Neo4j::Core::Query</tt>, which is a pure Ruby Cypher DSL provided by the <tt>neo4j-core</tt> gem.
|
16
|
+
# QueryProxy provides ActiveRecord-like methods for common patterns. When it's not handling CRUD for relationships and queries, it
|
17
|
+
# provides ActiveNode's association chaining (`student.lessons.teachers.where(age: 30).hobbies`) and enjoys long walks on the
|
18
|
+
# beach.
|
19
|
+
#
|
20
|
+
# It should not ever be necessary to instantiate a new QueryProxy object directly, it always happens as a result of
|
21
|
+
# calling a method that makes use of it.
|
22
|
+
#
|
23
|
+
# @param [Constant] model The class which included ActiveNode (typically a model, hence the name) from which the query
|
24
|
+
# originated.
|
25
|
+
# @param [Neo4j::ActiveNode::HasN::Association] association The ActiveNode association (an object created by a <tt>has_one</tt> or
|
26
|
+
# <tt>has_many</tt>) that created this object.
|
27
|
+
# @param [Hash] options Additional options pertaining to the QueryProxy object. These may include:
|
28
|
+
# * node_var: A string or symbol to be used by Cypher within its query string as an identifier
|
29
|
+
# * rel_var: Same as above but pertaining to a relationship identifier
|
30
|
+
# * session: The session to be used for this query
|
31
|
+
# * caller: The node instance at the start of the QueryProxy chain
|
32
|
+
# * query_proxy: An existing QueryProxy chain upon which this new object should be built
|
33
|
+
#
|
34
|
+
# QueryProxy objects are evaluated lazily.
|
14
35
|
def initialize(model, association = nil, options = {})
|
15
36
|
@model = model
|
16
37
|
@association = association
|
@@ -24,10 +45,21 @@ module Neo4j
|
|
24
45
|
@params = options[:query_proxy] ? options[:query_proxy].instance_variable_get('@params') : {}
|
25
46
|
end
|
26
47
|
|
48
|
+
# The current node identifier on deck, so to speak. It is the object that will be returned by calling `each` and the last node link
|
49
|
+
# in the QueryProxy chain.
|
27
50
|
def identity
|
28
51
|
@node_var || :result
|
29
52
|
end
|
30
53
|
|
54
|
+
# The relationship identifier most recently used by the QueryProxy chain.
|
55
|
+
def rel_identity
|
56
|
+
@rel_var
|
57
|
+
end
|
58
|
+
|
59
|
+
# Executes the query against the database if the results are not already present in a node's association cache. This method is
|
60
|
+
# shared by <tt>each</tt>, <tt>each_rel</tt>, and <tt>each_with_rel</tt>.
|
61
|
+
# @param [String,Symbol] node The string or symbol of the node to return from the database.
|
62
|
+
# @param [String,Symbol] rel The string or symbol of a relationship to return from the database.
|
31
63
|
def enumerable_query(node, rel = nil)
|
32
64
|
pluck_this = rel.nil? ? [node] : [node, rel]
|
33
65
|
return self.pluck(*pluck_this) if @association.nil? || caller.nil?
|
@@ -40,6 +72,10 @@ module Neo4j
|
|
40
72
|
association_collection
|
41
73
|
end
|
42
74
|
|
75
|
+
# Just like every other <tt>each</tt> but it allows for optional params to support the versions that also return relationships.
|
76
|
+
# The <tt>node</tt> and <tt>rel</tt> params are typically used by those other methods but there's nothing stopping you from
|
77
|
+
# using `your_node.each(true, true)` instead of `your_node.each_with_rel`.
|
78
|
+
# @return [Enumerable] An enumerable containing some combination of nodes and rels.
|
43
79
|
def each(node = true, rel = nil, &block)
|
44
80
|
if node && rel
|
45
81
|
enumerable_query(identity, @rel_var).each { |obj, rel| yield obj, rel }
|
@@ -49,14 +85,23 @@ module Neo4j
|
|
49
85
|
end
|
50
86
|
end
|
51
87
|
|
88
|
+
# When called at the end of a QueryProxy chain, it will return the resultant relationship objects intead of nodes.
|
89
|
+
# For example, to return the relationship between a given student and their lessons:
|
90
|
+
# student.lessons.each_rel do |rel|
|
91
|
+
# @return [Enumerable] An enumerable containing any number of applicable relationship objects.
|
52
92
|
def each_rel(&block)
|
53
93
|
block_given? ? each(false, true, &block) : to_enum(:each, false, true)
|
54
94
|
end
|
55
95
|
|
96
|
+
# When called at the end of a QueryProxy chain, it will return the nodes and relationships of the last link.
|
97
|
+
# For example, to return a lesson and each relationship to a given student:
|
98
|
+
# student.lessons.each_with_rel do |lesson, rel|
|
56
99
|
def each_with_rel(&block)
|
57
100
|
block_given? ? each(true, true, &block) : to_enum(:each, true, true)
|
58
101
|
end
|
59
102
|
|
103
|
+
# Does exactly what you would hope. Without it, comparing `bobby.lessons == sandy.lessons` would evaluate to false because it
|
104
|
+
# would be comparing the QueryProxy objects, not the lessons themselves.
|
60
105
|
def ==(value)
|
61
106
|
self.to_a == value
|
62
107
|
end
|
@@ -89,7 +134,10 @@ module Neo4j
|
|
89
134
|
query_as(identity)
|
90
135
|
end
|
91
136
|
|
92
|
-
# Build a Neo4j::Core::Query object for the QueryProxy
|
137
|
+
# Build a Neo4j::Core::Query object for the QueryProxy. This is necessary when you want to take an existing QueryProxy chain
|
138
|
+
# and work with it from the more powerful (but less friendly) Neo4j::Core::Query.
|
139
|
+
# @param [String,Symbol] var The identifier to use for node at this link of the QueryProxy chain.
|
140
|
+
# student.lessons.query_as(:l).with('your cypher here...')
|
93
141
|
def query_as(var)
|
94
142
|
var = @node_var if @node_var
|
95
143
|
query = if @association
|
@@ -106,7 +154,7 @@ module Neo4j
|
|
106
154
|
end
|
107
155
|
end
|
108
156
|
|
109
|
-
# Cypher string for the QueryProxy's query
|
157
|
+
# Cypher string for the QueryProxy's query. This will not include params. For the full output, see <tt>to_cypher_with_params</tt>.
|
110
158
|
def to_cypher
|
111
159
|
query.to_cypher
|
112
160
|
end
|
@@ -49,11 +49,36 @@ module Neo4j
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
# Deletes a group of nodes and relationships within a QP chain. When identifier is omitted, it will remove the last link in the chain.
|
53
|
+
# The optional argument must be a node identifier. A relationship identifier will result in a Cypher Error
|
54
|
+
# @param [String,Symbol] the optional identifier of the link in the chain to delete.
|
55
|
+
def delete_all(identifier = nil)
|
56
|
+
query_with_target(identifier) do |target|
|
57
|
+
begin
|
58
|
+
self.query.with(target).match("(#{target})-[#{target}_rel]-()").delete("#{target}, #{target}_rel").exec
|
59
|
+
rescue Neo4j::Session::CypherError
|
60
|
+
self.query.delete(target).exec
|
61
|
+
end
|
62
|
+
self.caller.clear_association_cache if self.caller.respond_to?(:clear_association_cache)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Shorthand for `MATCH (start)-[r]-(other_node) WHERE ID(other_node) = #{other_node.neo_id}`
|
67
|
+
# @return [Neo4j::ActiveNode::Query::QueryProxy] A QueryProxy object upon which you can build.
|
68
|
+
def match_to(node)
|
69
|
+
self.where(neo_id: node.neo_id)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Gives you the first relationship between the last link of a QueryProxy chain and a given node
|
73
|
+
# Shorthand for `MATCH (start)-[r]-(other_node) WHERE ID(other_node) = #{other_node.neo_id} RETURN r`
|
74
|
+
def first_rel_to(node)
|
75
|
+
self.where(neo_id: node.neo_id).limit(1).pluck(rel_identity).first
|
76
|
+
end
|
77
|
+
|
52
78
|
private
|
53
79
|
|
54
80
|
def query_with_target(target, &block)
|
55
|
-
target
|
56
|
-
block.yield(target)
|
81
|
+
block.yield(target || identity)
|
57
82
|
end
|
58
83
|
|
59
84
|
def exists_query_start(origin, condition, target)
|
@@ -36,11 +36,6 @@ module Neo4j
|
|
36
36
|
|
37
37
|
alias_method :blank?, :empty?
|
38
38
|
|
39
|
-
def include?(other)
|
40
|
-
raise(InvalidParameterError, ':include? only accepts nodes') unless other.respond_to?(:neo_id)
|
41
|
-
self.query_as(:n).where(n: {primary_key => other.id}).return("count(n) AS count").first.count > 0
|
42
|
-
end
|
43
|
-
|
44
39
|
def find_in_batches(options = {})
|
45
40
|
self.query_as(:n).return(:n).find_in_batches(:n, primary_key, options) do |batch|
|
46
41
|
yield batch.map(&:n)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Neo4j::ActiveNode
|
2
|
-
# A reflection contains information about an association.
|
2
|
+
# A reflection contains information about an association.
|
3
3
|
# They are often used in connection with form builders to determine associated classes.
|
4
4
|
# This module contains methods related to the creation and retrieval of reflections.
|
5
5
|
module Reflection
|
@@ -4,8 +4,8 @@ module Neo4j::ActiveRel
|
|
4
4
|
include Neo4j::Shared::Persistence
|
5
5
|
|
6
6
|
class RelInvalidError < RuntimeError; end
|
7
|
-
|
8
7
|
class ModelClassInvalidError < RuntimeError; end
|
8
|
+
class RelCreateFailedError < RuntimeError; end
|
9
9
|
|
10
10
|
def clear_association_cache; end
|
11
11
|
|
@@ -86,12 +86,16 @@ module Neo4j::ActiveRel
|
|
86
86
|
def _rel_creation_query(from_node, to_node, props)
|
87
87
|
from_class = from_node.class
|
88
88
|
to_class = to_node.class
|
89
|
-
|
90
|
-
.
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
begin
|
90
|
+
Neo4j::Session.query.match(n1: from_class.mapped_label_name, n2: to_class.mapped_label_name)
|
91
|
+
.where("n1.#{from_class.primary_key} = {from_node_id}")
|
92
|
+
.where("n2.#{to_class.primary_key} = {to_node_id}")
|
93
|
+
.params(from_node_id: from_node.id, to_node_id: to_node.id)
|
94
|
+
.create("(n1)-[r:`#{type}`]->(n2)")
|
95
|
+
.with('r').set(r: props).return(:r).first.r
|
96
|
+
rescue NoMethodError
|
97
|
+
raise RelCreateFailedError, "Unable to create relationship. from_node: #{from_node}, to_node: #{to_node}"
|
98
|
+
end
|
95
99
|
end
|
96
100
|
|
97
101
|
end
|
data/lib/neo4j/config.rb
CHANGED
@@ -113,7 +113,10 @@ module Neo4j
|
|
113
113
|
Neo4j::Config[:class_name_property] || :_classname
|
114
114
|
end
|
115
115
|
|
116
|
+
def include_root_in_json
|
117
|
+
# we use ternary because a simple || will always evaluate true
|
118
|
+
Neo4j::Config[:include_root_in_json].nil? ? true : Neo4j::Config[:include_root_in_json]
|
119
|
+
end
|
116
120
|
end
|
117
121
|
end
|
118
|
-
|
119
|
-
end
|
122
|
+
end
|
data/lib/neo4j/paginated.rb
CHANGED
@@ -8,9 +8,8 @@ module Neo4j
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.create_from(source, page, per_page, order = nil)
|
11
|
-
#partial = source.drop((page-1) * per_page).first(per_page)
|
12
11
|
target = source.node_var
|
13
|
-
partial = source.skip(page-1).limit(per_page)
|
12
|
+
partial = source.skip((page - 1) * per_page).limit(per_page)
|
14
13
|
ordered_partial, ordered_source = if order
|
15
14
|
[partial.order_by(order), source.query.with("#{target} as #{target}").pluck("COUNT(#{target})").first]
|
16
15
|
else
|
data/lib/neo4j/shared.rb
CHANGED
data/lib/neo4j/version.rb
CHANGED
data/neo4j.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.summary = "A graph database for Ruby"
|
17
17
|
s.license = 'MIT'
|
18
18
|
s.description = <<-EOF
|
19
|
-
A Neo4j OGM (Object-Graph-Mapper) for use in Ruby on Rails and Rack frameworks
|
19
|
+
A Neo4j OGM (Object-Graph-Mapper) for use in Ruby on Rails and Rack frameworks heavily inspired by ActiveRecord.
|
20
20
|
EOF
|
21
21
|
|
22
22
|
s.require_path = 'lib'
|
@@ -31,7 +31,7 @@ A Neo4j OGM (Object-Graph-Mapper) for use in Ruby on Rails and Rack frameworks,
|
|
31
31
|
s.add_dependency("activesupport", "~> 4")
|
32
32
|
s.add_dependency("railties", "~> 4")
|
33
33
|
s.add_dependency('active_attr', "~> 0.8")
|
34
|
-
s.add_dependency("neo4j-core", "~> 3.0.
|
34
|
+
s.add_dependency("neo4j-core", "~> 3.0.8")
|
35
35
|
|
36
36
|
if RUBY_PLATFORM =~ /java/
|
37
37
|
s.add_dependency("neo4j-community", '~> 2.0')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neo4j
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Ronge
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: orm_adapter
|
@@ -86,16 +86,16 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.0.
|
89
|
+
version: 3.0.8
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 3.0.
|
96
|
+
version: 3.0.8
|
97
97
|
description: |
|
98
|
-
A Neo4j OGM (Object-Graph-Mapper) for use in Ruby on Rails and Rack frameworks
|
98
|
+
A Neo4j OGM (Object-Graph-Mapper) for use in Ruby on Rails and Rack frameworks heavily inspired by ActiveRecord.
|
99
99
|
email: andreas.ronge@gmail.com
|
100
100
|
executables:
|
101
101
|
- neo4j-jars
|