neo4j 3.0.0.alpha.11 → 3.0.0.rc.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +12 -0
- data/README.md +18 -9
- data/lib/neo4j/active_node.rb +8 -0
- data/lib/neo4j/active_node/has_n.rb +56 -33
- data/lib/neo4j/active_node/has_n/association.rb +2 -2
- data/lib/neo4j/active_node/id_property.rb +5 -3
- data/lib/neo4j/active_node/labels.rb +27 -5
- data/lib/neo4j/active_node/node_wrapper.rb +1 -0
- data/lib/neo4j/active_node/query/query_proxy.rb +69 -14
- data/lib/neo4j/active_rel.rb +1 -0
- data/lib/neo4j/paginated.rb +1 -1
- data/lib/neo4j/railtie.rb +12 -0
- data/lib/neo4j/shared.rb +1 -3
- data/lib/neo4j/version.rb +1 -1
- data/lib/rails/generators/neo4j/model/model_generator.rb +7 -7
- data/lib/rails/generators/neo4j/model/templates/model.erb +4 -5
- data/neo4j.gemspec +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 489ffa77b2c5a647e44d217825a68af5fbeb13cf
|
4
|
+
data.tar.gz: 1ef50669eb2cbca0b88a1f7f1143ec5e56740527
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f275a297c3b4c2f93e2c655ad6cdaf3317f27ad9aa241959251558a1eb6202ec5e74b82e5c67684581df946b10be5209761dbd9d6826a0514d2afb6b235de015
|
7
|
+
data.tar.gz: b3e869867b335969ff6e4357e39f8796d894c6adedbafa426aa4fe0c30f67d261e4df8a31d00815b0fc8ba08888b32d39767b29ada56bb5ea3ed7f84fa5ba55e
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== 3.0.0.rc.2
|
2
|
+
* Use newer neo4j-core release
|
3
|
+
|
4
|
+
== 3.0.0.rc.1
|
5
|
+
* Support for count, size, length, empty, blank? for has_many relationship
|
6
|
+
* Support for rails logger of cypher queries in development
|
7
|
+
* Support for distinct count
|
8
|
+
* Optimized methods: https://github.com/andreasronge/neo4j/wiki/Optimized-Methods
|
9
|
+
* Queries should respect mapped label names (#421)
|
10
|
+
* Warn if no session is available
|
11
|
+
* Fix broken == and equality (#424)
|
12
|
+
|
1
13
|
== 3.0.0.alpha.11
|
2
14
|
* Bug fixes
|
3
15
|
|
data/README.md
CHANGED
@@ -2,22 +2,31 @@
|
|
2
2
|
|
3
3
|
Neo4j.rb is an Active Model compliant Ruby/JRuby wrapper for [the Neo4j graph database](http://www.neo4j.org/). It uses the [neo4j-core](https://github.com/andreasronge/neo4j-core) and [active_attr](https://github.com/cgriego/active_attr) gems.
|
4
4
|
|
5
|
-
##
|
5
|
+
## Documentation version 3.0.0.rc
|
6
6
|
|
7
|
-
|
7
|
+
* [Wiki](https://github.com/andreasronge/neo4j/wiki/Neo4j.rb-v3-Introduction)
|
8
8
|
|
9
|
-
|
10
|
-
* [Basic Rails 4 Example](https://github.com/andreasronge/neo4j/blob/master/example/blog/README.md)
|
9
|
+
## Documentation Old stable version 2.x
|
11
10
|
|
12
|
-
|
11
|
+
* [README](https://github.com/andreasronge/neo4j/tree/2.x)
|
12
|
+
* [Wiki](https://github.com/andreasronge/neo4j/wiki/Neo4j%3A%3ARails-Introduction)
|
13
|
+
|
14
|
+
## Support
|
15
|
+
|
16
|
+
* [Neo4j.rb mailing list](https://groups.google.com/forum/#!forum/neo4jrb)
|
17
|
+
* Consulting support ? ask any of the developers
|
18
|
+
|
19
|
+
## Developers
|
20
|
+
|
21
|
+
* [Andreas Ronge](https://github.com/andreasronge)
|
22
|
+
* [Brian Underwood](https://github.com/cheerfulstoic)
|
23
|
+
* [Chris Grigg](https://github.com/subvertallchris)
|
13
24
|
|
14
|
-
For the stable 2.x version, see [here](https://github.com/andreasronge/neo4j/tree/2.x)
|
15
25
|
|
16
26
|
## Contributing
|
17
27
|
|
18
|
-
|
19
|
-
|
20
|
-
* Do you need help - send me an email (andreas.ronge at gmail dot com).
|
28
|
+
Pull request with high test coverage and good [code climate](https://codeclimate.com/github/andreasronge/neo4j) values will be accepted faster.
|
29
|
+
|
21
30
|
|
22
31
|
## License
|
23
32
|
|
data/lib/neo4j/active_node.rb
CHANGED
@@ -25,6 +25,7 @@ module Neo4j
|
|
25
25
|
extend ActiveSupport::Concern
|
26
26
|
|
27
27
|
include Neo4j::Shared
|
28
|
+
include Neo4j::Shared::Identity
|
28
29
|
include Neo4j::ActiveNode::Initialize
|
29
30
|
include Neo4j::ActiveNode::IdProperty
|
30
31
|
include Neo4j::ActiveNode::SerializedProperties
|
@@ -43,6 +44,7 @@ module Neo4j
|
|
43
44
|
|
44
45
|
included do
|
45
46
|
def self.inherited(other)
|
47
|
+
inherit_id_property(other) if self.id_property_info
|
46
48
|
inherited_indexes(other) if self.respond_to?(:indexed_properties)
|
47
49
|
attributes.each_pair do |k,v|
|
48
50
|
other.attributes[k] = v
|
@@ -56,6 +58,12 @@ module Neo4j
|
|
56
58
|
self.indexed_properties.each {|property| other.index property }
|
57
59
|
end
|
58
60
|
|
61
|
+
def self.inherit_id_property(other)
|
62
|
+
id_prop = self.id_property_info
|
63
|
+
conf = id_prop[:type].empty? ? {auto: :uuid} : id_prop[:type]
|
64
|
+
other.id_property id_prop[:name], conf
|
65
|
+
end
|
66
|
+
|
59
67
|
Neo4j::Session.on_session_available do |_|
|
60
68
|
name = Neo4j::Config[:id_property]
|
61
69
|
type = Neo4j::Config[:id_property_type]
|
@@ -1,39 +1,49 @@
|
|
1
1
|
module Neo4j::ActiveNode
|
2
|
-
|
3
|
-
|
2
|
+
module HasN
|
3
|
+
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
|
5
|
+
class NonPersistedNodeError < StandardError; end
|
6
6
|
|
7
|
-
|
8
|
-
!!associations[name]
|
9
|
-
end
|
10
|
-
|
11
|
-
def associations
|
12
|
-
@associations || {}
|
13
|
-
end
|
7
|
+
module ClassMethods
|
14
8
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
super
|
20
|
-
end
|
21
|
-
|
22
|
-
def has_many(direction, name, options = {})
|
23
|
-
name = name.to_sym
|
9
|
+
def has_association?(name)
|
10
|
+
!!associations[name.to_sym]
|
11
|
+
end
|
24
12
|
|
25
|
-
|
26
|
-
|
13
|
+
def associations
|
14
|
+
@associations || {}
|
15
|
+
end
|
27
16
|
|
28
|
-
|
29
|
-
|
17
|
+
# make sure the inherited classes inherit the <tt>_decl_rels</tt> hash
|
18
|
+
def inherited(klass)
|
19
|
+
klass.instance_variable_set(:@associations, associations.clone)
|
30
20
|
|
31
|
-
|
21
|
+
super
|
22
|
+
end
|
32
23
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
24
|
+
def has_many(direction, name, options = {})
|
25
|
+
name = name.to_sym
|
26
|
+
|
27
|
+
association = Neo4j::ActiveNode::HasN::Association.new(:has_many, direction, name, options)
|
28
|
+
|
29
|
+
@associations ||= {}
|
30
|
+
@associations[name] = association
|
31
|
+
|
32
|
+
target_class_name = association.target_class_name || 'nil'
|
33
|
+
|
34
|
+
# TODO: Make assignment more efficient? (don't delete nodes when they are being assigned)
|
35
|
+
module_eval(%Q{
|
36
|
+
def #{name}(node = nil, rel = nil)
|
37
|
+
return [].freeze unless self.persisted?
|
38
|
+
Neo4j::ActiveNode::Query::QueryProxy.new(#{target_class_name},
|
39
|
+
self.class.associations[#{name.inspect}],
|
40
|
+
{
|
41
|
+
session: self.class.neo4j_session,
|
42
|
+
start_object: self,
|
43
|
+
node: node,
|
44
|
+
rel: rel,
|
45
|
+
context: '#{self.name}##{name}'
|
46
|
+
})
|
37
47
|
end
|
38
48
|
|
39
49
|
def #{name}=(other_nodes)
|
@@ -50,7 +60,16 @@ module Neo4j::ActiveNode
|
|
50
60
|
|
51
61
|
instance_eval(%Q{
|
52
62
|
def #{name}(node = nil, rel = nil)
|
53
|
-
|
63
|
+
context = (self.query_proxy && self.query_proxy.context ? self.query_proxy.context : '#{self.name}') + '##{name}'
|
64
|
+
Neo4j::ActiveNode::Query::QueryProxy.new(#{target_class_name},
|
65
|
+
@associations[#{name.inspect}],
|
66
|
+
{
|
67
|
+
session: self.neo4j_session,
|
68
|
+
query_proxy: self.query_proxy,
|
69
|
+
node: node,
|
70
|
+
rel: rel,
|
71
|
+
context: context
|
72
|
+
})
|
54
73
|
end}, __FILE__, __LINE__)
|
55
74
|
end
|
56
75
|
|
@@ -58,7 +77,6 @@ module Neo4j::ActiveNode
|
|
58
77
|
name = name.to_sym
|
59
78
|
|
60
79
|
association = Neo4j::ActiveNode::HasN::Association.new(:has_one, direction, name, options)
|
61
|
-
name = name.to_sym
|
62
80
|
|
63
81
|
@associations ||= {}
|
64
82
|
@associations[name] = association
|
@@ -67,6 +85,7 @@ module Neo4j::ActiveNode
|
|
67
85
|
|
68
86
|
module_eval(%Q{
|
69
87
|
def #{name}=(other_node)
|
88
|
+
raise(Neo4j::ActiveNode::HasN::NonPersistedNodeError, 'Unable to create relationship with non-persisted nodes') unless self.persisted?
|
70
89
|
#{name}_query_proxy(rel: :r).query_as(:n).delete(:r).exec
|
71
90
|
#{name}_query_proxy << other_node
|
72
91
|
end
|
@@ -80,16 +99,20 @@ module Neo4j::ActiveNode
|
|
80
99
|
end
|
81
100
|
|
82
101
|
def #{name}(node = nil, rel = nil)
|
83
|
-
|
102
|
+
return nil unless self.persisted?
|
103
|
+
#{name}_query_proxy(node: node, rel: rel, context: '#{self.name}##{name}').first
|
84
104
|
end}, __FILE__, __LINE__)
|
85
105
|
|
86
106
|
instance_eval(%Q{
|
87
107
|
def #{name}_query_proxy(options = {})
|
88
|
-
Neo4j::ActiveNode::Query::QueryProxy.new(#{target_class_name},
|
108
|
+
Neo4j::ActiveNode::Query::QueryProxy.new(#{target_class_name},
|
109
|
+
@associations[#{name.inspect}],
|
110
|
+
{session: self.neo4j_session}.merge(options))
|
89
111
|
end
|
90
112
|
|
91
113
|
def #{name}(node = nil, rel = nil)
|
92
|
-
|
114
|
+
context = (self.query_proxy && self.query_proxy.context ? self.query_proxy.context : '#{self.name}') + '##{name}'
|
115
|
+
#{name}_query_proxy(query_proxy: self.query_proxy, node: node, rel: rel, context: context)
|
93
116
|
end}, __FILE__, __LINE__)
|
94
117
|
end
|
95
118
|
|
@@ -117,8 +117,8 @@ module Neo4j
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def check_valid_type_and_dir(type, direction)
|
120
|
-
raise ArgumentError, "Invalid association type: #{type.inspect}" if not [:has_many, :has_one].include?(type.to_sym)
|
121
|
-
raise ArgumentError, "Invalid direction: #{direction.inspect}" if not [:out, :in, :both].include?(direction.to_sym)
|
120
|
+
raise ArgumentError, "Invalid association type: #{type.inspect} (valid value: :has_many and :has_one)" if not [:has_many, :has_one].include?(type.to_sym)
|
121
|
+
raise ArgumentError, "Invalid direction: #{direction.inspect} (valid value: :out, :in, and :both)" if not [:out, :in, :both].include?(direction.to_sym)
|
122
122
|
end
|
123
123
|
|
124
124
|
def validate_option_combinations(options)
|
@@ -101,10 +101,9 @@ module Neo4j::ActiveNode
|
|
101
101
|
Neo4j::Node.load(key.to_i)
|
102
102
|
end
|
103
103
|
|
104
|
-
|
105
104
|
def id_property(name, conf = {})
|
105
|
+
@id_property_info = {name: name, type: conf}
|
106
106
|
TypeMethods.define_id_methods(self, name, conf)
|
107
|
-
|
108
107
|
constraint name, type: :unique
|
109
108
|
|
110
109
|
self.define_singleton_method(:find_by_id) do |key|
|
@@ -112,8 +111,11 @@ module Neo4j::ActiveNode
|
|
112
111
|
end
|
113
112
|
end
|
114
113
|
|
115
|
-
|
114
|
+
def id_property_info
|
115
|
+
@id_property_info ||= false
|
116
|
+
end
|
116
117
|
|
118
|
+
end
|
117
119
|
end
|
118
120
|
|
119
121
|
end
|
@@ -9,6 +9,7 @@ module Neo4j
|
|
9
9
|
WRAPPED_CLASSES = []
|
10
10
|
class InvalidQueryError < StandardError; end
|
11
11
|
class RecordNotFound < StandardError; end
|
12
|
+
class InvalidParameterError < StandardError; end
|
12
13
|
|
13
14
|
# @return the labels
|
14
15
|
# @see Neo4j-core
|
@@ -71,12 +72,33 @@ module Neo4j
|
|
71
72
|
|
72
73
|
# Returns the last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs.
|
73
74
|
def last
|
74
|
-
self.query_as(:n).order('ID(n) DESC').
|
75
|
+
self.query_as(:n).limit(1).order('ID(n) DESC').pluck(:n).first
|
75
76
|
end
|
76
77
|
|
77
78
|
# @return [Fixnum] number of nodes of this class
|
78
|
-
def count
|
79
|
-
|
79
|
+
def count(distinct = nil)
|
80
|
+
raise(InvalidParameterError, ':count accepts `distinct` or nil as a parameter') unless distinct.nil? || distinct == :distinct
|
81
|
+
q = distinct.nil? ? "n" : "DISTINCT n"
|
82
|
+
self.query_as(:n).return("count(#{q}) AS count").first.count
|
83
|
+
end
|
84
|
+
alias_method :size, :count
|
85
|
+
alias_method :length, :count
|
86
|
+
|
87
|
+
def empty?
|
88
|
+
!self.exists?
|
89
|
+
end
|
90
|
+
alias_method :blank?, :empty?
|
91
|
+
|
92
|
+
def include?(other)
|
93
|
+
raise(InvalidParameterError, ':include? only accepts nodes') unless other.respond_to?(:neo_id)
|
94
|
+
self.query_as(:n).where("ID(n) = #{other.neo_id}").return("count(n) AS count").first.count > 0
|
95
|
+
end
|
96
|
+
|
97
|
+
def exists?(node_id=nil)
|
98
|
+
raise(InvalidParameterError, ':exists? only accepts neo_ids') unless node_id.is_a?(Integer) || node_id.nil?
|
99
|
+
start_q = self.query_as(:n)
|
100
|
+
end_q = node_id.nil? ? start_q : start_q.where("ID(n) = #{node_id}")
|
101
|
+
end_q.return("COUNT(n) AS count").first.count > 0
|
80
102
|
end
|
81
103
|
|
82
104
|
# Returns the object with the specified neo4j id.
|
@@ -147,7 +169,7 @@ module Neo4j
|
|
147
169
|
end
|
148
170
|
|
149
171
|
def index?(index_def)
|
150
|
-
mapped_label.indexes[:property_keys].include?(index_def)
|
172
|
+
mapped_label.indexes[:property_keys].include?([index_def])
|
151
173
|
end
|
152
174
|
|
153
175
|
# @return [Array{Symbol}] all the labels that this class has
|
@@ -157,7 +179,7 @@ module Neo4j
|
|
157
179
|
|
158
180
|
# @return [Symbol] the label that this class has which corresponds to a Ruby class
|
159
181
|
def mapped_label_name
|
160
|
-
@_label_name || self.to_s.to_sym
|
182
|
+
@_label_name || (self.name.nil? ? object_id.to_s.to_sym : self.name.to_sym)
|
161
183
|
end
|
162
184
|
|
163
185
|
# @return [Neo4j::Label] the label for this class
|
@@ -4,6 +4,7 @@ class Neo4j::Node
|
|
4
4
|
# this is a plugin in the neo4j-core so that the Ruby wrapper will be wrapped around the Neo4j::Node objects
|
5
5
|
def wrapper
|
6
6
|
most_concrete_class = sorted_wrapper_classes
|
7
|
+
return self unless most_concrete_class
|
7
8
|
wrapped_node = most_concrete_class.new
|
8
9
|
wrapped_node.init_on_load(self, self.props)
|
9
10
|
wrapped_node
|
@@ -1,19 +1,21 @@
|
|
1
1
|
module Neo4j
|
2
2
|
module ActiveNode
|
3
3
|
module Query
|
4
|
-
|
4
|
+
class InvalidParameterError < StandardError; end
|
5
5
|
class QueryProxy
|
6
|
+
|
6
7
|
include Enumerable
|
7
8
|
|
8
9
|
def initialize(model, association = nil, options = {})
|
9
10
|
@model = model
|
10
11
|
@association = association
|
12
|
+
@context = options.delete(:context)
|
11
13
|
@options = options
|
12
14
|
@node_var = options[:node]
|
13
15
|
@rel_var = options[:rel] || _rel_chain_var
|
14
16
|
@session = options[:session]
|
15
17
|
@chain = []
|
16
|
-
@params = {}
|
18
|
+
@params = options[:query_proxy] ? options[:query_proxy].instance_variable_get('@params') : {}
|
17
19
|
end
|
18
20
|
|
19
21
|
def each(node = true, rel = nil, &block)
|
@@ -75,7 +77,7 @@ module Neo4j
|
|
75
77
|
|
76
78
|
query = if @association
|
77
79
|
chain_var = _association_chain_var
|
78
|
-
label_string = @model && ":`#{@model.
|
80
|
+
label_string = @model && ":`#{@model.mapped_label_name}`"
|
79
81
|
(_association_query_start(chain_var) & _query_model_as(var)).match("#{chain_var}#{_association_arrow}(#{var}#{label_string})")
|
80
82
|
else
|
81
83
|
_query_model_as(var)
|
@@ -109,6 +111,15 @@ module Neo4j
|
|
109
111
|
raise "Can only create associations on associations" unless @association
|
110
112
|
other_nodes = [other_nodes].flatten
|
111
113
|
|
114
|
+
other_nodes.map! do |other_node|
|
115
|
+
case other_node
|
116
|
+
when Integer, String
|
117
|
+
@model.find(other_node)
|
118
|
+
else
|
119
|
+
other_node
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
112
123
|
raise ArgumentError, "Node must be of the association's class when model is specified" if @model && other_nodes.any? {|other_node| other_node.class != @model }
|
113
124
|
other_nodes.each do |other_node|
|
114
125
|
#Neo4j::Transaction.run do
|
@@ -116,9 +127,9 @@ module Neo4j
|
|
116
127
|
|
117
128
|
return false if @association.perform_callback(@options[:start_object], other_node, :before) == false
|
118
129
|
|
119
|
-
|
120
|
-
|
121
|
-
.
|
130
|
+
start_object = @options[:start_object]
|
131
|
+
_session.query(context: @options[:context])
|
132
|
+
.start(start: "node(#{start_object.neo_id})", end: "node(#{other_node.neo_id})")
|
122
133
|
.create("start#{_association_arrow(properties, true)}end").exec
|
123
134
|
|
124
135
|
@association.perform_callback(@options[:start_object], other_node, :after)
|
@@ -126,19 +137,53 @@ module Neo4j
|
|
126
137
|
end
|
127
138
|
end
|
128
139
|
|
140
|
+
#TODO: Get these out of here
|
141
|
+
def first
|
142
|
+
self.query_as(:n).limit(1).order('ID(n)').pluck(:n).first
|
143
|
+
end
|
144
|
+
|
145
|
+
def last
|
146
|
+
self.query_as(:n).limit(1).order('ID(n) DESC').pluck(:n).first
|
147
|
+
end
|
148
|
+
|
149
|
+
# @return [Fixnum] number of nodes of this class
|
150
|
+
def count(distinct = nil)
|
151
|
+
raise(InvalidParameterError, ':count accepts `distinct` or nil as a parameter') unless distinct.nil? || distinct == :distinct
|
152
|
+
q = distinct.nil? ? "n" : "DISTINCT n"
|
153
|
+
self.query_as(:n).return("count(#{q}) AS count").first.count
|
154
|
+
end
|
155
|
+
alias_method :size, :count
|
156
|
+
alias_method :length, :count
|
157
|
+
|
158
|
+
def empty?
|
159
|
+
!self.exists?
|
160
|
+
end
|
161
|
+
alias_method :blank?, :empty?
|
162
|
+
|
163
|
+
def include?(other)
|
164
|
+
raise(InvalidParameterError, ':include? only accepts nodes') unless other.respond_to?(:neo_id)
|
165
|
+
self.query_as(:n).where("ID(n) = #{other.neo_id}").return("count(n) AS count").first.count > 0
|
166
|
+
end
|
167
|
+
|
168
|
+
def exists?(node_id=nil)
|
169
|
+
raise(InvalidParameterError, ':exists? only accepts neo_ids') unless node_id.is_a?(Integer) || node_id.nil?
|
170
|
+
start_q = self.query_as(:n)
|
171
|
+
end_q = node_id.nil? ? start_q : start_q.where("ID(n) = #{node_id}")
|
172
|
+
end_q.return("COUNT(n) AS count").first.count > 0
|
173
|
+
end
|
174
|
+
|
129
175
|
# QueryProxy objects act as a representation of a model at the class level so we pass through calls
|
130
176
|
# This allows us to define class functions for reusable query chaining or for end-of-query aggregation/summarizing
|
131
177
|
def method_missing(method_name, *args)
|
132
178
|
if @model && @model.respond_to?(method_name)
|
133
|
-
|
134
|
-
result = @model.send(method_name, *args)
|
135
|
-
@model.query_proxy = nil
|
136
|
-
result
|
179
|
+
call_class_method(method_name, *args)
|
137
180
|
else
|
138
181
|
super
|
139
182
|
end
|
140
183
|
end
|
141
184
|
|
185
|
+
attr_reader :context
|
186
|
+
|
142
187
|
protected
|
143
188
|
# Methods are underscored to prevent conflict with user class methods
|
144
189
|
|
@@ -153,12 +198,13 @@ module Neo4j
|
|
153
198
|
end
|
154
199
|
|
155
200
|
def _query_model_as(var)
|
156
|
-
if @model
|
201
|
+
match_arg = if @model
|
157
202
|
label = @model.respond_to?(:mapped_label_name) ? @model.mapped_label_name : @model
|
158
|
-
|
203
|
+
{var => label}
|
159
204
|
else
|
160
|
-
|
205
|
+
var
|
161
206
|
end
|
207
|
+
_session.query(context: @context).match(match_arg)
|
162
208
|
end
|
163
209
|
|
164
210
|
def _session
|
@@ -203,8 +249,17 @@ module Neo4j
|
|
203
249
|
:"rel#{_chain_level - 1}"
|
204
250
|
end
|
205
251
|
|
252
|
+
attr_writer :context
|
253
|
+
|
206
254
|
private
|
207
255
|
|
256
|
+
def call_class_method(method_name, *args)
|
257
|
+
@model.query_proxy = self
|
258
|
+
result = @model.send(method_name, *args)
|
259
|
+
@model.query_proxy = nil
|
260
|
+
result
|
261
|
+
end
|
262
|
+
|
208
263
|
def build_deeper_query_proxy(method, args)
|
209
264
|
self.dup.tap do |new_query|
|
210
265
|
args.each do |arg|
|
@@ -251,7 +306,7 @@ module Neo4j
|
|
251
306
|
end
|
252
307
|
|
253
308
|
def links_for_order_arg(arg)
|
254
|
-
[[:order, ->(v) { {v => arg} }]]
|
309
|
+
[[:order, ->(v) { arg.is_a?(String) ? arg : {v => arg} }]]
|
255
310
|
end
|
256
311
|
|
257
312
|
|
data/lib/neo4j/active_rel.rb
CHANGED
data/lib/neo4j/paginated.rb
CHANGED
@@ -10,7 +10,7 @@ module Neo4j
|
|
10
10
|
def self.create_from(source, page, per_page)
|
11
11
|
#partial = source.drop((page-1) * per_page).first(per_page)
|
12
12
|
partial = source.skip(page-1).limit(per_page)
|
13
|
-
Paginated.new(partial, source.count, page)
|
13
|
+
Paginated.new(partial, source.instance_variable_get(:@model).count, page)
|
14
14
|
end
|
15
15
|
|
16
16
|
delegate :each, :to => :items
|
data/lib/neo4j/railtie.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/notifications'
|
2
|
+
|
1
3
|
module Neo4j
|
2
4
|
class Railtie < ::Rails::Railtie
|
3
5
|
config.neo4j = ActiveSupport::OrderedOptions.new
|
@@ -66,6 +68,16 @@ module Neo4j
|
|
66
68
|
Neo4j::Railtie.open_neo4j_session(session_opts)
|
67
69
|
end
|
68
70
|
Neo4j::Config.setup.merge!(cfg.to_hash)
|
71
|
+
|
72
|
+
clear = "\e[0m"
|
73
|
+
red = "\e[31m"
|
74
|
+
yellow = "\e[33m"
|
75
|
+
cyan = "\e[36m"
|
76
|
+
|
77
|
+
ActiveSupport::Notifications.subscribe('neo4j.cypher_query') do |name, start, finish, id, payload|
|
78
|
+
ms = (finish - start) * 1000
|
79
|
+
Rails.logger.info " #{cyan}#{payload[:context]}#{clear} #{yellow}#{ms.round}ms#{clear} #{payload[:cypher]}" + (payload[:params].size > 0 ? ' | ' + payload[:params].inspect : '')
|
80
|
+
end
|
69
81
|
end
|
70
82
|
end
|
71
83
|
end
|
data/lib/neo4j/shared.rb
CHANGED
@@ -7,8 +7,6 @@ module Neo4j
|
|
7
7
|
include ActiveModel::Serializers::Xml
|
8
8
|
include ActiveModel::Serializers::JSON
|
9
9
|
|
10
|
-
include Neo4j::Shared::Identity
|
11
|
-
|
12
10
|
module ClassMethods
|
13
11
|
def neo4j_session_name (name)
|
14
12
|
@neo4j_session_name = name
|
@@ -18,7 +16,7 @@ module Neo4j
|
|
18
16
|
if @neo4j_session_name
|
19
17
|
Neo4j::Session.named(@neo4j_session_name) || raise("#{self.name} is configured to use a neo4j session named #{@neo4j_session_name}, but no such session is registered with Neo4j::Session")
|
20
18
|
else
|
21
|
-
Neo4j::Session.current
|
19
|
+
Neo4j::Session.current!
|
22
20
|
end
|
23
21
|
end
|
24
22
|
end
|
data/lib/neo4j/version.rb
CHANGED
@@ -9,7 +9,7 @@ class Neo4j::Generators::ModelGenerator < Neo4j::Generators::Base #:nodoc:
|
|
9
9
|
class_option :parent, :type => :string, :desc => "The parent class for the generated model"
|
10
10
|
class_option :indices, :type => :array, :desc => "The properties which should be indexed"
|
11
11
|
class_option :has_one, :type => :array, :desc => "A list of has_one relationships"
|
12
|
-
class_option :
|
12
|
+
class_option :has_many, :type => :array, :desc => "A list of has_many relationships"
|
13
13
|
|
14
14
|
def create_model_file
|
15
15
|
template "model.erb", File.join('app/models', "#{singular_name}.rb")
|
@@ -24,14 +24,14 @@ class Neo4j::Generators::ModelGenerator < Neo4j::Generators::Base #:nodoc:
|
|
24
24
|
options[:timestamps]
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
options[:
|
27
|
+
def has_many?
|
28
|
+
options[:has_many]
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def has_many_statements
|
32
32
|
txt = ""
|
33
|
-
options[:
|
34
|
-
txt << has_x('
|
33
|
+
options[:has_many].each do |key|
|
34
|
+
txt << has_x('has_many', key)
|
35
35
|
end
|
36
36
|
txt
|
37
37
|
end
|
@@ -79,4 +79,4 @@ class Neo4j::Generators::ModelGenerator < Neo4j::Generators::Base #:nodoc:
|
|
79
79
|
end
|
80
80
|
|
81
81
|
hook_for :test_framework
|
82
|
-
end
|
82
|
+
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
class <%= class_name %> <%= parent? ? "#{options[:parent].classify}" : "" %>
|
2
|
-
|
2
|
+
include Neo4j::ActiveNode
|
3
3
|
<% attributes.each do |attribute| -%>
|
4
|
-
|
5
|
-
<%= index_fragment(attribute.name) %>
|
4
|
+
property :<%= attribute.name %><%= ", type: #{attribute.type_class}" unless attribute.type_class == 'any' %><%= "\n " + index_fragment if index_fragment = index_fragment(attribute.name) %>
|
6
5
|
<% end -%>
|
7
|
-
<%=
|
6
|
+
<%= has_many_statements if has_many? -%>
|
8
7
|
<%= has_one_statements if has_one? -%>
|
9
8
|
|
10
9
|
<%= timestamp_statements if timestamps? -%>
|
11
|
-
end
|
10
|
+
end
|
data/neo4j.gemspec
CHANGED
@@ -34,7 +34,7 @@ It comes included with the Apache Lucene document database.
|
|
34
34
|
s.add_dependency("activesupport", "~> 4")
|
35
35
|
s.add_dependency("railties", "~> 4")
|
36
36
|
s.add_dependency('active_attr', "~> 0.8")
|
37
|
-
s.add_dependency("neo4j-core", "
|
37
|
+
s.add_dependency("neo4j-core", "~> 3.0.0.rc.4")
|
38
38
|
|
39
39
|
if RUBY_PLATFORM =~ /java/
|
40
40
|
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.0.
|
4
|
+
version: 3.0.0.rc.2
|
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-08-
|
11
|
+
date: 2014-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: orm_adapter
|
@@ -84,16 +84,16 @@ dependencies:
|
|
84
84
|
name: neo4j-core
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.0.0.
|
89
|
+
version: 3.0.0.rc.4
|
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.0.
|
96
|
+
version: 3.0.0.rc.4
|
97
97
|
description: "You can think of Neo4j as a high-performance graph engine with all the
|
98
98
|
features of a mature and robust database.\nThe programmer works with an object-oriented,
|
99
99
|
flexible network structure rather than with strict and static tables \nyet enjoys
|