neo4j 3.0.0.rc.2 → 3.0.0.rc.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 489ffa77b2c5a647e44d217825a68af5fbeb13cf
4
- data.tar.gz: 1ef50669eb2cbca0b88a1f7f1143ec5e56740527
3
+ metadata.gz: d2a5f927c44fc68a95721d7feca406c21a6f71d8
4
+ data.tar.gz: e53647f9c20b8d48040bcab9bc28ce300287f5a8
5
5
  SHA512:
6
- metadata.gz: f275a297c3b4c2f93e2c655ad6cdaf3317f27ad9aa241959251558a1eb6202ec5e74b82e5c67684581df946b10be5209761dbd9d6826a0514d2afb6b235de015
7
- data.tar.gz: b3e869867b335969ff6e4357e39f8796d894c6adedbafa426aa4fe0c30f67d261e4df8a31d00815b0fc8ba08888b32d39767b29ada56bb5ea3ed7f84fa5ba55e
6
+ metadata.gz: 542621a0655dbae24993c9a36c5e39a37930c08fc023acb16bb907622bcd953f0a02662a4750174f851e6144e4fef62b9c4abc4326f3a954b93c4811e13402d7
7
+ data.tar.gz: 0ebd9085b56e5a50a01f0d01994dff9f2219f1744f5e6e053717c12d787243c3d3e94a60dcd7b9623f24c08f3ba886acd454e8551518f22b083d19b387ef2738
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ == 3.0.0.rc.3
2
+ * thread safety improvements
3
+ * scope and general refactoring
4
+ * Added ability to create relationships on init (persisted on save)
5
+
1
6
  == 3.0.0.rc.2
2
7
  * Use newer neo4j-core release
3
8
 
data/Gemfile CHANGED
@@ -6,7 +6,7 @@ gemspec
6
6
  #gem 'neo4j-core', :git => 'https://github.com/andreasronge/neo4j-core.git'
7
7
  #gem 'orm_adapter', :path => '../orm_adapter'
8
8
 
9
- gem 'coveralls', require: false
9
+ #gem 'coveralls', require: false
10
10
 
11
11
  group 'development' do
12
12
  gem 'pry'
@@ -16,6 +16,7 @@ group 'development' do
16
16
  end
17
17
 
18
18
  group 'test' do
19
+ gem "codeclimate-test-reporter", require: nil
19
20
  gem "rspec", '~> 2.0'
20
21
  # gem 'rspec-its' instead of its in rspec 3
21
22
  gem "its"
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # Welcome to Neo4j.rb [![Build Status](https://secure.travis-ci.org/andreasronge/neo4j.png?branch=master)](http://travis-ci.org/andreasronge/neo4j) [![Coverage Status](https://coveralls.io/repos/andreasronge/neo4j/badge.png)](https://coveralls.io/r/andreasronge/neo4j) [![Code Climate](https://codeclimate.com/github/andreasronge/neo4j.png)](https://codeclimate.com/github/andreasronge/neo4j)
1
+ # Welcome to Neo4j.rb [![Build Status](https://secure.travis-ci.org/neo4jrb/neo4j.png?branch=master)](http://travis-ci.org/neo4jrb/neo4j) [![Test Coverage](https://codeclimate.com/github/neo4jrb/neo4j/badges/coverage.svg)](https://codeclimate.com/github/neo4jrb/neo4j) [![Code Climate](https://codeclimate.com/github/neo4jrb/neo4j.png)](https://codeclimate.com/github/andreasronge/neo4j)
2
2
 
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.
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/neo4jrb/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
- * [Wiki](https://github.com/andreasronge/neo4j/wiki/Neo4j.rb-v3-Introduction)
7
+ * [Wiki](https://github.com/neo4jrb/neo4j/wiki/Neo4j.rb-v3-Introduction)
8
8
 
9
9
  ## Documentation Old stable version 2.x
10
10
 
11
- * [README](https://github.com/andreasronge/neo4j/tree/2.x)
12
- * [Wiki](https://github.com/andreasronge/neo4j/wiki/Neo4j%3A%3ARails-Introduction)
11
+ * [README](https://github.com/neo4jrb/neo4j/tree/2.x)
12
+ * [Wiki](https://github.com/neo4jrb/neo4j/wiki/Neo4j%3A%3ARails-Introduction)
13
13
 
14
14
  ## Support
15
15
 
@@ -31,7 +31,6 @@ Pull request with high test coverage and good [code climate](https://codeclimate
31
31
  ## License
32
32
 
33
33
  * Neo4j.rb - MIT, see the [LICENSE](http://github.com/andreasronge/neo4j/tree/master/LICENSE).
34
- * Lucene - Apache, see the [Lucene Documentation](http://lucene.apache.org/java/docs/features.html).
35
34
  * Neo4j - Dual free software/commercial license, see [Licensing Guide](http://www.neo4j.org/learn/licensing).
36
35
 
37
36
  **Notice:** There are different licenses for the `neo4j-community`, `neo4j-advanced`, and `neo4j-enterprise` jar gems. Only the `neo4j-community` gem is required by default.
data/lib/neo4j.rb CHANGED
@@ -38,6 +38,8 @@ require 'neo4j/active_rel/query'
38
38
  require 'neo4j/active_rel/related_node'
39
39
  require 'neo4j/active_rel'
40
40
 
41
+ require 'neo4j/active_node/query_methods'
42
+ require 'neo4j/active_node/query/query_proxy_methods'
41
43
  require 'neo4j/active_node/labels'
42
44
  require 'neo4j/active_node/id_property'
43
45
  require 'neo4j/active_node/callbacks'
@@ -51,6 +53,7 @@ require 'neo4j/active_node/has_n/association'
51
53
  require 'neo4j/active_node/query/query_proxy'
52
54
  require 'neo4j/active_node/query'
53
55
  require 'neo4j/active_node/serialized_properties'
56
+ require 'neo4j/active_node/scope'
54
57
  require 'neo4j/active_node'
55
58
 
56
59
  require 'neo4j/active_node/orm_adapter'
@@ -37,6 +37,7 @@ module Neo4j
37
37
  include Neo4j::ActiveNode::Labels
38
38
  include Neo4j::ActiveNode::Rels
39
39
  include Neo4j::ActiveNode::HasN
40
+ include Neo4j::ActiveNode::Scope
40
41
 
41
42
  def neo4j_obj
42
43
  _persisted_obj || raise("Tried to access native neo4j object on a non persisted object")
@@ -59,13 +59,16 @@ module HasN
59
59
  end}, __FILE__, __LINE__)
60
60
 
61
61
  instance_eval(%Q{
62
- def #{name}(node = nil, rel = nil)
63
- context = (self.query_proxy && self.query_proxy.context ? self.query_proxy.context : '#{self.name}') + '##{name}'
62
+ def #{name}(node = nil, rel = nil, proxy_obj = nil)
63
+ query_proxy = proxy_obj || Neo4j::ActiveNode::Query::QueryProxy.new(#{self.name}, nil, {
64
+ session: self.neo4j_session, query_proxy: nil, context: '#{self.name}' + '##{name}'
65
+ })
66
+ context = (query_proxy && query_proxy.context ? query_proxy.context : '#{self.name}') + '##{name}'
64
67
  Neo4j::ActiveNode::Query::QueryProxy.new(#{target_class_name},
65
68
  @associations[#{name.inspect}],
66
69
  {
67
70
  session: self.neo4j_session,
68
- query_proxy: self.query_proxy,
71
+ query_proxy: query_proxy,
69
72
  node: node,
70
73
  rel: rel,
71
74
  context: context
@@ -110,9 +113,9 @@ module HasN
110
113
  {session: self.neo4j_session}.merge(options))
111
114
  end
112
115
 
113
- def #{name}(node = nil, rel = nil)
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)
116
+ def #{name}(node = nil, rel = nil, query_proxy = nil)
117
+ context = (query_proxy && query_proxy.context ? query_proxy.context : '#{self.name}') + '##{name}'
118
+ #{name}_query_proxy(query_proxy: query_proxy, node: node, rel: rel, context: context)
116
119
  end}, __FILE__, __LINE__)
117
120
  end
118
121
 
@@ -2,12 +2,11 @@ module Neo4j::ActiveNode::Initialize
2
2
  extend ActiveSupport::Concern
3
3
  include Neo4j::TypeConverters
4
4
 
5
- attr_reader :_persisted_obj
6
-
7
5
  # called when loading the node from the database
8
6
  # @param [Neo4j::Node] persisted_node the node this class wraps
9
7
  # @param [Hash] properties of the persisted node.
10
8
  def init_on_load(persisted_node, properties)
9
+ @_association_attributes = self.class.extract_association_attributes!(properties)
11
10
  @_persisted_obj = persisted_node
12
11
  changed_attributes && changed_attributes.clear
13
12
  @attributes = attributes.merge(properties.stringify_keys)
@@ -9,7 +9,6 @@ module Neo4j
9
9
  WRAPPED_CLASSES = []
10
10
  class InvalidQueryError < StandardError; end
11
11
  class RecordNotFound < StandardError; end
12
- class InvalidParameterError < StandardError; end
13
12
 
14
13
  # @return the labels
15
14
  # @see Neo4j-core
@@ -60,46 +59,14 @@ module Neo4j
60
59
  end
61
60
 
62
61
  module ClassMethods
62
+ include Neo4j::ActiveNode::QueryMethods
63
+
63
64
  # Find all nodes/objects of this class
64
65
  def all
65
66
  self.query_as(:n).pluck(:n)
66
67
  end
67
68
 
68
- # Returns the first node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs.
69
- def first
70
- self.query_as(:n).limit(1).order('ID(n)').pluck(:n).first
71
- end
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.
74
- def last
75
- self.query_as(:n).limit(1).order('ID(n) DESC').pluck(:n).first
76
- end
77
-
78
- # @return [Fixnum] number of nodes of this class
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
69
 
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
102
- end
103
70
 
104
71
  # Returns the object with the specified neo4j id.
105
72
  # @param [String,Fixnum] id of node to find
@@ -13,6 +13,8 @@ module Neo4j::ActiveNode
13
13
  properties = convert_properties_to :db, props
14
14
  node = _create_node(properties)
15
15
  init_on_load(node, node.props)
16
+ send_props(@relationship_props) if @relationship_props
17
+ @relationship_props = nil
16
18
  # Neo4j::IdentityMap.add(node, self)
17
19
  # write_changed_relationships
18
20
  true
@@ -3,15 +3,19 @@ module Neo4j::ActiveNode
3
3
  extend ActiveSupport::Concern
4
4
  include Neo4j::Shared::Property
5
5
 
6
+ def initialize(attributes={}, options={})
7
+ super(attributes, options)
8
+
9
+ send_props(@relationship_props) if persisted? and not @relationship_props.nil?
10
+ end
11
+
6
12
  module ClassMethods
7
13
 
8
14
  # Extracts keys from attributes hash which are relationships of the model
9
15
  # TODO: Validate separately that relationships are getting the right values? Perhaps also store the values and persist relationships on save?
10
16
  def extract_association_attributes!(attributes)
11
- attributes.keys.inject({}) do |association_props, key|
17
+ attributes.keys.each_with_object({}) do |key, association_props|
12
18
  association_props[key] = attributes.delete(key) if self.has_association?(key)
13
-
14
- association_props
15
19
  end
16
20
  end
17
21
  end
@@ -23,7 +23,7 @@ module Neo4j
23
23
  module ClassMethods
24
24
  include Enumerable
25
25
 
26
- attr_writer :query_proxy
26
+ #attr_writer :query_proxy
27
27
 
28
28
  def each
29
29
  self.query_as(:n).pluck(:n).each {|o| yield o }
@@ -49,7 +49,7 @@ module Neo4j
49
49
  end
50
50
 
51
51
  def query_proxy(options = {})
52
- @query_proxy || Neo4j::ActiveNode::Query::QueryProxy.new(self, nil, options)
52
+ Neo4j::ActiveNode::Query::QueryProxy.new(self, nil, options)
53
53
  end
54
54
 
55
55
  def as(node_var)
@@ -1,10 +1,10 @@
1
1
  module Neo4j
2
2
  module ActiveNode
3
3
  module Query
4
- class InvalidParameterError < StandardError; end
5
4
  class QueryProxy
6
5
 
7
6
  include Enumerable
7
+ include Neo4j::ActiveNode::Query::QueryProxyMethods
8
8
 
9
9
  def initialize(model, association = nil, options = {})
10
10
  @model = model
@@ -18,13 +18,17 @@ module Neo4j
18
18
  @params = options[:query_proxy] ? options[:query_proxy].instance_variable_get('@params') : {}
19
19
  end
20
20
 
21
+ def identity
22
+ @node_var || :result
23
+ end
24
+
21
25
  def each(node = true, rel = nil, &block)
22
26
  if node && rel
23
- self.pluck((@node_var || :result), @rel_var).each do |obj, rel|
27
+ self.pluck(identity, @rel_var).each do |obj, rel|
24
28
  yield obj, rel
25
29
  end
26
30
  else
27
- pluck_this = !rel ? (@node_var || :result) : @rel_var
31
+ pluck_this = !rel ? identity : @rel_var
28
32
  self.pluck(pluck_this).each do |obj|
29
33
  yield obj
30
34
  end
@@ -68,13 +72,12 @@ module Neo4j
68
72
 
69
73
  # Like calling #query_as, but for when you don't care about the variable name
70
74
  def query
71
- query_as(@node_var || :result)
75
+ query_as(identity)
72
76
  end
73
77
 
74
78
  # Build a Neo4j::Core::Query object for the QueryProxy
75
79
  def query_as(var)
76
80
  var = @node_var if @node_var
77
-
78
81
  query = if @association
79
82
  chain_var = _association_chain_var
80
83
  label_string = @model && ":`#{@model.mapped_label_name}`"
@@ -111,14 +114,14 @@ module Neo4j
111
114
  raise "Can only create associations on associations" unless @association
112
115
  other_nodes = [other_nodes].flatten
113
116
 
114
- other_nodes.map! do |other_node|
117
+ other_nodes = other_nodes.map do |other_node|
115
118
  case other_node
116
119
  when Integer, String
117
120
  @model.find(other_node)
118
121
  else
119
122
  other_node
120
123
  end
121
- end
124
+ end.compact
122
125
 
123
126
  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 }
124
127
  other_nodes.each do |other_node|
@@ -137,41 +140,6 @@ module Neo4j
137
140
  end
138
141
  end
139
142
 
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
-
175
143
  # QueryProxy objects act as a representation of a model at the class level so we pass through calls
176
144
  # This allows us to define class functions for reusable query chaining or for end-of-query aggregation/summarizing
177
145
  def method_missing(method_name, *args)
@@ -254,9 +222,8 @@ module Neo4j
254
222
  private
255
223
 
256
224
  def call_class_method(method_name, *args)
257
- @model.query_proxy = self
225
+ args[2] = self
258
226
  result = @model.send(method_name, *args)
259
- @model.query_proxy = nil
260
227
  result
261
228
  end
262
229
 
@@ -0,0 +1,60 @@
1
+ module Neo4j
2
+ module ActiveNode
3
+ module Query
4
+ module QueryProxyMethods
5
+ class InvalidParameterError < StandardError; end
6
+
7
+ def query_with_target(target, &block)
8
+ target = target.nil? ? identity : target
9
+ block.yield(target)
10
+ end
11
+
12
+ def first(target=nil)
13
+ query_with_target(target) { |target| first_and_last("ID(#{target})", target) }
14
+ end
15
+
16
+ def last(target=nil)
17
+ query_with_target(target) { |target| first_and_last("ID(#{target}) DESC", target) }
18
+ end
19
+
20
+ def first_and_last(order, target)
21
+ self.order(order).limit(1).pluck(target).first
22
+ end
23
+
24
+ # @return [Fixnum] number of nodes of this class
25
+ def count(distinct=nil, target=nil)
26
+ raise(InvalidParameterError, ':count accepts `distinct` or nil as a parameter') unless distinct.nil? || distinct == :distinct
27
+ query_with_target(target) do |target|
28
+ q = distinct.nil? ? target : "DISTINCT #{target}"
29
+ self.query.return("count(#{q}) AS count").first.count
30
+ end
31
+ end
32
+
33
+ alias_method :size, :count
34
+ alias_method :length, :count
35
+
36
+ def empty?(target=nil)
37
+ query_with_target(target) { |target| !self.exists?(nil, target) }
38
+ end
39
+
40
+ alias_method :blank?, :empty?
41
+
42
+ def include?(other, target=nil)
43
+ raise(InvalidParameterError, ':include? only accepts nodes') unless other.respond_to?(:neo_id)
44
+ query_with_target(target) do |target|
45
+ self.where("ID(#{target}) = {other_node_id}").params(other_node_id: other.neo_id).query.return("count(#{target}) AS count").first.count > 0
46
+ end
47
+ end
48
+
49
+ def exists?(node_id=nil, target=nil)
50
+ raise(InvalidParameterError, ':exists? only accepts neo_ids') unless node_id.is_a?(Integer) || node_id.nil?
51
+ query_with_target(target) do |target|
52
+ start_q = self.query
53
+ end_q = node_id.nil? ? start_q : start_q.where("ID(#{target}) = #{node_id}")
54
+ end_q.return("COUNT(#{target}) AS count").first.count > 0
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,47 @@
1
+ module Neo4j
2
+ module ActiveNode
3
+ module QueryMethods
4
+ class InvalidParameterError < StandardError; end
5
+
6
+ def exists?(node_id=nil)
7
+ raise(InvalidParameterError, ':exists? only accepts neo_ids') unless node_id.is_a?(Integer) || node_id.nil?
8
+ start_q = self.query_as(:n)
9
+ end_q = node_id.nil? ? start_q : start_q.where("ID(n) = #{node_id}")
10
+ end_q.return("COUNT(n) AS count").first.count > 0
11
+ end
12
+
13
+ # Returns the first node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs.
14
+ def first
15
+ self.query_as(:n).limit(1).order('ID(n)').pluck(:n).first
16
+ end
17
+
18
+ # Returns the last node of this class, sorted by ID. Note that this may not be the first node created since Neo4j recycles IDs.
19
+ def last
20
+ self.query_as(:n).limit(1).order('ID(n) DESC').pluck(:n).first
21
+ end
22
+
23
+ # @return [Fixnum] number of nodes of this class
24
+ def count(distinct = nil)
25
+ raise(InvalidParameterError, ':count accepts `distinct` or nil as a parameter') unless distinct.nil? || distinct == :distinct
26
+ q = distinct.nil? ? "n" : "DISTINCT n"
27
+ self.query_as(:n).return("count(#{q}) AS count").first.count
28
+ end
29
+
30
+ alias_method :size, :count
31
+ alias_method :length, :count
32
+
33
+ def empty?
34
+ !self.exists?
35
+ end
36
+
37
+ alias_method :blank?, :empty?
38
+
39
+ def include?(other)
40
+ raise(InvalidParameterError, ':include? only accepts nodes') unless other.respond_to?(:neo_id)
41
+ self.query_as(:n).where("ID(n) = #{other.neo_id}").return("count(n) AS count").first.count > 0
42
+ end
43
+
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,87 @@
1
+ module Neo4j::ActiveNode
2
+ module Scope
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+
7
+ # Similar to ActiveRecord scope
8
+ #
9
+ # @example without argument
10
+ # class Person
11
+ # include Neo4j::ActiveNode
12
+ # property :name
13
+ # property :score
14
+ # has_many :out, :friends, model_class: self
15
+ # scope :top_students, -> { where(score: 42)}") }
16
+ # end
17
+ # Person.top_students.to_a
18
+ # a_person.friends.top_students.to_a
19
+ # a_person.friends.friends.top_students.to_a
20
+ # a_person.friends.top_students.friends.to_a
21
+ #
22
+ # @example Argument for scopes
23
+ # Person.scope :level, ->(num) { where(level_num: num)}
24
+ #
25
+ # @example Argument as a cypher identifier
26
+ # class Person
27
+ # include Neo4j::ActiveNode
28
+ # property :name
29
+ # property :score
30
+ # has_many :out, :friends, model_class: self
31
+ # scope :great_students, ->(identifier) { where("#{identifier}.score > 41") }
32
+ # end
33
+ # Person.as(:all_people).great_students(:all_people).to_a
34
+ #
35
+ # @see http://guides.rubyonrails.org/active_record_querying.html#scopes
36
+ def scope(name, proc)
37
+ _scope[name.to_sym] = proc
38
+
39
+ module_eval(%Q{
40
+ def #{name}(query_params=nil, _=nil, query_proxy=nil)
41
+ eval_context = ScopeEvalContext.new(self, query_proxy || self.class.query_proxy)
42
+ proc = self.class._scope[:"#{name}"]
43
+ self.class._call_scope_context(eval_context, query_params, proc)
44
+ end
45
+ }, __FILE__, __LINE__)
46
+
47
+ instance_eval(%Q{
48
+ def #{name}(query_params=nil, _=nil, query_proxy=nil)
49
+ eval_context = ScopeEvalContext.new(self, query_proxy || self.query_proxy)
50
+ proc = _scope[:"#{name}"]
51
+ _call_scope_context(eval_context, query_params, proc)
52
+ end
53
+ }, __FILE__, __LINE__)
54
+ end
55
+
56
+
57
+
58
+ def _scope
59
+ @_scope ||= {}
60
+ end
61
+
62
+ def _call_scope_context(eval_context, query_params, proc)
63
+ if proc.arity == 1
64
+ eval_context.instance_exec(query_params,&proc)
65
+ else
66
+ eval_context.instance_exec(&proc)
67
+ end
68
+ end
69
+
70
+
71
+ end
72
+
73
+ class ScopeEvalContext
74
+ def initialize(target, query_proxy)
75
+ @query_proxy = query_proxy
76
+ @target = target
77
+ end
78
+
79
+ Neo4j::ActiveNode::Query::QueryProxy::METHODS.each do |method|
80
+ module_eval(%Q{
81
+ def #{method}(params={})
82
+ (@query_proxy || @target).#{method}(params)
83
+ end}, __FILE__, __LINE__)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -27,4 +27,4 @@ module Neo4j::ActiveRel
27
27
  self
28
28
  end
29
29
  end
30
- end
30
+ end
@@ -30,7 +30,7 @@ module Neo4j::ActiveRel
30
30
  create_magic_properties
31
31
  set_timestamps
32
32
  properties = convert_properties_to :db, props
33
- rel = _create_rel(properties)
33
+ rel = _create_rel(from_node, to_node, properties)
34
34
  init_on_load(rel, to_node, from_node, @rel_type)
35
35
  true
36
36
  end
@@ -69,8 +69,7 @@ module Neo4j::ActiveRel
69
69
  end
70
70
  end
71
71
 
72
- def _create_rel(*args)
73
- session = self.class.neo4j_session
72
+ def _create_rel(from_node, to_node, *args)
74
73
  props = self.class.default_property_values(self)
75
74
  props.merge!(args[0]) if args[0].is_a?(Hash)
76
75
  set_classname(props)
@@ -19,15 +19,19 @@ module Neo4j::ActiveRel
19
19
  self.class._type
20
20
  end
21
21
 
22
+ def initialize(attributes={}, options={})
23
+ super(attributes, options)
24
+
25
+ send_props(@relationship_props) unless @relationship_props.nil?
26
+ end
27
+
22
28
  module ClassMethods
23
29
 
24
30
  # Extracts keys from attributes hash which are relationships of the model
25
31
  # TODO: Validate separately that relationships are getting the right values? Perhaps also store the values and persist relationships on save?
26
32
  def extract_association_attributes!(attributes)
27
- attributes.keys.inject({}) do |relationship_props, key|
28
- relationship_props[key] = attributes.delete(key) if key == :from_node || key == :to_node
29
-
30
- relationship_props
33
+ attributes.keys.each_with_object({}) do |key, relationship_props|
34
+ relationship_props[key] = attributes.delete(key) if [:from_node, :to_node].include?(key)
31
35
  end
32
36
  end
33
37
 
@@ -15,13 +15,16 @@ module Neo4j::Shared
15
15
 
16
16
  ILLEGAL_PROPS = %w[from_node to_node start_node end_node]
17
17
 
18
+ attr_reader :_persisted_obj
19
+
18
20
  def initialize(attributes={}, options={})
19
21
  attributes = process_attributes(attributes)
20
- relationship_props = self.class.extract_association_attributes!(attributes)
22
+ @relationship_props = self.class.extract_association_attributes!(attributes)
21
23
  writer_method_props = extract_writer_methods!(attributes)
22
24
  validate_attributes!(attributes)
23
25
  send_props(writer_method_props) unless writer_method_props.nil?
24
- send_props(relationship_props) unless relationship_props.nil?
26
+
27
+ @_persisted_obj = nil
25
28
 
26
29
  super(attributes, options)
27
30
  end
data/lib/neo4j/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Neo4j
2
- VERSION = "3.0.0.rc.2"
2
+ VERSION = "3.0.0.rc.3"
3
3
  end
data/neo4j.gemspec CHANGED
@@ -11,15 +11,12 @@ Gem::Specification.new do |s|
11
11
 
12
12
  s.authors = "Andreas Ronge"
13
13
  s.email = 'andreas.ronge@gmail.com'
14
- s.homepage = "http://github.com/andreasronge/neo4j/tree"
14
+ s.homepage = "https://github.com/andreasronge/neo4j/"
15
15
  s.rubyforge_project = 'neo4j'
16
16
  s.summary = "A graph database for Ruby"
17
17
  s.license = 'MIT'
18
18
  s.description = <<-EOF
19
- You can think of Neo4j as a high-performance graph engine with all the features of a mature and robust database.
20
- The programmer works with an object-oriented, flexible network structure rather than with strict and static tables
21
- yet enjoys all the benefits of a fully transactional, enterprise-strength database.
22
- It comes included with the Apache Lucene document database.
19
+ A Neo4j OGM for use in Ruby on Rails and Rack frameworks, intended as a complete replacement for ActiveRecord.
23
20
  EOF
24
21
 
25
22
  s.require_path = 'lib'
@@ -34,7 +31,7 @@ It comes included with the Apache Lucene document database.
34
31
  s.add_dependency("activesupport", "~> 4")
35
32
  s.add_dependency("railties", "~> 4")
36
33
  s.add_dependency('active_attr', "~> 0.8")
37
- s.add_dependency("neo4j-core", "~> 3.0.0.rc.4")
34
+ s.add_dependency("neo4j-core", "= 3.0.0.rc.4")
38
35
 
39
36
  if RUBY_PLATFORM =~ /java/
40
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.0.rc.2
4
+ version: 3.0.0.rc.3
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-27 00:00:00.000000000 Z
11
+ date: 2014-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: orm_adapter
@@ -84,21 +84,18 @@ 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
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
96
  version: 3.0.0.rc.4
97
- description: "You can think of Neo4j as a high-performance graph engine with all the
98
- features of a mature and robust database.\nThe programmer works with an object-oriented,
99
- flexible network structure rather than with strict and static tables \nyet enjoys
100
- all the benefits of a fully transactional, enterprise-strength database.\nIt comes
101
- included with the Apache Lucene document database.\n"
97
+ description: |
98
+ A Neo4j OGM for use in Ruby on Rails and Rack frameworks, intended as a complete replacement for ActiveRecord.
102
99
  email: andreas.ronge@gmail.com
103
100
  executables:
104
101
  - neo4j-jars
@@ -127,7 +124,10 @@ files:
127
124
  - lib/neo4j/active_node/property.rb
128
125
  - lib/neo4j/active_node/query.rb
129
126
  - lib/neo4j/active_node/query/query_proxy.rb
127
+ - lib/neo4j/active_node/query/query_proxy_methods.rb
128
+ - lib/neo4j/active_node/query_methods.rb
130
129
  - lib/neo4j/active_node/rels.rb
130
+ - lib/neo4j/active_node/scope.rb
131
131
  - lib/neo4j/active_node/serialized_properties.rb
132
132
  - lib/neo4j/active_node/validations.rb
133
133
  - lib/neo4j/active_rel.rb
@@ -155,7 +155,7 @@ files:
155
155
  - lib/rails/generators/neo4j/model/templates/model.erb
156
156
  - lib/rails/generators/neo4j_generator.rb
157
157
  - neo4j.gemspec
158
- homepage: http://github.com/andreasronge/neo4j/tree
158
+ homepage: https://github.com/andreasronge/neo4j/
159
159
  licenses:
160
160
  - MIT
161
161
  metadata: {}