class Mingo::ManyProxy

Public Class Methods

decorate_each(&block) click to toggle source
# File lib/mingo/many_proxy.rb, line 23
def self.decorate_each(&block)
  if block_given?
    @decorate_each = block
  else
    @decorate_each
  end
end
decorate_with(mod = nil, &block) click to toggle source
# File lib/mingo/many_proxy.rb, line 15
def self.decorate_with(mod = nil, &block)
  if mod or block_given?
    @decorate_with = mod || Module.new(&block)
  else
    @decorate_with
  end
end
new(parent, property, mapping) click to toggle source
# File lib/mingo/many_proxy.rb, line 31
def initialize(parent, property, mapping)
  @parent = parent
  @property = property
  # TODO: ugh, improve naming
  @model, @self_referencing_key, @forward_referencing_key = analyze_mapping mapping
  @counter_cache_field = "#{@property}_count"
  @join_loaded = nil
  @loaded = nil
end

Public Instance Methods

<<(doc) click to toggle source
# File lib/mingo/many_proxy.rb, line 62
def <<(doc)
  doc = convert(doc)
  doc['_id'] = join_collection.save doc
  change_counter_cache(1)
  load_join << doc if @join_loaded
  unload_collection
  self
end
cache_key() click to toggle source
# File lib/mingo/many_proxy.rb, line 105
def cache_key
  [@parent, @property, counter_cache]
end
convert(doc) click to toggle source
# File lib/mingo/many_proxy.rb, line 58
def convert(doc)
  {@self_referencing_key => @parent.id, @forward_referencing_key => doc.id}
end
delete(doc) click to toggle source
# File lib/mingo/many_proxy.rb, line 71
def delete(doc)
  doc = convert(doc)
  if join_doc = find_join_doc(doc[@forward_referencing_key])
    join_collection.remove :_id => join_doc['_id']
    change_counter_cache(-1)
    unload_collection
    @join_loaded.delete join_doc
  end
  doc
end
find(selector = {}, options = {}, &block) click to toggle source
# File lib/mingo/many_proxy.rb, line 91
def find(selector = {}, options = {}, &block)
  @model.find(selector, find_options.merge(options), &block)
end
include?(doc) click to toggle source
# File lib/mingo/many_proxy.rb, line 54
def include?(doc)
  !!find_join_doc(doc.id)
end
loaded?() click to toggle source
# File lib/mingo/many_proxy.rb, line 82
def loaded?
  !!@loaded
end
object_ids() click to toggle source
# File lib/mingo/many_proxy.rb, line 44
def object_ids
  join_docs = load_join
  join_docs = join_docs.select(&Proc.new) if block_given?
  join_docs.map { |doc| doc[@forward_referencing_key] }
end
reload() click to toggle source
# File lib/mingo/many_proxy.rb, line 86
def reload
  @loaded = @join_loaded = nil
  self
end
reset_counter_cache() click to toggle source
# File lib/mingo/many_proxy.rb, line 99
def reset_counter_cache
  delta = join_cursor.count - counter_cache
  change_counter_cache delta
  counter_cache
end
respond_to?(method, priv = false) click to toggle source
Calls superclass method
# File lib/mingo/many_proxy.rb, line 95
def respond_to?(method, priv = false)
  super || method_missing(:respond_to?, method, priv)
end
size() click to toggle source
# File lib/mingo/many_proxy.rb, line 50
def size
  (counter_cache? && counter_cache) || (@join_loaded && @join_loaded.size) || join_cursor.count
end

Private Instance Methods

analyze_mapping(mapping) click to toggle source

Example: {self => 'user_id', 'movie_id' => Movie}

# File lib/mingo/many_proxy.rb, line 134
def analyze_mapping(mapping)
  model = self_referencing_key = forward_referencing_key = nil
  mapping.each do |key, value|
    if key == @parent.class then self_referencing_key = value.to_s
    elsif value < Mingo
      forward_referencing_key = key.to_s
      model = value
    end
  end
  [model, self_referencing_key, forward_referencing_key]
end
change_counter_cache(by) click to toggle source
# File lib/mingo/many_proxy.rb, line 128
def change_counter_cache(by)
  @counter_cache = counter_cache + by
  @parent.update '$inc' => { @counter_cache_field => by }
end
counter_cache() click to toggle source
# File lib/mingo/many_proxy.rb, line 120
def counter_cache
  @counter_cache ||= @parent[@counter_cache_field].to_i
end
counter_cache?() click to toggle source
# File lib/mingo/many_proxy.rb, line 124
def counter_cache?
  !!@parent[@counter_cache_field]
end
find_join_doc(forward_id) click to toggle source
# File lib/mingo/many_proxy.rb, line 171
def find_join_doc(forward_id)
  load_join.find { |d| d[@forward_referencing_key] == forward_id }
end
find_options() click to toggle source
# File lib/mingo/many_proxy.rb, line 146
def find_options
  @find_options ||= begin
    decorator = self.class.decorate_with
    decorate_block = self.class.decorate_each
    
    if decorator or decorate_block
      {:transformer => lambda { |doc|
        @model.new(doc).tap do |obj|
          obj.extend decorator if decorator
          if decorate_block
            join_doc = find_join_doc(doc['_id'])
            decorate_block.call(obj, join_doc)
          end
        end
      }}
    else
      {}
    end
  end
end
join_collection() click to toggle source
# File lib/mingo/many_proxy.rb, line 116
def join_collection
  @join_collection ||= @parent.class.collection[@property.to_s]
end
join_cursor() click to toggle source
# File lib/mingo/many_proxy.rb, line 175
def join_cursor
  # TODO: make options configurable
  join_collection.find({@self_referencing_key => @parent.id}, :sort => '_id')
end
load_collection() click to toggle source
# File lib/mingo/many_proxy.rb, line 180
def load_collection
  @loaded ||= if self.object_ids.empty? then []
  else find(self.object_ids)
  end
end
load_join() click to toggle source
# File lib/mingo/many_proxy.rb, line 167
def load_join
  @join_loaded ||= join_cursor.to_a
end
method_missing(method, *args, &block) click to toggle source
# File lib/mingo/many_proxy.rb, line 111
def method_missing(method, *args, &block)
  load_collection
  @loaded.send(method, *args, &block)
end
unload_collection() click to toggle source
# File lib/mingo/many_proxy.rb, line 186
def unload_collection
  @loaded = nil
end