lib/neoid/relationship.rb in neoid-0.0.2 vs lib/neoid/relationship.rb in neoid-0.0.5.alpha
- old
+ new
@@ -1,24 +1,33 @@
module Neoid
module Relationship
module InstanceMethods
def neo_find_by_id
Neoid.db.get_relationship_index(self.class.neo_index_name, :ar_id, self.id)
+ rescue Neography::NotFoundException
+ nil
end
def neo_create
- options = self.class.neoidable_options
+ return unless Neoid.enabled?
+ @_neo_destroyed = false
+ options = self.class.neoid_config.relationship_options
+
start_node = self.send(options[:start_node])
end_node = self.send(options[:end_node])
return unless start_node && end_node
+
+ data = self.to_neo.merge(ar_type: self.class.name, ar_id: self.id)
+ data.reject! { |k, v| v.nil? }
relationship = Neography::Relationship.create(
- options[:type],
+ options[:type].is_a?(Proc) ? options[:type].call(self) : options[:type],
start_node.neo_node,
- end_node.neo_node
+ end_node.neo_node,
+ data
)
Neoid.db.add_relationship_to_index(self.class.neo_index_name, :ar_id, self.id, relationship)
Neoid::logger.info "Relationship#neo_create #{self.class.name} #{self.id}, index = #{self.class.neo_index_name}"
@@ -29,25 +38,91 @@
def neo_load(relationship)
Neography::Relationship.load(relationship)
end
def neo_destroy
+ return if @_neo_destroyed
+ @_neo_destroyed = true
return unless neo_relationship
Neoid.db.remove_relationship_from_index(self.class.neo_index_name, neo_relationship)
neo_relationship.del
+ _reset_neo_representation
+
+ Neoid::logger.info "Relationship#neo_destroy #{self.class.name} #{self.id}, index = #{self.class.neo_index_name}"
+
+ true
end
+ def neo_update
+ Neoid.db.set_relationship_properties(neo_relationship, self.to_neo) if neo_relationship
+ end
+
def neo_relationship
_neo_representation
end
end
def self.included(receiver)
- receiver.extend Neoid::ModelAdditions::ClassMethods
- receiver.send :include, Neoid::ModelAdditions::InstanceMethods
+ receiver.send :include, Neoid::ModelAdditions
receiver.send :include, InstanceMethods
receiver.after_create :neo_create
receiver.after_destroy :neo_destroy
+ receiver.after_update :neo_update
+
+ if Neoid.env_loaded
+ initialize_relationship receiver
+ else
+ Neoid.relationship_models << receiver
+ end
end
+
+ def self.initialize_relationship(rel_model)
+ rel_model.reflect_on_all_associations(:belongs_to).each do |belongs_to|
+ return if belongs_to.options[:polymorphic]
+
+ # e.g. all has_many on User class
+ all_has_many = belongs_to.klass.reflect_on_all_associations(:has_many)
+
+ # has_many (without through) on the side of the relationship that removes a relationship. e.g. User has_many :likes
+ this_has_many = all_has_many.find { |o| o.klass == rel_model }
+ next unless this_has_many
+
+ # e.g. User has_many :likes, after_remove: ...
+ full_callback_name = "after_remove_for_#{this_has_many.name}"
+ belongs_to.klass.send(full_callback_name) << :neo_after_relationship_remove if belongs_to.klass.method_defined?(full_callback_name)
+ # belongs_to.klass.send(:has_many, this_has_many.name, this_has_many.options.merge(after_remove: :neo_after_relationship_remove))
+
+ # has_many (with through) on the side of the relationship that removes a relationship. e.g. User has_many :movies, through :likes
+ many_to_many = all_has_many.find { |o| o.options[:through] == this_has_many.name }
+ next unless many_to_many
+
+ return if many_to_many.options[:as] # polymorphic are not supported here yet
+
+ # user_id
+ foreign_key_of_owner = many_to_many.through_reflection.foreign_key
+
+ # movie_id
+ foreign_key_of_record = many_to_many.source_reflection.foreign_key
+
+ (Neoid.config[:relationship_meta_data] ||= {}).tap do |data|
+ (data[belongs_to.klass.name.to_s] ||= {}).tap do |model_data|
+ model_data[many_to_many.klass.name.to_s] = [rel_model.name.to_s, foreign_key_of_owner, foreign_key_of_record]
+ end
+ end
+
+ # puts Neoid.config[:relationship_meta_data].inspect
+
+ # e.g. User has_many :movies, through: :likes, before_remove: ...
+ full_callback_name = "before_remove_for_#{many_to_many.name}"
+ belongs_to.klass.send(full_callback_name) << :neo_before_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)
+ # belongs_to.klass.send(:has_many, many_to_many.name, many_to_many.options.merge(before_remove: :neo_after_relationship_remove))
+
+
+ # e.g. User has_many :movies, through: :likes, after_remove: ...
+ full_callback_name = "after_remove_for_#{many_to_many.name}"
+ belongs_to.klass.send(full_callback_name) << :neo_after_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)
+ # belongs_to.klass.send(:has_many, many_to_many.name, many_to_many.options.merge(after_remove: :neo_after_relationship_remove))
+ end
+ end
end
-end
\ No newline at end of file
+end