neo4j 3.0.0.alpha.11 → 3.0.0.rc.2
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/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
|