Module: Ripple::Associations

Extended by:
ActiveSupport::Concern
Defined in:
lib/ripple/associations.rb,
lib/ripple/associations/one.rb,
lib/ripple/associations/many.rb,
lib/ripple/associations/proxy.rb,
lib/ripple/associations/linked.rb,
lib/ripple/associations/embedded.rb,
lib/ripple/associations/instantiators.rb,
lib/ripple/associations/one_key_proxy.rb,
lib/ripple/associations/one_linked_proxy.rb,
lib/ripple/associations/many_linked_proxy.rb,
lib/ripple/associations/one_embedded_proxy.rb,
lib/ripple/associations/many_embedded_proxy.rb,
lib/ripple/associations/many_reference_proxy.rb,
lib/ripple/associations/one_stored_key_proxy.rb,
lib/ripple/associations/many_stored_key_proxy.rb

Overview

Adds associations via links and embedding to Document models. Examples:

# Documents can contain embedded documents, and link to other standalone documents
# via associations using the many and one class methods.
class Person
  include Ripple::Document
  property :name, String
  many :addresses
  many :friends, :class_name => "Person"
  one :account
end

# Account and Address are embeddable documents
class Account
  include Ripple::EmbeddedDocument
  property :paid_until, Time
  embedded_in :person # Adds "person" method to get parent document
end

class Address
  include Ripple::EmbeddedDocument
  property :street, String
  property :city, String
  property :state, String
  property :zip, String
end

person = Person.find("adamhunter")
person.friends << Person.find("seancribbs") # Links to people/seancribbs with tag "friend"
person.addresses << Address.new(:street => "100 Main Street") # Adds an embedded address
person..paid_until = 3.months.from_now

Defined Under Namespace

Modules: ClassMethods, Embedded, Instantiators, KeyDelegator, Linked, Many, One Classes: ManyEmbeddedProxy, ManyLinkedProxy, ManyReferenceProxy, ManyStoredKeyProxy, OneEmbeddedProxy, OneKeyProxy, OneLinkedProxy, OneStoredKeyProxy, Proxy

Instance Method Summary collapse

Instance Method Details

#attributes_for_persistenceObject

Adds embedded documents to the attributes



143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/ripple/associations.rb', line 143

def attributes_for_persistence
  self.class.embedded_associations.inject(super) do |attrs, association|
    documents = instance_variable_get(association.ivar)
    # We must explicitly check #nil? (rather than just saying `if documents`)
    # because documents can be an association proxy that is proxying nil.
    # In this case ruby treats documents as true because it is not _really_ nil,
    # but #nil? will tell us if it is proxying nil.

    unless documents.nil?
      attrs[association.name] = documents.is_a?(Array) ? documents.map(&:attributes_for_persistence) : documents.attributes_for_persistence
    end
    attrs
  end
end

#get_proxy(association) ⇒ Object



126
127
128
129
130
131
132
# File 'lib/ripple/associations.rb', line 126

def get_proxy(association)
  unless proxy = instance_variable_get(association.ivar)
    proxy = association.proxy_class.new(self, association)
    instance_variable_set(association.ivar, proxy)
  end
  proxy
end

#propagate_callbacks_to_embedded_associations(name, kind) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/ripple/associations.rb', line 158

def propagate_callbacks_to_embedded_associations(name, kind)
  self.class.embedded_associations.each do |association|
    documents = instance_variable_get(association.ivar)
    # We must explicitly check #nil? (rather than just saying `if documents`)
    # because documents can be an association proxy that is proxying nil.
    # In this case ruby treats documents as true because it is not _really_ nil,
    # but #nil? will tell us if it is proxying nil.
    next if documents.nil?

    Array(documents).each do |doc|
      doc.send("_#{name}_callbacks").each do |callback|
        next unless callback.kind == kind
        doc.send(callback.filter)
      end
    end
  end
end

#reset_associationsObject



135
136
137
138
139
# File 'lib/ripple/associations.rb', line 135

def reset_associations
  self.class.associations.each do |name, assoc_object|
    send(name).reset
  end
end

#run_callbacks(name, *args, &block) ⇒ Object

Propagates callbacks (save/create/update/destroy) to embedded associated documents. This is necessary so that when a parent is saved, the embedded child’s before_save hooks are run as well.



180
181
182
183
184
185
186
187
188
189
# File 'lib/ripple/associations.rb', line 180

def run_callbacks(name, *args, &block)
  # validation is already propagated to embedded documents via the
  # AssociatedValidator.  We don't need to duplicate the propagation here.
  return super if name == :validation

  propagate_callbacks_to_embedded_associations(name, :before)
  return_value = super
  propagate_callbacks_to_embedded_associations(name, :after)
  return_value
end