Class: DatastaxRails::Associations::CollectionProxy

Inherits:
Object
  • Object
show all
Defined in:
lib/datastax_rails/associations/collection_proxy.rb

Overview

Association proxies in DatastaxRails are middlemen between the object that holds the association, known as the @owner, and the actual associated object, known as the @target. The kind of association any proxy is about is available in @reflection. That's an instance of the class DatastaxRails::Reflection::AssociationReflection.

For example, given

class Blog < DatastaxRails::Base
  has_many :posts
end

blog = Blog.first

the association proxy in blog.posts has the object in blog as @owner, the collection of its posts as @target, and the @reflection object represents a :has_many macro.

This class has most of the basic instance methods removed, and delegates unknown methods to @target via method_missing. As a corner case, it even removes the class method and that's why you get

blog.posts.class # => Array

though the object behind blog.posts is not an Array, but an DatastaxRails::Associations::HasManyAssociation.

The @target object is not loaded until needed. For example,

blog.posts.count

is computed directly through Solr and does not trigger by itself the instantiation of the actual post records.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(association) ⇒ CollectionProxy

Returns a new instance of CollectionProxy


51
52
53
54
# File 'lib/datastax_rails/associations/collection_proxy.rb', line 51

def initialize(association)
  @association = association
  Array.wrap(association.options[:extend]).each { |ext| proxy_extend(ext) }
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/datastax_rails/associations/collection_proxy.rb', line 64

def method_missing(method, *args, &block)
  if target.respond_to?(method) || (!proxy_association.klass.respond_to?(method) && Class.respond_to?(method))
    if load_target
      if target.respond_to?(method)
        target.send(method, *args, &block)
      else
        begin
          super
        rescue NoMethodError => e
          raise e, e.message.sub(/ for #<.*$/, " via proxy for #{target}")
        end
      end
    end

  else
    scoped.send(method, *args, &block)
  end
end

Instance Attribute Details

#associationObject (readonly) Also known as: proxy_association

Returns the value of attribute association


37
38
39
# File 'lib/datastax_rails/associations/collection_proxy.rb', line 37

def association
  @association
end

Instance Method Details

#<<(*records) ⇒ Object Also known as: push


94
95
96
# File 'lib/datastax_rails/associations/collection_proxy.rb', line 94

def <<(*records)
  proxy_association.concat(records) && self
end

#===(other) ⇒ Object

Forwards === explicitly to the target because the instance method removal above doesn't catch it. Loads the target if needed.


85
86
87
# File 'lib/datastax_rails/associations/collection_proxy.rb', line 85

def ===(other)
  other === load_target # rubocop:disable Style/CaseEquality
end

#clearObject


99
100
101
102
# File 'lib/datastax_rails/associations/collection_proxy.rb', line 99

def clear
  destroy_all
  self
end

#reloadObject


104
105
106
107
# File 'lib/datastax_rails/associations/collection_proxy.rb', line 104

def reload
  proxy_association.reload
  self
end

#respond_to?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)

58
59
60
61
62
# File 'lib/datastax_rails/associations/collection_proxy.rb', line 58

def respond_to?(name, include_private = false)
  super ||
    (load_target && target.respond_to?(name, include_private)) ||
    proxy_association.klass.respond_to?(name, include_private)
end

#to_aryObject Also known as: to_a


89
90
91
# File 'lib/datastax_rails/associations/collection_proxy.rb', line 89

def to_ary
  load_target.dup
end