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



63
64
65
# File 'lib/cassie/model.rb', line 63

def find_subscribers
  @@find_subscribers
end

Instance Method Details

#==(other) ⇒ Object



551
552
553
# File 'lib/cassie/model.rb', line 551

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

#attributesObject

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



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

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)


484
485
486
# File 'lib/cassie/model.rb', line 484

def counter_table?
  !!self.class._counter_table
end

#destroyObject

Delete a record and call the destroy callbacks.



525
526
527
528
529
530
531
# File 'lib/cassie/model.rb', line 525

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

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


547
548
549
# File 'lib/cassie/model.rb', line 547

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

#initialize(attributes = {}) ⇒ Object



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

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

#key_hashObject

Returns the primary key as a hash



556
557
558
559
560
561
562
# File 'lib/cassie/model.rb', line 556

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)


479
480
481
# File 'lib/cassie/model.rb', line 479

def persisted?
  @persisted
end

#persistence_ttlObject

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



543
544
545
# File 'lib/cassie/model.rb', line 543

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)


491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
# File 'lib/cassie/model.rb', line 491

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
      options = {:consistency => write_consistency, :ttl => (ttl || persistence_ttl)}
      if persisted?
        run_callbacks(:update) do
          self.class.connection.update(self.class.full_table_name, values_hash, key_hash, options)
        end
      else
        run_callbacks(:create) do
          self.class.connection.insert(self.class.full_table_name, attributes, options)
          @persisted = true
        end
      end
    end
    true
  else
    false
  end
end

#save!(ttl: nil) ⇒ Object

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



516
517
518
519
520
521
522
# File 'lib/cassie/model.rb', line 516

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