Module: CassandraMapper::Indexing::ClassMethods

Defined in:
lib/cassandra_mapper/indexing.rb

Instance Method Summary collapse

Instance Method Details

#has_index(index, options = {}, &block) ⇒ Object

Build an index object and install it into the calling class.

  • The index argument should be a symbol, which will be the name of the index and the name of the accessor method for that index at both the class level and the instance level.

  • The options hash is passed through to the CassandraMapper::Index constructor, with some minor mapping logic. See the CassandraMapper::Index documentation for most options. Some options specific to this method:

    • class: the class object to use for the index object; use this if you want to provide your own custom index behavior. Defaults to Cassandra::Index. This option determines the class to be instantiated and is not passed along to the constructor.

    • indexed_class: always gets set to the receiver, even if you set it explicitly. This ensures that the index binds to the class against which has_index was called.

    • name: always gets set to the index argument provided to the has_index call, even if you set it explicitly in options.

  • If a _&block_ is provided, it will be evaluated in the context of the newly-created index object; this makes it easy to build indexes that have specialized logic for formatting sortable identifiers, etc.

The index is installed as the index attribute of the class object, so all index operations can be accomplished from there. Additionally, the index name is used as an instance attribute, in which an instance’s state relative to the index is tracked. Therefore, choose an index value that you’re happy having on both class and instances.

The index object is activated after installation, so its observer goes into effect immediately.

Given the example class and index described at CassandraMapper::Index, the same strategy could be achieved less verbosely with:

class ToBeIndexed < CassandraMapper::Base
  column_family :ToBeIndexed
  maps :key, :type => :simple_uuid

  maps :data
  maps :created_at, :type => :timestamp, :default => :from_type

  def timestamped_key
    "#{created_at.to_s}_#{key}"
  end

  has_index :data_index, :source             => :data,
                         :indexed_identifier => :timestamped_key,
                         :column_family      => :Indexes
end

The has_index invocation takes care of the details for creating the :data_index class and instance attributes, the CassandraMapper::Index instance, its installation and activation, etc.

Finally, if the timestamped key only pertains to this index (as is the case in this example), we could arguably reduce clutter in the main model class and keep the key generation encapsulated in the index by using the block-style invocation.

class ToBeIndexed < CassandraMapper::Base
  column_family :ToBeIndexed
  maps :key, :type => :simple_uuid

  maps :data
  maps :created_at, :type => :timestamp, :default => :from_type

  has_index :data_index, :source => :data, :column_family => :Indexes do
    def indexed_identifier_for(instance)
      "#{instance.created_at.to_s}_#{instance.key}"
    end
  end
end


145
146
147
148
149
150
# File 'lib/cassandra_mapper/indexing.rb', line 145

def has_index(index, options={}, &block)
  klass = options.delete(:class) || CassandraMapper::Index
  object = klass.new(options.merge(:indexed_class => self, :name => index))
  object.instance_eval &block if block_given?
  install_index(index, object)
end

#install_index(name, index) ⇒ Object



152
153
154
155
156
157
158
159
# File 'lib/cassandra_mapper/indexing.rb', line 152

def install_index(name, index)
  name_string = name.to_s
  instance_variable_set(:"@#{name_string}", index)
  instance_eval "def #{name_string}; @#{name_string}; end"
  module_eval "def #{name_string}; @#{name_string} ||= CassandraMapper::Index::State.new; end"
  index.activate!
  index
end