Class: Safrano::Media::Static
- Defined in:
- lib/odata/collection_media.rb
Overview
Simple static File/Directory based media store handler similar to Rack::Static with a flat directory structure
Direct Known Subclasses
Instance Method Summary collapse
-
#abs_filename(entity) ⇒ Object
absolute filename.
-
#abs_media_directory(entity) ⇒ Object
the same as above but absolute.
-
#abs_path(entity) ⇒ Object
/@root/Photo/1.
-
#atomic_write(file_name) ⇒ Object
see also …
- #create_abs_class_dir ⇒ Object
- #create_abs_temp_dir ⇒ Object
-
#filename(entity) ⇒ Object
relative to @root eg Photo/1/1.
- #finalize ⇒ Object
-
#initialize(root: nil, mediaklass:) ⇒ Static
constructor
A new instance of Static.
-
#media_directory(entity) ⇒ Object
this is relative to abs_klass_dir(entity) eg to /@root/Photo simplest implementation is media_directory = entity.media_path_id –> we get a 1 level depth flat directory structure.
-
#media_path(entity) ⇒ Object
this is relative to @root eg.
- #odata_delete(entity:) ⇒ Object
-
#odata_get(request:, entity:) ⇒ Object
minimal working implementation…
- #register ⇒ Object
-
#replace_file(data:, entity:) ⇒ Object
Note: add a new Version and remove the previous one.
-
#ressource_version(entity) ⇒ Object
needed for having a changing media ressource “source” metadata after each upload, so that clients get informed about new versions of the same media ressource.
-
#save_file(data:, filename:, entity:) ⇒ Object
Here as well, MVP implementation.
-
#with_media_directory(entity) {|Pathname(mpi)| ... } ⇒ Object
yields the absolute path of media directory and ensure the directory exists.
Methods inherited from Handler
Constructor Details
#initialize(root: nil, mediaklass:) ⇒ Static
Returns a new instance of Static.
22 23 24 25 26 27 28 29 30 31 |
# File 'lib/odata/collection_media.rb', line 22 def initialize(root: nil, mediaklass:) super() @root = Pathname(File.absolute_path(root || Dir.pwd)) @files_class = ::Rack.release[0..2] == '2.0' ? ::Rack::File : ::Rack::Files @media_class = mediaklass @media_dir_name = Pathname(mediaklass.to_s) @semaphore = Thread::Mutex.new register end |
Instance Method Details
#abs_filename(entity) ⇒ Object
absolute filename
98 99 100 |
# File 'lib/odata/collection_media.rb', line 98 def abs_filename(entity) @root + filename(entity) end |
#abs_media_directory(entity) ⇒ Object
the same as above but absolute
110 111 112 |
# File 'lib/odata/collection_media.rb', line 110 def abs_media_directory(entity) @abs_klass_dir + entity.media_path_id end |
#abs_path(entity) ⇒ Object
/@root/Photo/1
93 94 95 |
# File 'lib/odata/collection_media.rb', line 93 def abs_path(entity) @root + media_path(entity) end |
#atomic_write(file_name) ⇒ Object
see also … File activesupport/lib/active_support/core_ext/file/atomic.rb, line 21
53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/odata/collection_media.rb', line 53 def atomic_write(file_name) Tempfile.open('', @abs_temp_dir) do |temp_file| temp_file.binmode return_val = yield temp_file temp_file.close # Overwrite original file with temp file File.rename(temp_file.path, file_name) return_val end end |
#create_abs_class_dir ⇒ Object
38 39 40 |
# File 'lib/odata/collection_media.rb', line 38 def create_abs_class_dir FileUtils.makedirs @abs_klass_dir end |
#create_abs_temp_dir ⇒ Object
42 43 44 |
# File 'lib/odata/collection_media.rb', line 42 def create_abs_temp_dir FileUtils.makedirs @abs_temp_dir end |
#filename(entity) ⇒ Object
relative to @root eg Photo/1/1
88 89 90 |
# File 'lib/odata/collection_media.rb', line 88 def filename(entity) media_path(entity) + ressource_version(entity) end |
#finalize ⇒ Object
46 47 48 49 |
# File 'lib/odata/collection_media.rb', line 46 def finalize create_abs_class_dir create_abs_temp_dir end |
#media_directory(entity) ⇒ Object
this is relative to abs_klass_dir(entity) eg to /@root/Photo simplest implementation is media_directory = entity.media_path_id –> we get a 1 level depth flat directory structure
105 106 107 |
# File 'lib/odata/collection_media.rb', line 105 def media_directory(entity) entity.media_path_id end |
#media_path(entity) ⇒ Object
this is relative to @root eg. Photo/1
82 83 84 |
# File 'lib/odata/collection_media.rb', line 82 def media_path(entity) @media_dir_name + media_directory(entity) end |
#odata_delete(entity:) ⇒ Object
122 123 124 125 126 127 |
# File 'lib/odata/collection_media.rb', line 122 def odata_delete(entity:) mpi = abs_media_directory(entity) return unless Dir.exist?(mpi) mpi.children.each { |oldp| File.delete(oldp) } end |
#odata_get(request:, entity:) ⇒ Object
minimal working implementation…
Note: files_app works relative to @root directory
67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/odata/collection_media.rb', line 67 def odata_get(request:, entity:) media_env = request.env.dup media_env['PATH_INFO'] = filename(entity) # new app instance for each call for thread safety files_app = @files_class.new(@root) fsret = files_app.call(media_env) if fsret.first == 200 # provide own content type as we keep it in the media entity fsret[1]['Content-Type'] = entity.content_type end fsret end |
#register ⇒ Object
33 34 35 36 |
# File 'lib/odata/collection_media.rb', line 33 def register @abs_klass_dir = @root + @media_dir_name @abs_temp_dir = @abs_klass_dir.join('tmp') end |
#replace_file(data:, entity:) ⇒ Object
Note: add a new Version and remove the previous one
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/odata/collection_media.rb', line 145 def replace_file(data:, entity:) with_media_directory(entity) do |d| tp = Tempfile.open('', @abs_temp_dir) do |temp_file| temp_file.binmode IO.copy_stream(data, temp_file) temp_file.path end # picking new filename and the "move" operation must # be protected @semaphore.synchronize do # new filename = "version" + 1 v = ressource_version(entity) filename = d + (v.to_i + 1).to_s # Move temp file to original target file File.rename(tp, filename) # remove the previous version filename = d + v File.delete(filename) end end end |
#ressource_version(entity) ⇒ Object
needed for having a changing media ressource “source” metadata after each upload, so that clients get informed about new versions of the same media ressource
140 141 142 |
# File 'lib/odata/collection_media.rb', line 140 def ressource_version(entity) abs_media_directory(entity).children(false).max.to_s end |
#save_file(data:, filename:, entity:) ⇒ Object
Here as well, MVP implementation
130 131 132 133 134 135 |
# File 'lib/odata/collection_media.rb', line 130 def save_file(data:, filename:, entity:) with_media_directory(entity) do |d| filename = d.join('1') atomic_write(filename) { |f| IO.copy_stream(data, f) } end end |
#with_media_directory(entity) {|Pathname(mpi)| ... } ⇒ Object
yields the absolute path of media directory and ensure the directory exists
116 117 118 119 120 |
# File 'lib/odata/collection_media.rb', line 116 def with_media_directory(entity) mpi = abs_media_directory(entity) FileUtils.mkdir_p mpi yield Pathname(mpi) end |