Module: Dis::Model

Extended by:
ActiveSupport::Concern
Defined in:
lib/dis/model.rb,
lib/dis/model/data.rb,
lib/dis/model/class_methods.rb

Overview

Dis Model

ActiveModel extension for the model holding your data. To use it, simply include the module in your model:

class Document < ActiveRecord::Base
  include Dis::Model
end

You’ll need to define a few attributes in your database table. Here’s a minimal migration:

create_table :documents do |t|
  t.string  :content_hash
  t.string  :content_type
  t.integer :content_length
  t.string  :filename
end

You can override the names of any of these by setting dis_attributes.

class Document < ActiveRecord::Base
  include Dis::Model
  self.dis_attributes = {
    filename:       :my_filename,
    content_length: :filesize
  }
end

Usage

To save a file, simply assign to the file attribute.

document = Document.create(file: params.permit(:file))

content_type and filename will automatically be set if the supplied object quacks like a file. content_length will always be set. content_hash won’t be set until the record is being saved.

If you don’t care about filenames and content types and just want to store a binary blob, you can also just set the data attribute.

my_data = File.read('document.pdf')
document.update(data: my_data)

The data won’t be stored until the record is saved, and not unless the record is valid.

To retrieve your data, simply read the data attribute. The file will be lazily loaded from the store on demand and cached in memory as long as the record stays in scope.

my_data = document.data

Destroying a record will delete the file from the store, unless another record also refers to the same hash. Similarly, stale files will be purged when content changes.

Validations

No validation is performed by default. If you want to ensure that data is present, use the validates_data_presence method.

class Document < ActiveRecord::Base
  include Dis::Model
  validates_data_presence
end

If you want to validate content types, size or similar, simply use standard Rails validations on the metadata attributes:

validates :content_type, presence: true, format: /\Aapplication\/pdf\z/
validates :filename, presence: true, format: /\A[\w_\-\.]+\.pdf\z/i
validates :content_length, numericality: { less_than: 5.megabytes }

Defined Under Namespace

Modules: ClassMethods Classes: Data

Instance Method Summary collapse

Instance Method Details

#dataObject

Returns the data as a binary string, or nil if no data has been set.



93
94
95
# File 'lib/dis/model.rb', line 93

def data
  dis_data.read
end

#data=(raw_data) ⇒ Object

Assigns new data. This also sets content_length, and resets content_hash to nil.



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/dis/model.rb', line 104

def data=(raw_data)
  new_data = Dis::Model::Data.new(self, raw_data)
  attribute_will_change!("data") unless new_data == dis_data
  @dis_data = new_data
  dis_set :content_hash, if raw_data.nil?
                           nil
                         else
                           Storage.file_digest(new_data.read)
                         end
  dis_set :content_length, dis_data.content_length
end

#data?Boolean

Returns true if data is set.

Returns:

  • (Boolean)


98
99
100
# File 'lib/dis/model.rb', line 98

def data?
  dis_data.any?
end

#data_changed?Boolean

Returns true if the data has been changed since the object was last saved.

Returns:

  • (Boolean)


117
118
119
# File 'lib/dis/model.rb', line 117

def data_changed?
  changes.include?("data")
end

#dis_stored?Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/dis/model.rb', line 121

def dis_stored?
  !(new_record? || data_changed?)
end

#file=(file) ⇒ Object

Assigns new data from an uploaded file. In addition to the actions performed by data=, this will set content_type and filename.



128
129
130
131
132
# File 'lib/dis/model.rb', line 128

def file=(file)
  self.data = file
  dis_set :content_type, file.content_type
  dis_set :filename, file.original_filename
end