Class: DatastaxRails::PayloadModel

Inherits:
WideStorageModel show all
Includes:
CassandraOnlyModel
Defined in:
lib/datastax_rails/payload_model.rb

Overview

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

Constant Summary

Constants included from Callbacks

Callbacks::CALLBACKS

Instance Attribute Summary

Attributes inherited from Base

#attributes, #key, #loaded_attributes

Attributes included from AutosaveAssociation

#destroyed_by_association, #marked_for_destruction

Attributes included from Associations

#association_cache

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from WideStorageModel

#id_for_update

Methods inherited from Base

#==, attribute_names, #attribute_names, base_class, #column_names, columns, default_page_size, #eql?, find_by_id, #freeze, #frozen?, #hash, #init_changed_attributes, #init_internals, #init_with, #initialize, #inspect, inspect, logger, models, payload_model?, search_ids, #to_param, valid_consistency?, #valid_consistency?, wide_storage_model?

Methods included from SolrRepair

#repair_solr

Methods included from Serialization

#serializable_hash, #to_xml

Methods included from Timestamps

#initialize_dup

Methods included from Scoping

#populate_with_current_scope_attributes

Methods included from AutosaveAssociation

#changed_for_autosave?, #mark_for_destruction, #reload

Methods included from Associations

#association, #clear_association_cache

Methods included from Callbacks

#destroy

Methods included from Validations

#save, #save!, #valid?

Methods included from AttributeMethods

#attribute_exists?, #attribute_for_inspect, #column_for_attribute, #method_missing, #respond_to?

Methods included from AttributeAssignment

#assign_attributes

Methods included from Batches

#find_each, #find_each_with_index, #find_in_batches

Methods included from FinderMethods

#find, #find_by, #find_by!, #first, #first!, #last, #last!

Methods included from Persistence

#destroy, #persisted?, #reload, #save, #save!, #toggle, #toggle!, #update_attribute, #update_attributes, #update_attributes!

Constructor Details

This class inherits a constructor from DatastaxRails::Base

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class DatastaxRails::AttributeMethods

Class Method Details

.find(digest, options = {}) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 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) ⇒ Object



21
22
23
24
25
26
27
28
29
30
# 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 = {}) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 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

Instance Method Details

#id_for_destroyObject



81
82
83
# File 'lib/datastax_rails/payload_model.rb', line 81

def id_for_destroy
  { digest: digest }
end