Class: Dynamoid::Indexes::Index

Inherits:
Object
  • Object
show all
Defined in:
lib/dynamoid/indexes/index.rb

Overview

The class contains all the information an index contains, including its keys and which attributes it covers.

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Index) initialize(source, name, options = {})

Create a new index. Pass either :range => true or :range => :column_name to create a ranged index on that column.

Parameters:

  • source (Class)

    the source class for the index

  • name (Symbol)

    the name of the index

Raises:

Since:

  • 0.2.0



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/dynamoid/indexes/index.rb', line 16

def initialize(source, name, options = {})
  @source = source
  
  if options.delete(:range)
    @range_keys = sort(name)
  elsif options[:range_key]
    @range_keys = sort(options[:range_key])
  end
  @hash_keys = sort(name)
  @name = sort([hash_keys, range_keys])
  
  raise Dynamoid::Errors::InvalidField, 'A key specified for an index is not a field' unless keys.all?{|n| source.attributes.include?(n)}
end

Instance Attribute Details

- (Object) hash_keys

Returns the value of attribute hash_keys



7
8
9
# File 'lib/dynamoid/indexes/index.rb', line 7

def hash_keys
  @hash_keys
end

- (Object) name

Returns the value of attribute name



7
8
9
# File 'lib/dynamoid/indexes/index.rb', line 7

def name
  @name
end

- (Object) range_keys Also known as: range_key?

Returns the value of attribute range_keys



7
8
9
# File 'lib/dynamoid/indexes/index.rb', line 7

def range_keys
  @range_keys
end

- (Object) source

Returns the value of attribute source



7
8
9
# File 'lib/dynamoid/indexes/index.rb', line 7

def source
  @source
end

Instance Method Details

- (Object) delete(obj, changed_attributes = false)

Delete an object from this index, preserving existing ids if there are any, and failing gracefully if for some reason the index doesn't already have this object in it.

Since:

  • 0.2.0



93
94
95
96
97
98
99
# File 'lib/dynamoid/indexes/index.rb', line 93

def delete(obj, changed_attributes = false)
  values = values(obj, changed_attributes)
  return true if values[:hash_value].blank? || (!values[:range_value].nil? && values[:range_value].blank?)
  existing = Dynamoid::Adapter.read(self.table_name, values[:hash_value], { :range_key => values[:range_value]})
  return true unless existing && existing[:ids] && existing[:ids].include?(obj.id)
  Dynamoid::Adapter.write(self.table_name, {:id => values[:hash_value], :ids => (existing[:ids] - Set[obj.id]), :range => values[:range_value]})
end

- (Object) keys

Return the array of keys this index uses for its table.

Since:

  • 0.2.0



43
44
45
# File 'lib/dynamoid/indexes/index.rb', line 43

def keys
  [Array(hash_keys) + Array(range_keys)].flatten.uniq
end

- (Object) save(obj)

Save an object to this index, merging it with existing ids if there's already something present at this index location. First, though, delete this object from its old indexes (so the object isn't listed in an erroneous index).

Since:

  • 0.2.0



80
81
82
83
84
85
86
87
# File 'lib/dynamoid/indexes/index.rb', line 80

def save(obj)
  self.delete(obj, true)
  values = values(obj)
  return true if values[:hash_value].blank? || (!values[:range_value].nil? && values[:range_value].blank?)
  existing = Dynamoid::Adapter.read(self.table_name, values[:hash_value], { :range_key => values[:range_value] })
  ids = ((existing and existing[:ids]) or Set.new)
  Dynamoid::Adapter.write(self.table_name, {:id => values[:hash_value], :ids => ids.merge([obj.id]), :range => values[:range_value]})
end

- (Object) sort(objs)

Sort objects into alphabetical strings, used for composing index names correctly (since we always assume they're alphabetical).

Examples:

find all users by first and last name

sort([:gamma, :alpha, :beta, :omega]) # => [:alpha, :beta, :gamma, :omega]

Since:

  • 0.2.0



36
37
38
# File 'lib/dynamoid/indexes/index.rb', line 36

def sort(objs)
  Array(objs).flatten.compact.uniq.collect(&:to_s).sort.collect(&:to_sym)
end

- (Object) table_name

Return the table name for this index.

Since:

  • 0.2.0



50
51
52
# File 'lib/dynamoid/indexes/index.rb', line 50

def table_name
  "#{Dynamoid::Config.namespace}_index_#{source.to_s.downcase}_#{name.collect(&:to_s).collect(&:pluralize).join('_and_')}"
end

- (Hash) values(attrs, changed_attributes = false)

Given either an object or a list of attributes, generate a hash key and a range key for the index. Optionally pass in true to changed_attributes for a list of all the object's dirty attributes in convenient index form (for deleting stale information from the indexes).

Parameters:

  • attrs (Object)

    either an object that responds to :attributes, or a hash of attributes

Returns:

  • (Hash)

    a hash with the keys :hash_value and :range_value

Since:

  • 0.2.0



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/dynamoid/indexes/index.rb', line 63

def values(attrs, changed_attributes = false)
  if changed_attributes
    hash = {}
    attrs.changes.each {|k, v| hash[k.to_sym] = (v.first || v.last)}
    attrs = hash
  end
  attrs = attrs.send(:attributes) if attrs.respond_to?(:attributes)
  {}.tap do |hash|
    hash[:hash_value] = hash_keys.collect{|key| attrs[key]}.join('.')
    hash[:range_value] = range_keys.inject(0.0) {|sum, key| sum + attrs[key].to_f} if self.range_key?
  end
end