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

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: 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