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.



92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/api_resource/associations/association_proxy.rb', line 92

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)



151
152
153
154
155
156
157
158
159
# File 'lib/api_resource/associations/association_proxy.rb', line 151

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
69
70
71
72
73
74
75
76
77
78
79
80
81
# 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
  remote_proxy = false

  # This is a terrible hack to hold us over until
  # we have a real association system
  if self.name.demodulize =~ /RemoteObjectProxy$/
    remote_proxy = true
  end
  # 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)
      # Active record uses string attributes key
      # Here's a terrible hack for the time being
      if #{remote_proxy}
        @attributes['#{id_method_name}'] = val
      else
        # and we use symbol attribute keys
        @attributes[:#{id_method_name}] = val
      end
    end

  EOE
end

Instance Method Details

#==(other) ⇒ Object



145
146
147
# File 'lib/api_resource/associations/association_proxy.rb', line 145

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

#expires_in(ttl) ⇒ Object



136
137
138
# File 'lib/api_resource/associations/association_proxy.rb', line 136

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

#includes(*args) ⇒ Object



141
142
143
# File 'lib/api_resource/associations/association_proxy.rb', line 141

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



111
112
113
114
115
116
# File 'lib/api_resource/associations/association_proxy.rb', line 111

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



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

def load_resource_definition
  self.klass.load_resource_definition
end

#loaded?Boolean

has the scope been loaded?

Returns:

  • (Boolean)


119
120
121
# File 'lib/api_resource/associations/association_proxy.rb', line 119

def loaded?
  @loaded == true
end

#reloadObject

unset all of our scope values and our internal object



128
129
130
131
132
133
134
# File 'lib/api_resource/associations/association_proxy.rb', line 128

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

#ttlObject



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

def ttl
  @ttl || 0
end