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, 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, 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 and content_hash will always be set.
To store a binary blob without filenames or content types, set the data attribute directly.
my_data = File.read('document.pdf')
document.update(data: my_data)
The data won't be stored until the record is saved, and only if the record is valid.
To retrieve your data, 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, 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
-
#data ⇒ String?
Returns the data as a binary string, or nil if no data has been set.
-
#data=(raw_data) ⇒ void
Assigns new data.
-
#data? ⇒ Boolean
Returns true if data is set.
-
#data_changed? ⇒ Boolean
Returns true if the data has been changed since the object was last saved.
-
#dis_stored? ⇒ Boolean
Returns true if the record has been persisted and its data has not been changed since the last save.
-
#file=(file) ⇒ void
Assigns new data from an uploaded file.
-
#open_data {|file| ... } ⇒ File, Object
Returns the data as an open, read-only file, or yields it and closes it afterwards.
-
#with_data_file {|path| ... } ⇒ Object
Yields the path to a file containing the data, for tools that need a file name rather than the bytes.
Instance Method Details
#data ⇒ String?
Returns the data as a binary string, or nil if no data has been set.
96 97 98 |
# File 'lib/dis/model.rb', line 96 def data dis_data.read end |
#data=(raw_data) ⇒ void
This method returns an undefined value.
Assigns new data. This also sets content_length and
content_hash.
112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/dis/model.rb', line 112 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.
103 104 105 |
# File 'lib/dis/model.rb', line 103 def data? dis_data.any? end |
#data_changed? ⇒ Boolean
Returns true if the data has been changed since the object was last saved.
128 129 130 |
# File 'lib/dis/model.rb', line 128 def data_changed? changes.include?("data") end |
#dis_stored? ⇒ Boolean
Returns true if the record has been persisted and its data has not been changed since the last save.
136 137 138 |
# File 'lib/dis/model.rb', line 136 def dis_stored? !(new_record? || data_changed?) end |
#file=(file) ⇒ void
This method returns an undefined value.
Assigns new data from an uploaded file. In addition to the
actions performed by #data=, this will set content_type
and filename.
148 149 150 151 152 |
# File 'lib/dis/model.rb', line 148 def file=(file) self.data = file dis_set :content_type, file.content_type dis_set :filename, file.original_filename end |
#open_data {|file| ... } ⇒ File, Object
Returns the data as an open, read-only file, or yields it and closes it afterwards. The data stays readable until the file is closed, even if the content is deleted or evicted meanwhile.
174 175 176 177 178 179 180 181 182 183 |
# File 'lib/dis/model.rb', line 174 def open_data file = dis_data.open return file unless block_given? begin yield file ensure file.close unless file.closed? end end |
#with_data_file {|path| ... } ⇒ Object
Yields the path to a file containing the data, for tools that need a file name rather than the bytes. The path is valid for the duration of the block only, so resolve anything lazy before returning.
164 165 166 |
# File 'lib/dis/model.rb', line 164 def with_data_file(&) dis_data.with_file(&) end |