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 Classes: FindMessage

Constant Summary collapse

@@find_subscribers =
Cassie::Subscribers.new

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.find_subscribersObject



61
62
63
# File 'lib/cassie/model.rb', line 61

def find_subscribers
  @@find_subscribers
end

Instance Method Details

#==(other) ⇒ Object



530
531
532
# File 'lib/cassie/model.rb', line 530

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

#attributesObject

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



513
514
515
516
517
518
519
# File 'lib/cassie/model.rb', line 513

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)


464
465
466
# File 'lib/cassie/model.rb', line 464

def counter_table?
  !!self.class._counter_table
end

#destroyObject

Delete a record and call the destroy callbacks.



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

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)


526
527
528
# File 'lib/cassie/model.rb', line 526

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

#initialize(attributes = {}) ⇒ Object



453
454
455
456
# File 'lib/cassie/model.rb', line 453

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

#key_hashObject

Returns the primary key as a hash



535
536
537
538
539
540
541
# File 'lib/cassie/model.rb', line 535

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)


459
460
461
# File 'lib/cassie/model.rb', line 459

def persisted?
  @persisted
end

#persistence_ttlObject

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



522
523
524
# File 'lib/cassie/model.rb', line 522

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)


471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
# File 'lib/cassie/model.rb', line 471

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.



495
496
497
498
499
500
501
# File 'lib/cassie/model.rb', line 495

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