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

Sign up to get free protection for your applications and to get access to all the features.
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: {}