module Neo4j::ActiveNode::HasN::ClassMethods
Public Instance Methods
association?(name)
click to toggle source
rubocop:enable Style/PredicateName
# File lib/neo4j/active_node/has_n.rb 228 def association?(name) 229 !!associations[name.to_sym] 230 end
associations()
click to toggle source
# File lib/neo4j/active_node/has_n.rb 232 def associations 233 @associations ||= {} 234 end
associations_keys()
click to toggle source
# File lib/neo4j/active_node/has_n.rb 236 def associations_keys 237 @associations_keys ||= associations.keys 238 end
has_association?(name)
click to toggle source
:nocov:
# File lib/neo4j/active_node/has_n.rb 219 def has_association?(name) 220 ActiveSupport::Deprecation.warn 'has_association? is deprecated and may be removed from future releases, use association? instead.', caller 221 222 association?(name) 223 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 330 def has_many(direction, name, options = {}) # rubocop:disable Style/PredicateName 331 name = name.to_sym 332 build_association(:has_many, direction, name, options) 333 334 define_has_many_methods(name) 335 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 347 def has_one(direction, name, options = {}) # rubocop:disable Style/PredicateName 348 name = name.to_sym 349 build_association(:has_one, direction, name, options) 350 351 define_has_one_methods(name) 352 end
inherited(klass)
click to toggle source
make sure the inherited classes inherit the _decl_rels
hash
Calls superclass method
# File lib/neo4j/active_node/has_n.rb 241 def inherited(klass) 242 klass.instance_variable_set(:@associations, associations.clone) 243 @associations_keys = klass.associations_keys.clone 244 super 245 end
Private Instance Methods
association_proxy(name, options = {})
click to toggle source
# File lib/neo4j/active_node/has_n.rb 490 def association_proxy(name, options = {}) 491 AssociationProxy.new(association_query_proxy(name, options)) 492 end
association_query_proxy(name, options = {})
click to toggle source
# File lib/neo4j/active_node/has_n.rb 474 def association_query_proxy(name, options = {}) 475 previous_query_proxy = options[:previous_query_proxy] || current_scope 476 query_proxy = previous_query_proxy || default_association_query_proxy 477 Neo4j::ActiveNode::Query::QueryProxy.new(association_target_class(name), 478 associations[name], 479 {session: neo4j_session, 480 query_proxy: query_proxy, 481 context: "#{query_proxy.context || self.name}##{name}", 482 optional: query_proxy.optional?, 483 association_labels: options[:labels], 484 source_object: query_proxy.source_object}.merge!(options)).tap do |query_proxy_result| 485 target_classes = association_target_classes(name) 486 return query_proxy_result.as_models(target_classes) if target_classes 487 end 488 end
association_target_class(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 494 def association_target_class(name) 495 target_classes_or_nil = associations[name].target_classes_or_nil 496 497 return if !target_classes_or_nil.is_a?(Array) || target_classes_or_nil.size != 1 498 499 target_classes_or_nil[0] 500 end
association_target_classes(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 502 def association_target_classes(name) 503 target_classes_or_nil = associations[name].target_classes_or_nil 504 505 return if !target_classes_or_nil.is_a?(Array) || target_classes_or_nil.size <= 1 506 507 target_classes_or_nil 508 end
build_association(macro, direction, name, options)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 515 def build_association(macro, direction, name, options) 516 options[:model_class] = options[:model_class].name if options[:model_class] == self 517 Neo4j::ActiveNode::HasN::Association.new(macro, direction, name, options).tap do |association| 518 @associations ||= {} 519 @associations[name] = association 520 create_reflection(macro, name, association, self) 521 end 522 523 associations_keys << name 524 525 # Re-raise any exception with added class name and association name to 526 # make sure error message is helpful 527 rescue StandardError => e 528 raise e.class, "#{e.message} (#{self.class}##{name})" 529 end
default_association_query_proxy()
click to toggle source
# File lib/neo4j/active_node/has_n.rb 510 def default_association_query_proxy 511 Neo4j::ActiveNode::Query::QueryProxy.new("::#{self.name}".constantize, nil, 512 session: neo4j_session, query_proxy: nil, context: "#{self.name}") 513 end
define_class_method(*args, &block)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 467 def define_class_method(*args, &block) 468 klass = class << self; self; end 469 klass.instance_eval do 470 define_method(*args, &block) 471 end 472 end
define_has_many_id_methods(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 386 def define_has_many_id_methods(name) 387 define_method_unless_defined("#{name.to_s.singularize}_ids") do 388 association_proxy(name).result_ids 389 end 390 391 define_method_unless_defined("#{name.to_s.singularize}_ids=") do |ids| 392 clear_deferred_nodes_for_association(name) 393 association_proxy(name).replace_with(ids) 394 end 395 396 define_method_unless_defined("#{name.to_s.singularize}_neo_ids") do 397 association_proxy(name).pluck(:neo_id) 398 end 399 end
define_has_many_methods(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 356 def define_has_many_methods(name) 357 define_method(name) do |node = nil, rel = nil, options = {}| 358 # return [].freeze unless self._persisted_obj 359 360 options, node = node, nil if node.is_a?(Hash) 361 362 association_proxy(name, {node: node, rel: rel, source_object: self, labels: options[:labels]}.merge!(options)) 363 end 364 365 define_has_many_setter(name) 366 367 define_has_many_id_methods(name) 368 369 define_class_method(name) do |node = nil, rel = nil, options = {}| 370 options, node = node, nil if node.is_a?(Hash) 371 372 association_proxy(name, {node: node, rel: rel, labels: options[:labels]}.merge!(options)) 373 end 374 end
define_has_many_setter(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 376 def define_has_many_setter(name) 377 define_method("#{name}=") do |other_nodes| 378 association_proxy_cache.clear 379 380 clear_deferred_nodes_for_association(name) 381 382 Neo4j::Transaction.run { association_proxy(name).replace_with(other_nodes) } 383 end 384 end
define_has_one_getter(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 433 def define_has_one_getter(name) 434 define_method(name) do |node = nil, rel = nil, options = {}| 435 options, node = node, nil if node.is_a?(Hash) 436 437 # Return all results if a variable-length relationship length was given 438 association_proxy = association_proxy(name, {node: node, rel: rel}.merge!(options)) 439 if options[:rel_length] && !options[:rel_length].is_a?(Fixnum) 440 association_proxy 441 else 442 target_class = self.class.send(:association_target_class, name) 443 o = association_proxy.result.first 444 if target_class 445 target_class.send(:nodeify, o) 446 else 447 o 448 end 449 end 450 end 451 end
define_has_one_id_methods(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 419 def define_has_one_id_methods(name) 420 define_method_unless_defined("#{name}_id") do 421 association_proxy(name).result_ids.first 422 end 423 424 define_method_unless_defined("#{name}_id=") do |id| 425 association_proxy(name).replace_with(id) 426 end 427 428 define_method_unless_defined("#{name}_neo_id") do 429 association_proxy(name).pluck(:neo_id).first 430 end 431 end
define_has_one_methods(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 405 def define_has_one_methods(name) 406 define_has_one_getter(name) 407 408 define_has_one_setter(name) 409 410 define_has_one_id_methods(name) 411 412 define_class_method(name) do |node = nil, rel = nil, options = {}| 413 options, node = node, nil if node.is_a?(Hash) 414 415 association_proxy(name, {node: node, rel: rel, labels: options[:labels]}.merge!(options)) 416 end 417 end
define_has_one_setter(name)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 453 def define_has_one_setter(name) 454 define_method("#{name}=") do |other_node| 455 if persisted? 456 other_node.save if other_node.respond_to?(:persisted?) && !other_node.persisted? 457 association_proxy_cache.clear # TODO: Should probably just clear for this association... 458 Neo4j::Transaction.run { association_proxy(name).replace_with(other_node) } 459 # handle_non_persisted_node(other_node) 460 else 461 defer_create(name, other_node, clear: true) 462 other_node 463 end 464 end 465 end
define_method_unless_defined(method_name, &block)
click to toggle source
# File lib/neo4j/active_node/has_n.rb 401 def define_method_unless_defined(method_name, &block) 402 define_method(method_name, block) unless method_defined?(method_name) 403 end