class DatastaxRails::PayloadModel

A special model that is designed to efficiently store binary files. The major limitation is that the only fields this can store are the SHA1 digest and the payload itself. If you need to store other metadata, you will need another model that points at this one.

class AttachmentPayload < DatastaxRails::PayloadModel
  self.column_family = 'attachment_payloads'

  validate do
    if self.payload.size > 50.megabytes
      errors.add(:payload, "is larger than the limit of 50MB")
    end
  end
end

Public Class Methods

find(digest, options = {}) click to toggle source
# File lib/datastax_rails/payload_model.rb, line 32
def self.find(digest, options = {})
  if options[:consistency] && !valid_consistency?(options[:consistency].to_s.upcase)
    fail ArgumentError, "'#{options[:consistency]}' is not a valid Cassandra consistency level"
  end
  c = cql.select.conditions(digest: digest).order('chunk')
  c.using(options[:consistency]) if options[:consistency]
  io = StringIO.new('', 'w+')
  found = false
  chunk = 0
  c.execute.each do |row|
    io << Base64.decode64(row['payload'])
    chunk = row['chunk']
    found = true
  end
  fail DatastaxRails::RecordNotFound unless found
  io.rewind
  fail ChecksumMismatchError if digest != Digest::SHA1.hexdigest(io.read)
  io.rewind
  instantiate(digest, { digest: digest, payload: io.read, chunk: chunk }, [:digest, :payload])
end
inherited(child) click to toggle source
Calls superclass method
# File lib/datastax_rails/payload_model.rb, line 21
def self.inherited(child)
  super
  child.primary_key = 'digest'
  child.cluster_by = 'chunk'
  child.create_options = 'COMPACT STORAGE'
  child.string :digest
  child.binary :payload
  child.integer :chunk
  child.validates :digest, presence: true
end
write(record, options = {}) click to toggle source
# File lib/datastax_rails/payload_model.rb, line 53
def self.write(record, options = {})
  if options[:consistency] && !valid_consistency?(options[:consistency].to_s.upcase)
    fail ArgumentError, "'#{options[:consistency]}' is not a valid Cassandra consistency level"
  end
  c = cql.select('count(*)').conditions(digest: record.id)
  count = c.execute.first['count']

  i = 0
  io = StringIO.new(record.attributes['payload'])
  while (chunk = io.read(1.megabyte))
    c = cql.insert.columns(digest: record.id, chunk: i, payload: Base64.encode64(chunk))
    c.using(options[:consistency]) if options[:consistency]
    c.execute
    i += 1
  end

  # This probably doesn't make sense once we start enforcing digest to actually be the digest
  if count && count > i
    i.upto(count) do |j|
      c = cql.delete(digest: record.id, chunk: j)
      c.using(options[:consistency]) if options[:consistency]
      c.execute
    end
  end

  record.id
end

Public Instance Methods

id_for_destroy() click to toggle source
# File lib/datastax_rails/payload_model.rb, line 81
def id_for_destroy
  { digest: digest }
end