Module: Cassie::Model

Extended by:
ActiveModel::Callbacks, ActiveSupport::Concern
Includes:
ActiveModel::Model, ActiveModel::Validations, ActiveModel::Validations::Callbacks
Defined in:
lib/cassie/model.rb

Overview

This module provides a simple interface for models backed by Cassandra tables.

Cassandra is very limited in how data can be accessed efficiently so this code is intentionally not designed as a full fledged DSL with all the nifty features of ActiveRecord. Doing so will only get you into trouble when you run into the limits of Cassandra data structures.

It implements ActiveModel::Model and supports ActiveModel callbacks on :create, :update, :save, and :destroy as well as ActiveModel validations.

Example:

class Thing
  include Cassie::Model

  self.table_name = "things"
  self.keyspace = "test"
  self.primary_key = [:owner, :id]

  column :owner, :int
  column :id, :int, :as => :identifier
  column :val, :varchar, :as => :value

  ordering_key :id, :desc

  validates_presence_of :id, :value

  before_save do
    ...
  end
end

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#==(other) ⇒ Object



498
499
500
# File 'lib/cassie/model.rb', line 498

def ==(other)
  eql?(other)
end

#attributesObject

Returns a hash of column to values. Column names will be symbols.



481
482
483
484
485
486
487
# File 'lib/cassie/model.rb', line 481

def attributes
  hash = {}
  self.class.column_names.each do |name|
    hash[name] = send(name)
  end
  hash
end

#counter_table?Boolean

Return true if the table is used for a counter.

Returns:

  • (Boolean)


432
433
434
# File 'lib/cassie/model.rb', line 432

def counter_table?
  !!self.class._counter_table
end

#destroyObject

Delete a record and call the destroy callbacks.



472
473
474
475
476
477
478
# File 'lib/cassie/model.rb', line 472

def destroy
  run_callbacks(:destroy) do
    self.class.connection.delete(self.class.full_table_name, key_hash)
    @persisted = false
    true
  end
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


494
495
496
# File 'lib/cassie/model.rb', line 494

def eql?(other)
  other.is_a?(self.class) && other.key_hash == key_hash
end

#initialize(attributes = {}) ⇒ Object



421
422
423
424
# File 'lib/cassie/model.rb', line 421

def initialize(attributes = {})
  super
  @persisted = false
end

#key_hashObject

Returns the primary key as a hash



503
504
505
506
507
508
509
# File 'lib/cassie/model.rb', line 503

def key_hash
  hash = {}
  self.class.primary_key.each do |key|
    hash[key] = self.send(key)
  end
  hash
end

#persisted?Boolean

Return true if the record has been persisted to Cassandra.

Returns:

  • (Boolean)


427
428
429
# File 'lib/cassie/model.rb', line 427

def persisted?
  @persisted
end

#persistence_ttlObject

Subclasses can override this method to provide a TTL on the persisted record.



490
491
492
# File 'lib/cassie/model.rb', line 490

def persistence_ttl
  nil
end

#save(validate: true, ttl: nil) ⇒ Object

Save a record. Returns true if the record was persisted and false if it was invalid. This method will run the save callbacks as well as either the update or create callbacks as necessary.

Raises:

  • (ArgumentError)


439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/cassie/model.rb', line 439

def save(validate: true, ttl: nil)
  raise ArgumentError.new("Cannot call save on a counter table") if counter_table?
  valid_record = (validate ? valid? : true)
  if valid_record
    run_callbacks(:save) do
      if persisted?
        run_callbacks(:update) do
          self.class.connection.update(self.class.full_table_name, values_hash, key_hash, :ttl => (ttl || persistence_ttl))
        end
      else
        run_callbacks(:create) do
          self.class.connection.insert(self.class.full_table_name, attributes, :ttl => (ttl || persistence_ttl))
          @persisted = true
        end
      end
    end
    true
  else
    false
  end
end

#save!Object

Save a record. Returns true if the record was saved and raises an ActiveRecord::RecordInvalid error if the record is invalid.



463
464
465
466
467
468
469
# File 'lib/cassie/model.rb', line 463

def save!
  if save
    true
  else
    raise Cassie::RecordInvalid.new(self)
  end
end