module Cequel::Record::Associations

Cequel records can have parent-child relationships defined by {ClassMethods#belongs_to belongs_to} and {ClassMethods#has_many has_many} associations. Unlike in a relational database ORM, associations are not represented by foreign keys; instead they use CQL3's compound primary keys. A child object's primary key begins with it's parent's primary key.

In the below example, the `blogs` table has a one-column primary key `(subdomain)`, and the `posts` table has a two-column primary key `(blog_subdomain, permalink)`. All posts that belong to the blog with subdomain `“cassandra”` will have `“cassandra”` as their `blog_subdomain`.

@example Blogs and Posts

class Blog
  include Cequel::Record

  key :subdomain, :text

  column :name, :text

  has_many :posts
end

class Post
  include Cequel::Record

  # This defines the first primary key column as `blog_subdomain`.
  # Because `belongs_to` associations implicitly define columns in the
  # primary key, it must come before any explicit key definition. For
  # the same reason, a Record class can only have a single `belongs_to`
  # declaration.
  belongs_to :blog

  # We also define an additional primary key column so that each post
  # has a unique compound primary key
  key :permalink

  column :title, :text
  column :body, :text
end

blog = Blog.new(subdomain: 'cassandra')
post = blog.posts.new(permalink: 'cequel')
post.blog_subdomain #=> "cassandra"

@since 1.0.0

Public Instance Methods

destroy(*) click to toggle source

@private

Calls superclass method
# File lib/cequel/record/associations.rb, line 177
def destroy(*)
  super.tap do
    self.class.child_associations.each_value do |association|
      case association.dependent
      when :destroy
        __send__(association.name).destroy_all
      when :delete
        __send__(association.name).delete_all
      end
    end
  end
end
read_child_association(association_name, reload = false) click to toggle source
# File lib/cequel/record/associations.rb, line 227
def read_child_association(association_name, reload = false)
  association = child_associations[association_name]
  ivar = association.instance_variable_name
  if !reload && instance_variable_defined?(ivar)
    return instance_variable_get(ivar)
  end

  base_scope = association.association_class
  association_record_set =
    key_values.reduce(base_scope) do |record_set, key_value|
      record_set[key_value]
    end

  instance_variable_set(
    ivar, AssociationCollection.new(association_record_set))
end
read_parent_association() click to toggle source
# File lib/cequel/record/associations.rb, line 190
def read_parent_association
  ivar_name = parent_association.instance_variable_name
  if instance_variable_defined?(ivar_name)
    return instance_variable_get(ivar_name)
  end
  parent_key_values = key_values
    .first(parent_association.association_key_columns.length)
  if parent_key_values.none? { |value| value.nil? }
    clazz = parent_association.association_class
    parent = parent_key_values.reduce(clazz) do |record_set, key_value|
      record_set[key_value]
    end
    instance_variable_set(ivar_name, parent)
  end
end
write_parent_association(parent) click to toggle source
# File lib/cequel/record/associations.rb, line 206
def write_parent_association(parent)
  unless parent.is_a?(parent_association.association_class)
    fail ArgumentError,
         "Wrong class for #{parent_association.name}; expected " \
         "#{parent_association.association_class.name}, got " \
         "#{parent.class.name}"
  end
  instance_variable_set "@#{parent_association.name}", parent
  key_column_names = self.class.key_column_names
  parent.key_attributes
    .zip(key_column_names) do |(parent_column_name, value), column_name|
      if value.nil?
        fail ArgumentError,
             "Can't set parent association " \
             "#{parent_association.name.inspect} " \
             "without value in key #{parent_column_name.inspect}"
      end
      write_attribute(column_name, value)
    end
end