Class: ApiResource::Associations::AssociationProxy

Inherits:
Object
  • Object
show all
Defined in:
lib/api_resource/associations/association_proxy.rb

Direct Known Subclasses

MultiObjectProxy, SingleObjectProxy

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(klass, owner, options = {}) ⇒ AssociationProxy

Returns a new instance of AssociationProxy.



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/api_resource/associations/association_proxy.rb', line 79

def initialize(klass, owner, options = {})

  # the base class for our scope, e.g. ApiResource::SomeClass
  @klass = klass.is_a?(String) ? klass.constantize : klass

  # load the resource definition
  @klass.load_resource_definition

  @owner = owner

  # store our options
  @options = options
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



138
139
140
141
142
143
144
145
146
# File 'lib/api_resource/associations/association_proxy.rb', line 138

def method_missing(method, *args, &block)
  # If we are calling a scoped method that should be allowed
  if self.klass.scope?(method)
    cond = self.klass.send(method, *args, &block)
    self.to_condition.merge!(cond)
  else
    self.internal_object.send(method, *args, &block)
  end
end

Instance Attribute Details

#finder_optsObject (readonly)

Returns the value of attribute finder_opts.



12
13
14
# File 'lib/api_resource/associations/association_proxy.rb', line 12

def finder_opts
  @finder_opts
end

#klassObject (readonly)

Returns the value of attribute klass.



12
13
14
# File 'lib/api_resource/associations/association_proxy.rb', line 12

def klass
  @klass
end

#ownerObject (readonly)

Returns the value of attribute owner.



12
13
14
# File 'lib/api_resource/associations/association_proxy.rb', line 12

def owner
  @owner
end

#remote_pathObject

Returns the value of attribute remote_path.



11
12
13
# File 'lib/api_resource/associations/association_proxy.rb', line 11

def remote_path
  @remote_path
end

Class Method Details

.define_association_as_attribute(klass, assoc_name, opts = {}) ⇒ Object

define association methods on the class



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/api_resource/associations/association_proxy.rb', line 23

def self.define_association_as_attribute(klass, assoc_name, opts = {})

  id_method_name = self.foreign_key_name(assoc_name)
  associated_class = opts[:class_name] || assoc_name.to_s.classify

  # pass this along
  opts[:name] = assoc_name

  klass.api_resource_generated_methods.module_eval <<-EOE, __FILE__, __LINE__ + 1
    def #{assoc_name}
      @attributes_cache[:#{assoc_name}] ||= begin
        instance = #{self}.new(
          #{associated_class}, self, #{opts}
        )
        if @attributes.key?(:#{assoc_name})
          instance.internal_object = @attributes[:#{assoc_name}]
        end
        instance
      end
    end
    def #{assoc_name}=(val, force = true)
      if !force
        #{assoc_name}_will_change!
      elsif self.#{assoc_name}.internal_object != val
        #{assoc_name}_will_change!
      end
      # This should not force a load
      self.#{assoc_name}.internal_object = val
    end

    def #{assoc_name}?
      self.#{assoc_name}.internal_object.present?
    end

    # writer is the same for everyone
    def #{id_method_name}=(val, force = false)
      unless @attributes_cache[:#{id_method_name}] == val
        #{id_method_name}_will_change!
      end
      @attributes_cache[:#{id_method_name}] = val
      # write_attribute(:#{id_method_name}, val)
      @attributes[:#{id_method_name}] = val
    end

  EOE
end

Instance Method Details

#==(other) ⇒ Object



132
133
134
# File 'lib/api_resource/associations/association_proxy.rb', line 132

def ==(other)
   raise "Not Implemented: This method must be implemented in a subclass"
end

#expires_in(ttl) ⇒ Object



123
124
125
# File 'lib/api_resource/associations/association_proxy.rb', line 123

def expires_in(ttl)
  ApiResource::Decorators::CachingDecorator.new(self, ttl)
end

#includes(*args) ⇒ Object



128
129
130
# File 'lib/api_resource/associations/association_proxy.rb', line 128

def includes(*args)
  self.to_condition.merge!(self.klass.includes(*args))
end

#internal_objectObject

Use this method to access the internal data, this guarantees that loading only occurs once per object



98
99
100
101
102
103
# File 'lib/api_resource/associations/association_proxy.rb', line 98

def internal_object
  if instance_variable_defined?(:@internal_object)
    return instance_variable_get(:@internal_object)
  end
  instance_variable_set(:@internal_object, self.load)
end

#load_resource_definitionObject



110
111
112
# File 'lib/api_resource/associations/association_proxy.rb', line 110

def load_resource_definition
  self.klass.load_resource_definition
end

#loaded?Boolean

has the scope been loaded?

Returns:

  • (Boolean)


106
107
108
# File 'lib/api_resource/associations/association_proxy.rb', line 106

def loaded?
  @loaded == true
end

#reloadObject

unset all of our scope values and our internal object



115
116
117
118
119
120
121
# File 'lib/api_resource/associations/association_proxy.rb', line 115

def reload
  @loaded = false
  if instance_variable_defined?(:@internal_object)
    remove_instance_variable(:@internal_object)
  end
  self
end

#ttlObject



93
94
95
# File 'lib/api_resource/associations/association_proxy.rb', line 93

def ttl
  @ttl || 0
end