module Neo4j::ActiveNode::HasN::ClassMethods
rubocop:disable Metrics/ModuleLength
Public Instance Methods
association?(name)
click to toggle source
rubocop:enable Naming/PredicateName
# File lib/neo4j/active_node/has_n.rb 293 def association?(name) 294 !!associations[name.to_sym] 295 end
associations()
click to toggle source
# File lib/neo4j/active_node/has_n.rb 301 def associations 302 (@associations ||= parent_associations.dup) 303 end
associations_keys()
click to toggle source
# File lib/neo4j/active_node/has_n.rb 305 def associations_keys 306 @associations_keys ||= associations.keys 307 end
has_association?(name)
click to toggle source
:nocov:
# File lib/neo4j/active_node/has_n.rb 284 def has_association?(name) 285 ActiveSupport::Deprecation.warn 'has_association? is deprecated and may be removed from future releases, use association? instead.', caller 286 287 association?(name) 288 end
has_many(direction, name, options = {})
click to toggle source
For defining an “has many” association on a model. This defines a set of methods on your model instances. For instance, if you define the association on a Person model:
- .. code-block
-
ruby
has_many :out, :vehicles, type: :has_vehicle
This would define the following methods:
#vehicles
Returns a QueryProxy object. This is an Enumerable object and thus can be iterated over. It also has the ability to accept class-level methods from the Vehicle model (including calls to association methods)
**#vehicles=**
Takes an array of Vehicle objects and replaces all current ``:HAS_VEHICLE`` relationships with new relationships refering to the specified objects
.vehicles
Returns a QueryProxy object. This would represent all ``Vehicle`` objects associated with either all ``Person`` nodes (if ``Person.vehicles`` is called), or all ``Vehicle`` objects associated with the ``Person`` nodes thus far represented in the QueryProxy chain. For example: .. code-block:: ruby company.people.where(age: 40).vehicles
Arguments:
**direction:** **Available values:** ``:in``, ``:out``, or ``:both``. Refers to the relative to the model on which the association is being defined. Example: .. code-block:: ruby Person.has_many :out, :posts, type: :wrote means that a `WROTE` relationship goes from a `Person` node to a `Post` node **name:** The name of the association. The affects the methods which are created (see above). The name is also used to form default assumptions about the model which is being referred to Example: .. code-block:: ruby Person.has_many :out, :posts, type: :wrote will assume a `model_class` option of ``'Post'`` unless otherwise specified **options:** A ``Hash`` of options. Allowed keys are: *type*: The Neo4j relationship type. This option is required unless either the `origin` or `rel_class` options are specified *origin*: The name of the association from another model which the `type` and `model_class` can be gathered. Example: .. code-block:: ruby # `model_class` of `Post` is assumed here Person.has_many :out, :posts, origin: :author Post.has_one :in, :author, type: :has_author, model_class: :Person *model_class*: The model class to which the association is referring. Can be a Symbol/String (or an ``Array`` of same) with the name of the `ActiveNode` class, `false` to specify any model, or nil to specify that it should be guessed. *rel_class*: The ``ActiveRel`` class to use for this association. Can be either a model object ``include`` ing ``ActiveRel`` or a Symbol/String (or an ``Array`` of same). **A Symbol or String is recommended** to avoid load-time issues *dependent*: Enables deletion cascading. **Available values:** ``:delete``, ``:delete_orphans``, ``:destroy``, ``:destroy_orphans`` (note that the ``:destroy_orphans`` option is known to be "very metal". Caution advised)
# File lib/neo4j/active_node/has_n.rb 392 def has_many(direction, name, options = {}) # rubocop:disable Naming/PredicateName 393 name = name.to_sym 394 build_association(:has_many, direction, name, options) 395 396 define_has_many_methods(name, options) 397 end
has_one(direction, name, options = {})
click to toggle source
For defining an “has one” association on a model. This defines a set of methods on your model instances. For instance, if you define the association on a Person model:
has_one
:out, :vehicle, type: :has_vehicle
This would define the methods: “#vehicle“, “#vehicle=“, and “.vehicle“.
See :ref:`#has_many <Neo4j/ActiveNode/HasN/ClassMethods#has_many>` for anything not specified here
# File lib/neo4j/active_node/has_n.rb 409 def has_one(direction, name, options = {}) # rubocop:disable Naming/PredicateName 410 name = name.to_sym 411 build_association(:has_one, direction, name, options) 412 413 define_has_one_methods(name, options) 414 end
parent_associations()
click to toggle source
# File lib/neo4j/active_node/has_n.rb 297 def parent_associations 298 superclass == Object ? {} : superclass.associations 299 end
Private Instance Methods
add_association(name, association_object)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 600 def add_association(name, association_object) 601 fail "Association `#{name}` defined for a second time. "\ 602 'Associations can only be defined once' if duplicate_association?(name) 603 associations[name] = association_object 604 end
association_proxy(name, options = {})
click to toggle source
# File lib/neo4j/active_node/has_n.rb 560 def association_proxy(name, options = {}) 561 AssociationProxy.new(association_query_proxy(name, options)) 562 end
association_query_proxy(name, options = {})
click to toggle source
# File lib/neo4j/active_node/has_n.rb 544 def association_query_proxy(name, options = {}) 545 previous_query_proxy = options[:previous_query_proxy] || current_scope 546 query_proxy = previous_query_proxy || default_association_query_proxy 547 Neo4j::ActiveNode::Query::QueryProxy.new(association_target_class(name), 548 associations[name], 549 {session: neo4j_session, 550 query_proxy: query_proxy, 551 context: "#{query_proxy.context || self.name}##{name}", 552 optional: query_proxy.optional?, 553 association_labels: options[:labels], 554 source_object: query_proxy.source_object}.merge!(options)).tap do |query_proxy_result| 555 target_classes = association_target_classes(name) 556 return query_proxy_result.as_models(target_classes) if target_classes 557 end 558 end
association_target_class(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 564 def association_target_class(name) 565 target_classes_or_nil = associations[name].target_classes_or_nil 566 567 return if !target_classes_or_nil.is_a?(Array) || target_classes_or_nil.size != 1 568 569 target_classes_or_nil[0] 570 end
association_target_classes(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 572 def association_target_classes(name) 573 target_classes_or_nil = associations[name].target_classes_or_nil 574 575 return if !target_classes_or_nil.is_a?(Array) || target_classes_or_nil.size <= 1 576 577 target_classes_or_nil 578 end
build_association(macro, direction, name, options)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 585 def build_association(macro, direction, name, options) 586 options[:model_class] = options[:model_class].name if options[:model_class] == self 587 Neo4j::ActiveNode::HasN::Association.new(macro, direction, name, options).tap do |association| 588 add_association(name, association) 589 create_reflection(macro, name, association, self) 590 end 591 592 @associations_keys = nil 593 594 # Re-raise any exception with added class name and association name to 595 # make sure error message is helpful 596 rescue StandardError => e 597 raise e.class, "#{e.message} (#{self.class}##{name})" 598 end
default_association_query_proxy()
click to toggle source
# File lib/neo4j/active_node/has_n.rb 580 def default_association_query_proxy 581 Neo4j::ActiveNode::Query::QueryProxy.new("::#{self.name}".constantize, nil, 582 session: neo4j_session, query_proxy: nil, context: self.name.to_s) 583 end
define_class_method(*args, &block)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 537 def define_class_method(*args, &block) 538 klass = class << self; self; end 539 klass.instance_eval do 540 define_method(*args, &block) 541 end 542 end
define_has_many_id_methods(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 454 def define_has_many_id_methods(name) 455 define_method_unless_defined("#{name.to_s.singularize}_ids") do 456 association_proxy(name).result_ids 457 end 458 459 define_method_unless_defined("#{name.to_s.singularize}_ids=") do |ids| 460 clear_deferred_nodes_for_association(name) 461 association_proxy(name).replace_with(Array(ids).reject(&:blank?)) 462 end 463 464 define_method_unless_defined("#{name.to_s.singularize}_neo_ids") do 465 association_proxy(name).pluck(:neo_id) 466 end 467 end
define_has_many_methods(name, association_options)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 418 def define_has_many_methods(name, association_options) 419 default_options = association_options.slice(:labels) 420 421 define_method(name) do |node = nil, rel = nil, options = {}| 422 # return [].freeze unless self._persisted_obj 423 424 options, node = node, nil if node.is_a?(Hash) 425 426 options = default_options.merge(options) 427 428 association_proxy(name, {node: node, rel: rel, source_object: self, labels: options[:labels]}.merge!(options)) 429 end 430 431 define_has_many_setter(name) 432 433 define_has_many_id_methods(name) 434 435 define_class_method(name) do |node = nil, rel = nil, options = {}| 436 options, node = node, nil if node.is_a?(Hash) 437 438 options = default_options.merge(options) 439 440 association_proxy(name, {node: node, rel: rel, labels: options[:labels]}.merge!(options)) 441 end 442 end
define_has_many_setter(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 444 def define_has_many_setter(name) 445 define_method("#{name}=") do |other_nodes| 446 association_proxy_cache.clear 447 448 clear_deferred_nodes_for_association(name) 449 450 self.class.run_transaction { association_proxy(name).replace_with(other_nodes) } 451 end 452 end
define_has_one_getter(name, default_options)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 505 def define_has_one_getter(name, default_options) 506 define_method(name) do |node = nil, rel = nil, options = {}| 507 options, node = node, nil if node.is_a?(Hash) 508 509 options = default_options.merge(options) 510 511 association_proxy = association_proxy(name, {node: node, rel: rel}.merge!(options)) 512 513 # Return all results if options[:chainable] == true or a variable-length relationship length was given 514 if options[:chainable] || (options[:rel_length] && !options[:rel_length].is_a?(Integer)) 515 association_proxy 516 else 517 o = association_proxy.result.first 518 self.class.send(:association_target_class, name).try(:nodeify, o) || o 519 end 520 end 521 end
define_has_one_id_methods(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 491 def define_has_one_id_methods(name) 492 define_method_unless_defined("#{name}_id") do 493 association_proxy(name).result_ids.first 494 end 495 496 define_method_unless_defined("#{name}_id=") do |id| 497 association_proxy(name).replace_with(id) 498 end 499 500 define_method_unless_defined("#{name}_neo_id") do 501 association_proxy(name).pluck(:neo_id).first 502 end 503 end
define_has_one_methods(name, association_options)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 473 def define_has_one_methods(name, association_options) 474 default_options = association_options.slice(:labels) 475 476 define_has_one_getter(name, default_options) 477 478 define_has_one_setter(name) 479 480 define_has_one_id_methods(name) 481 482 define_class_method(name) do |node = nil, rel = nil, options = {}| 483 options, node = node, nil if node.is_a?(Hash) 484 485 options = default_options.merge(options) 486 487 association_proxy(name, {node: node, rel: rel, labels: options[:labels]}.merge!(options)) 488 end 489 end
define_has_one_setter(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 523 def define_has_one_setter(name) 524 define_method("#{name}=") do |other_node| 525 if persisted? 526 other_node.save if other_node.respond_to?(:persisted?) && !other_node.persisted? 527 association_proxy_cache.clear # TODO: Should probably just clear for this association... 528 self.class.run_transaction { association_proxy(name).replace_with(other_node) } 529 # handle_non_persisted_node(other_node) 530 else 531 defer_create(name, other_node, clear: true) 532 other_node 533 end 534 end 535 end
define_method_unless_defined(method_name, &block)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 469 def define_method_unless_defined(method_name, &block) 470 define_method(method_name, block) unless method_defined?(method_name) 471 end
duplicate_association?(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 606 def duplicate_association?(name) 607 associations.key?(name) && parent_associations[name] != associations[name] 608 end