module Couchbase::Model::Relationship::Parent::ClassMethods

Public Instance Methods

child(name, options = {}) click to toggle source
# File lib/couchbase/model/relationship/parent.rb, line 102
def child(name, options = {})
  # TODO This may get the full module path for a relationship name,
  # and that will make the keys very long. Is this necessary? see: AR STI
  name = name.to_s.underscore unless name.is_a?(String)

  (@_children ||= []).push Relationship::Association.new(name, options)

  define_method("#{name}=") do |object|
    # FIXME Sanity check. If parent and parent != self, error
    object.parent = self if object.respond_to?(:parent)

    # Mark as loaded when we use the setter
    send("#{name}_loaded!")
    instance_variable_set :"@_child_#{name}", object
  end

  define_method("#{name}_loaded?") do
    instance_variable_get("@_child_#{name}_loaded")
  end

  define_method("#{name}_loaded!") do
    instance_variable_set("@_child_#{name}_loaded", true)
  end
  protected "#{name}_loaded!".to_sym

  define_method("#{name}") do
    # DO NOT USE Association#fetch IN THIS METHOD
    base_var_name = "@_child_#{name}"

    if (existing = instance_variable_get(base_var_name)).present?
      existing
    else
      if send("#{name}_loaded?")
        send("build_#{name}")
      else
        assoc = self.class.child_association_for(name)
        send("#{name}_loaded!")

        if (unloaded = assoc.load(self)).present?
          send("#{name}=", unloaded)
        end

        send(name)
      end
    end
  end

  define_method("build_#{name}") do |attributes = {}|
    assoc = self.class.child_association_for(name)
    send("#{name}=", assoc.child_class.new(attributes)).tap do |child|
      child.parent = self
    end
  end
end
child_association_for(name) click to toggle source
# File lib/couchbase/model/relationship/parent.rb, line 171
def child_association_for(name)
  @_children.detect {|association| association.name == name.to_s }
end
child_association_names() click to toggle source
# File lib/couchbase/model/relationship/parent.rb, line 163
def child_association_names
  children.map(&:name)
end
child_associations() click to toggle source
# File lib/couchbase/model/relationship/parent.rb, line 167
def child_associations
  @_children || []
end
children(*names) click to toggle source
# File lib/couchbase/model/relationship/parent.rb, line 157
def children(*names)
  options = names.extract_options!

  names.each {|name| child name, options }
end
find_all_with_children(ids, *children) click to toggle source

FIXME This is a horrible abortion of a method

# File lib/couchbase/model/relationship/parent.rb, line 182
def find_all_with_children(ids, *children)
  ids = Array(ids)

  effective_children = if children.blank?
    @_children.select {|child| child.auto_load }
  else
    children = children.map(&:to_s)
    @_children.select {|child| children.include?(child.name) }
  end
  
  search_ids = ids.dup
  ids.each do |id|
    search_ids.concat(effective_children.map do |child| 
      child.child_class.prefixed_id(id)
    end)
  end

  results = bucket.get(search_ids, quiet: true, extended: true)

  parent_objects = ids.map do |id|
    if results.key?(id)
      raw_new(id, results.delete(id))
    else
      raise Couchbase::Error::NotFound.new("failed to get value (key=\"#{id}\"")
    end
  end

  parent_objects.each do |parent|
    results.each do |child_id, child_attributes|
      if unprefixed_id(parent.id) == unprefixed_id(child_id) 
        assoc = effective_children.detect {|assoc| assoc.prefix == prefix_from_id(child_id) }
        parent.send "#{assoc.name}=", 
          assoc.child_class.raw_new(child_id, child_attributes)
      end
    end

    effective_children.each {|assoc| parent.send("#{assoc.name}_loaded!") }
  end
end
find_with_children(id, *children) click to toggle source
# File lib/couchbase/model/relationship/parent.rb, line 175
def find_with_children(id, *children)
  return nil if id.blank?

  find_all_with_children(id, *children).first
end
inherited(base) click to toggle source
# File lib/couchbase/model/relationship/parent.rb, line 95
def inherited(base)
  children = child_associations
  base.class_eval do
    @_children = children.dup
  end
end
raw_new(id, results) click to toggle source
# File lib/couchbase/model/relationship/parent.rb, line 222
def raw_new(id, results)
  obj, flags, cas = results
  if obj.is_a?(Hash)
    obj.merge!(:_ignore_dirty => true)
  else
    obj = {:raw => obj}
  end

  new({:id => id, :meta => {'flags' => flags, 'cas' => cas}}.merge(obj))
end