neo4j 3.0.0.alpha.9 → 3.0.0.alpha.10

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: c1f7216c885708e2f7b3f094a4ab4266e83c37a0
4
- data.tar.gz: 7350f7cd2f95de57873b607bda7a7a6357b29643
3
+ metadata.gz: f3ed632e184847cf87dace2146181d1fbde5bc7c
4
+ data.tar.gz: 3c4314c17410475fad46f4b5eed730186e800458
5
5
  SHA512:
6
- metadata.gz: cf800fb8a523e06f163e837985600bfa84109f74b2b548e18bd99961adb28e3ee5703963fe34e8939688af842eb2dc3b4d7ae3d529412ef2ce3791fa924bb922
7
- data.tar.gz: 3f0e91124dbe00b6f102d82c9f69117ecd9f4268c87d3f30600e145078ae28e155f69927415d8e106f93015ed4c694a4df9da540330d7cf929e5abd4ff23b6a2
6
+ metadata.gz: f8732369f9890161646404ccbdc2f3aca3d6facc4119c775a5dac45ae0b130997039dfc0a6134f7004801969c333b2dd3d191de1adcd5603e4bd2c88904830b4
7
+ data.tar.gz: edfdf0fc367e93e5d72e4255aec79216f80834aab3d40bbc9f5447762883412521b273980c0d15ff7bbc6d90a4969248a2bea632fe03d9a034cc9d6278ee9066
data/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ == 3.0.0.alpha.10
2
+ * ActiveRel support, see Wiki pages (chris #393)
3
+
1
4
  == 3.0.0.alpha.9
2
5
  * Complete rewrite of the query api, see wiki page (#406, chris, brian)
3
6
  * Performance improvements (#382,#400, #402, chris)
data/Gemfile CHANGED
@@ -2,7 +2,8 @@ source 'http://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- #gem 'neo4j-core', :path => '../neo4j-core'
5
+
6
+ gem 'neo4j-core' #, path: '../neo4j-core'
6
7
  #gem 'neo4j-core', :git => 'https://github.com/andreasronge/neo4j-core.git'
7
8
  #gem 'orm_adapter', :path => '../orm_adapter'
8
9
 
data/lib/neo4j.rb CHANGED
@@ -17,9 +17,28 @@ require 'active_support/core_ext/class/attribute.rb'
17
17
  require 'active_attr'
18
18
  require 'neo4j/config'
19
19
  require 'neo4j/wrapper'
20
+ require 'neo4j/active_rel/rel_wrapper'
21
+ require 'neo4j/active_node/node_wrapper'
20
22
  require 'neo4j/type_converters'
21
- require "neo4j/active_node/labels"
22
- require 'neo4j/active_node/identity'
23
+ require 'neo4j/paginated'
24
+
25
+ require 'neo4j/shared/callbacks'
26
+ require 'neo4j/shared/property'
27
+ require 'neo4j/shared/persistence'
28
+ require 'neo4j/shared/validations'
29
+ require 'neo4j/shared/identity'
30
+ require 'neo4j/shared'
31
+
32
+ require 'neo4j/active_rel/callbacks'
33
+ require 'neo4j/active_rel/initialize'
34
+ require 'neo4j/active_rel/property'
35
+ require 'neo4j/active_rel/persistence'
36
+ require 'neo4j/active_rel/validations'
37
+ require 'neo4j/active_rel/query'
38
+ require 'neo4j/active_rel/related_node'
39
+ require 'neo4j/active_rel'
40
+
41
+ require 'neo4j/active_node/labels'
23
42
  require 'neo4j/active_node/id_property'
24
43
  require 'neo4j/active_node/callbacks'
25
44
  require 'neo4j/active_node/initialize'
@@ -29,11 +48,9 @@ require 'neo4j/active_node/validations'
29
48
  require 'neo4j/active_node/rels'
30
49
  require 'neo4j/active_node/has_n'
31
50
  require 'neo4j/active_node/has_n/association'
32
- require 'neo4j/active_node/has_n/nodes'
33
51
  require 'neo4j/active_node/query/query_proxy'
34
52
  require 'neo4j/active_node/query'
35
53
  require 'neo4j/active_node/serialized_properties'
36
- require 'neo4j/paginated'
37
54
  require 'neo4j/active_node'
38
55
 
39
56
  require 'neo4j/active_node/orm_adapter'
@@ -23,55 +23,25 @@ module Neo4j
23
23
  #
24
24
  module ActiveNode
25
25
  extend ActiveSupport::Concern
26
- extend ActiveModel::Naming
27
-
28
- include ActiveModel::Conversion
29
- include ActiveModel::Serializers::Xml
30
- include ActiveModel::Serializers::JSON
31
26
 
27
+ include Neo4j::Shared
32
28
  include Neo4j::ActiveNode::Initialize
33
- include Neo4j::ActiveNode::Identity
34
29
  include Neo4j::ActiveNode::IdProperty
35
- include Neo4j::ActiveNode::Persistence
36
30
  include Neo4j::ActiveNode::SerializedProperties
37
31
  include Neo4j::ActiveNode::Property
38
- include Neo4j::ActiveNode::Query
39
- include Neo4j::ActiveNode::Labels
32
+ include Neo4j::ActiveNode::Persistence
40
33
  include Neo4j::ActiveNode::Validations
41
34
  include Neo4j::ActiveNode::Callbacks
35
+ include Neo4j::ActiveNode::Query
36
+ include Neo4j::ActiveNode::Labels
42
37
  include Neo4j::ActiveNode::Rels
43
38
  include Neo4j::ActiveNode::HasN
44
39
 
45
- def wrapper
46
- self
47
- end
48
-
49
40
  def neo4j_obj
50
- _persisted_node || raise("Tried to access native neo4j object on a non persisted object")
51
- end
52
-
53
- module ClassMethods
54
- def neo4j_session_name (name)
55
- @neo4j_session_name = name
56
- end
57
-
58
- def neo4j_session
59
- if @neo4j_session_name
60
- 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")
61
- else
62
- Neo4j::Session.current
63
- end
64
- end
41
+ _persisted_obj || raise("Tried to access native neo4j object on a non persisted object")
65
42
  end
66
43
 
67
44
  included do
68
- self.include_root_in_json = true
69
-
70
-
71
- def self.i18n_scope
72
- :neo4j
73
- end
74
-
75
45
  def self.inherited(other)
76
46
  inherited_indexes(other) if self.respond_to?(:indexed_properties)
77
47
  attributes.each_pair do |k,v|
@@ -2,40 +2,7 @@ module Neo4j
2
2
  module ActiveNode
3
3
  module Callbacks #:nodoc:
4
4
  extend ActiveSupport::Concern
5
-
6
- module ClassMethods
7
- include ActiveModel::Callbacks
8
- end
9
-
10
- included do
11
- include ActiveModel::Validations::Callbacks
12
-
13
- define_model_callbacks :initialize, :find, :only => :after
14
- define_model_callbacks :save, :create, :update, :destroy
15
- end
16
-
17
- def destroy #:nodoc:
18
- run_callbacks(:destroy) { super }
19
- end
20
-
21
- def touch(*) #:nodoc:
22
- run_callbacks(:touch) { super }
23
- end
24
-
25
- private
26
-
27
- def create_or_update #:nodoc:
28
- run_callbacks(:save) { super }
29
- end
30
-
31
- def create_model #:nodoc:
32
- run_callbacks(:create) { super }
33
- end
34
-
35
- def update_model(*) #:nodoc:
36
- run_callbacks(:update) { super }
37
- end
5
+ include Neo4j::Shared::Callbacks
38
6
  end
39
-
40
7
  end
41
8
  end
@@ -7,26 +7,16 @@ module Neo4j
7
7
  attr_reader :type, :name, :relationship, :direction
8
8
 
9
9
  def initialize(type, direction, name, options = {})
10
- raise ArgumentError, "Invalid association type: #{type.inspect}" if not [:has_many, :has_one].include?(type.to_sym)
11
- raise ArgumentError, "Invalid direction: #{direction.inspect}" if not [:out, :in, :both].include?(direction.to_sym)
10
+ check_valid_type_and_dir(type, direction)
12
11
  @type = type.to_sym
13
12
  @name = name
14
13
  @direction = direction.to_sym
15
- raise ArgumentError, "Cannot specify both :type and :origin (#{base_declaration})" if options[:type] && options[:origin]
16
-
17
14
  @target_class_name_from_name = name.to_s.classify
18
- @target_class_option = target_class_option(options)
19
- @callbacks = {before: options[:before], after: options[:after]}
20
- @relationship_type = options[:type] && options[:type].to_sym
21
- @origin = options[:origin] && options[:origin].to_sym
15
+ set_vars_from_options(options)
22
16
  end
23
17
 
24
18
  def target_class_option(options)
25
- if options[:model_class].nil?
26
- @target_class_name_from_name
27
- elsif options[:model_class]
28
- options[:model_class]
29
- end
19
+ options[:model_class].nil? ? @target_class_name_from_name : options[:model_class]
30
20
  end
31
21
 
32
22
  # Return cypher partial query string for the relationship part of a MATCH (arrow / relationship definition)
@@ -35,7 +25,6 @@ module Neo4j
35
25
 
36
26
  relationship_type = relationship_type(create)
37
27
  relationship_name_cypher = ":`#{relationship_type}`" if relationship_type
38
-
39
28
  properties_string = get_properties_string(properties)
40
29
  relationship_cypher = get_relationship_cypher(var, relationship_name_cypher, properties_string)
41
30
  get_direction(relationship_cypher, create)
@@ -63,9 +52,12 @@ module Neo4j
63
52
  end
64
53
 
65
54
  def relationship_type(create = false)
66
- if @relationship_type
55
+ case
56
+ when @relationship_class
57
+ @relationship_class._type
58
+ when @relationship_type
67
59
  @relationship_type
68
- elsif @origin
60
+ when @origin
69
61
  origin_type
70
62
  else
71
63
  (create || exceptional_target_class?) && "##{@name}"
@@ -91,7 +83,9 @@ module Neo4j
91
83
  end
92
84
 
93
85
  def get_properties_string(properties)
86
+ properties[Neo4j::Config.class_name_property] = @relationship_class.name if @relationship_class
94
87
  p = properties.map do |key, value|
88
+ next if key == :_classname
95
89
  "#{key}: #{value.inspect}"
96
90
  end.join(', ')
97
91
  p.size == 0 ? '' : " {#{p}}"
@@ -101,6 +95,21 @@ module Neo4j
101
95
  target_class.associations[@origin].relationship_type
102
96
  end
103
97
 
98
+ def relationship_class
99
+ @relationship_class
100
+ end
101
+
102
+ private
103
+
104
+ def set_vars_from_options(options)
105
+ validate_option_combinations(options)
106
+ @target_class_option = target_class_option(options)
107
+ @callbacks = {before: options[:before], after: options[:after]}
108
+ @origin = options[:origin] && options[:origin].to_sym
109
+ @relationship_class = options[:rel_class]
110
+ @relationship_type = options[:type] && options[:type].to_sym
111
+ end
112
+
104
113
  # Return basic details about association as declared in the model
105
114
  # @example
106
115
  # has_many :in, :bands
@@ -108,6 +117,16 @@ module Neo4j
108
117
  "#{type} #{direction.inspect}, #{name.inspect}"
109
118
  end
110
119
 
120
+ def check_valid_type_and_dir(type, direction)
121
+ raise ArgumentError, "Invalid association type: #{type.inspect}" if not [:has_many, :has_one].include?(type.to_sym)
122
+ raise ArgumentError, "Invalid direction: #{direction.inspect}" if not [:out, :in, :both].include?(direction.to_sym)
123
+ end
124
+
125
+ def validate_option_combinations(options)
126
+ raise ArgumentError, "Cannot specify both :type and :origin (#{base_declaration})" if options[:type] && options[:origin]
127
+ raise ArgumentError, "Cannot specify both :type and :rel_class (#{base_declaration})" if options[:type] && options[:rel_class]
128
+ raise ArgumentError, "Cannot specify both :origin and :rel_class (#{base_declaration}" if options[:origin] && options[:rel_class]
129
+ end
111
130
 
112
131
  # Determine if model class as derived from the association name would be different than the one specified via the model_class key
113
132
  # @example
@@ -116,4 +116,4 @@ module Neo4j::ActiveNode
116
116
 
117
117
  end
118
118
 
119
- end
119
+ end
@@ -2,13 +2,13 @@ module Neo4j::ActiveNode::Initialize
2
2
  extend ActiveSupport::Concern
3
3
  include Neo4j::TypeConverters
4
4
 
5
- attr_reader :_persisted_node
5
+ attr_reader :_persisted_obj
6
6
 
7
7
  # called when loading the node from the database
8
8
  # @param [Neo4j::Node] persisted_node the node this class wraps
9
9
  # @param [Hash] properties of the persisted node.
10
10
  def init_on_load(persisted_node, properties)
11
- @_persisted_node = persisted_node
11
+ @_persisted_obj = persisted_node
12
12
  changed_attributes && changed_attributes.clear
13
13
  @attributes = attributes.merge(properties.stringify_keys)
14
14
  self.default_properties=properties
@@ -13,20 +13,20 @@ module Neo4j
13
13
  # @return the labels
14
14
  # @see Neo4j-core
15
15
  def labels
16
- @_persisted_node.labels
16
+ @_persisted_obj.labels
17
17
  end
18
18
 
19
19
  # adds one or more labels
20
20
  # @see Neo4j-core
21
21
  def add_label(*label)
22
- @_persisted_node.add_label(*label)
22
+ @_persisted_obj.add_label(*label)
23
23
  end
24
24
 
25
25
  # Removes one or more labels
26
26
  # Be careful, don't remove the label representing the Ruby class.
27
27
  # @see Neo4j-core
28
28
  def remove_label(*label)
29
- @_persisted_node.remove_label(*label)
29
+ @_persisted_obj.remove_label(*label)
30
30
  end
31
31
 
32
32
  def self.included(klass)
@@ -0,0 +1,50 @@
1
+ class Neo4j::Node
2
+ module Wrapper
3
+
4
+ # this is a plugin in the neo4j-core so that the Ruby wrapper will be wrapped around the Neo4j::Node objects
5
+ def wrapper
6
+ most_concrete_class = sorted_wrapper_classes
7
+ wrapped_node = most_concrete_class.new
8
+ wrapped_node.init_on_load(self, self.props)
9
+ wrapped_node
10
+ end
11
+
12
+ def checked_labels_set
13
+ @@_checked_labels_set ||= Set.new
14
+ end
15
+
16
+ def check_label(label_name)
17
+ unless checked_labels_set.include?(label_name)
18
+ load_class_from_label(label_name)
19
+ # do this only once
20
+ checked_labels_set.add(label_name)
21
+ end
22
+ end
23
+
24
+ def sorted_wrapper_classes
25
+ if self.props.is_a?(Hash) && self.props.has_key?(Neo4j::Config.class_name_property)
26
+ self.props[Neo4j::Config.class_name_property].constantize
27
+ else
28
+ wrappers = _class_wrappers
29
+ return self if wrappers.nil?
30
+ wrapper_classes = wrappers.map{|w| Neo4j::ActiveNode::Labels._wrapped_labels[w]}
31
+ wrapper_classes.sort.first
32
+ end
33
+ end
34
+
35
+ def load_class_from_label(label_name)
36
+ begin
37
+ label_name.to_s.split("::").inject(Kernel) {|container, name| container.const_get(name.to_s) }
38
+ rescue NameError
39
+ nil
40
+ end
41
+ end
42
+
43
+ def _class_wrappers
44
+ labels.find_all do |label_name|
45
+ check_label(label_name)
46
+ Neo4j::ActiveNode::Labels._wrapped_labels[label_name].class == Class
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,32 +1,13 @@
1
1
  module Neo4j::ActiveNode
2
2
  module Persistence
3
- class RecordInvalidError < RuntimeError
4
- attr_reader :record
5
-
6
- def initialize(record)
7
- @record = record
8
- super(@record.errors.full_messages.join(", "))
9
- end
10
- end
11
-
12
3
  extend ActiveSupport::Concern
13
- include Neo4j::TypeConverters
14
-
15
- # Saves the model.
16
- #
17
- # If the model is new a record gets created in the database, otherwise the existing record gets updated.
18
- # If perform_validation is true validations run.
19
- # If any of them fail the action is cancelled and save returns false. If the flag is false validations are bypassed altogether. See ActiveRecord::Validations for more information.
20
- # There’s a series of callbacks associated with save. If any of the before_* callbacks return false the action is cancelled and save returns false.
21
- def save(*)
22
- update_magic_properties
23
- create_or_update
24
- end
4
+ include Neo4j::Shared::Persistence
25
5
 
26
6
  # Creates a model with values matching those of the instance attributes and returns its id.
27
7
  # @private
28
8
  # @return true
29
9
  def create_model(*)
10
+ create_magic_properties
30
11
  set_timestamps
31
12
  create_magic_properties
32
13
  properties = convert_properties_to :db, props
@@ -37,97 +18,6 @@ module Neo4j::ActiveNode
37
18
  true
38
19
  end
39
20
 
40
- # Persist the object to the database. Validations and Callbacks are included
41
- # by default but validation can be disabled by passing :validate => false
42
- # to #save! Creates a new transaction.
43
- #
44
- # @raise a RecordInvalidError if there is a problem during save.
45
- # @param (see Neo4j::Rails::Validations#save)
46
- # @return nil
47
- # @see #save
48
- # @see Neo4j::Rails::Validations Neo4j::Rails::Validations - for the :validate parameter
49
- # @see Neo4j::Rails::Callbacks Neo4j::Rails::Callbacks - for callbacks
50
- def save!(*args)
51
- unless save(*args)
52
- raise RecordInvalidError.new(self)
53
- end
54
- end
55
-
56
- # Convenience method to set attribute and #save at the same time
57
- # @param [Symbol, String] attribute of the attribute to update
58
- # @param [Object] value to set
59
- def update_attribute(attribute, value)
60
- send("#{attribute}=", value)
61
- self.save
62
- end
63
-
64
- # Convenience method to set attribute and #save! at the same time
65
- # @param [Symbol, String] attribute of the attribute to update
66
- # @param [Object] value to set
67
- def update_attribute!(attribute, value)
68
- send("#{attribute}=", value)
69
- self.save!
70
- end
71
-
72
- # Convenience method to set multiple attributes and #save at the same time
73
- # @param [Hash] attributes of names and values of attributes to set
74
- def update_attributes(attributes)
75
- assign_attributes(attributes)
76
- self.save
77
- end
78
-
79
- def create_or_update
80
- # since the same model can be created or updated twice from a relationship we have to have this guard
81
- @_create_or_updating = true
82
- result = persisted? ? update_model : create_model
83
- unless result != false
84
- Neo4j::Transaction.current.fail if Neo4j::Transaction.current
85
- false
86
- else
87
- true
88
- end
89
- rescue => e
90
- Neo4j::Transaction.current.fail if Neo4j::Transaction.current
91
- raise e
92
- ensure
93
- @_create_or_updating = nil
94
- end
95
-
96
- def exist?
97
- _persisted_node && _persisted_node.exist?
98
- end
99
-
100
- # Returns +true+ if the object was destroyed.
101
- def destroyed?
102
- @_deleted || (!new_record? && !exist?)
103
- end
104
-
105
- # Returns +true+ if the record is persisted, i.e. it’s not a new record and it was not destroyed
106
- def persisted?
107
- !new_record? && !destroyed?
108
- end
109
-
110
- # Returns +true+ if the record hasn't been saved to Neo4j yet.
111
- def new_record?
112
- ! _persisted_node
113
- end
114
-
115
- alias :new? :new_record?
116
-
117
- def destroy
118
- _persisted_node && _persisted_node.del
119
- @_deleted = true
120
- end
121
-
122
- def update_model
123
- if changed_attributes && !changed_attributes.empty?
124
- changed_props = attributes.select{|k,v| changed_attributes.include?(k)}
125
- changed_props = convert_properties_to :db, changed_props
126
- _persisted_node.update_props(changed_props)
127
- changed_attributes.clear
128
- end
129
- end
130
-
131
21
  def _create_node(*args)
132
22
  session = self.class.neo4j_session
133
23
  props = self.class.default_property_values(self)
@@ -137,75 +27,6 @@ module Neo4j::ActiveNode
137
27
  session.create_node(props, labels)
138
28
  end
139
29
 
140
- # @return [Hash] all defined and none nil properties
141
- def props
142
- attributes.reject{|k,v| v.nil?}.symbolize_keys
143
- end
144
-
145
- # @return true if the attributes hash has been frozen
146
- def frozen?
147
- freeze_if_deleted
148
- @attributes.frozen?
149
- end
150
-
151
- def freeze
152
- @attributes.freeze
153
- self
154
- end
155
-
156
- def freeze_if_deleted
157
- unless new_record?
158
- # TODO - Neo4j::IdentityMap.remove_node_by_id(neo_id)
159
- unless self.class.load_entity(neo_id)
160
- @_deleted = true
161
- freeze
162
- end
163
- end
164
- end
165
-
166
- def reload
167
- return self if new_record?
168
- changed_attributes && changed_attributes.clear
169
- unless reload_from_database
170
- @_deleted = true
171
- freeze
172
- end
173
- self
174
- end
175
-
176
- def reload_from_database
177
- # TODO - Neo4j::IdentityMap.remove_node_by_id(neo_id)
178
- if reloaded = self.class.load_entity(neo_id)
179
- send(:attributes=, reloaded.attributes)
180
- end
181
- reloaded
182
- end
183
-
184
- # Updates this resource with all the attributes from the passed-in Hash and requests that the record be saved.
185
- # If saving fails because the resource is invalid then false will be returned.
186
- def update(attributes)
187
- self.attributes = attributes
188
- save
189
- end
190
- alias_method :update_attributes, :update
191
-
192
- # Same as {#update_attributes}, but raises an exception if saving fails.
193
- def update!(attributes)
194
- self.attributes = attributes
195
- save!
196
- end
197
- alias_method :update_attributes!, :update!
198
-
199
- def cache_key
200
- if self.new_record?
201
- "#{self.class.model_name.cache_key}/new"
202
- elsif self.respond_to?(:updated_at) && !self.updated_at.blank?
203
- "#{self.class.model_name.cache_key}/#{neo_id}-#{self.updated_at.utc.to_s(:number)}"
204
- else
205
- "#{self.class.model_name.cache_key}/#{neo_id}"
206
- end
207
- end
208
-
209
30
  module ClassMethods
210
31
  # Creates a saves a new node
211
32
  # @param [Hash] props the properties the new node should have
@@ -237,33 +58,9 @@ module Neo4j::ActiveNode
237
58
  def load_entity(id)
238
59
  Neo4j::Node.load(id)
239
60
  end
240
-
241
61
  end
242
62
 
243
63
  private
244
64
 
245
- def create_magic_properties
246
-
247
- end
248
-
249
- def update_magic_properties
250
- self.updated_at = DateTime.now if respond_to?(:updated_at=) && changed?
251
- end
252
-
253
- def set_classname(props)
254
- props[Neo4j::Config.class_name_property] = self.class.name if self.class.cached_class?
255
- end
256
-
257
- def assign_attributes(attributes)
258
- attributes.each do |attribute, value|
259
- send("#{attribute}=", value)
260
- end
261
- end
262
-
263
- def set_timestamps
264
- self.created_at = DateTime.now if respond_to?(:created_at=)
265
- self.updated_at = self.created_at if respond_to?(:updated_at=)
266
- end
267
65
  end
268
-
269
66
  end