Class: Miasma::Models::Storage::Local

Inherits:
Miasma::Models::Storage show all
Includes:
Contrib::LocalApiCore::ApiCommon
Defined in:
lib/miasma/contrib/local/storage.rb

Instance Method Summary collapse

Methods included from Contrib::LocalApiCore::ApiCommon

included

Constructor Details

#initialize(args = {}) ⇒ self

Create new instance

Parameters:

  • args (Hash) (defaults to: {})


16
17
18
19
20
21
# File 'lib/miasma/contrib/local/storage.rb', line 16

def initialize(args={})
  super
  unless(::File.directory?(object_store_root))
    FileUtils.mkdir_p(object_store_root)
  end
end

Instance Method Details

#bucket_allArray<Models::Storage::Bucket>

Return all buckets

Returns:

  • (Array<Models::Storage::Bucket>)


68
69
70
71
72
73
74
75
76
77
78
# File 'lib/miasma/contrib/local/storage.rb', line 68

def bucket_all
  Dir.new(object_store_root).map do |item|
    if(::File.directory?(item) && !item.start_with?('.'))
      Bucket.new(
        self,
        :id => ::File.basename(uri_unescape(item)),
        :name => ::File.basename(uri_unescape(item))
      ).valid_state
    end
  end.compact
end

#bucket_destroy(bucket) ⇒ TrueClass, FalseClass

Destroy bucket

Parameters:

  • bucket (Models::Storage::Bucket)

Returns:

  • (TrueClass, FalseClass)


40
41
42
43
44
45
46
47
# File 'lib/miasma/contrib/local/storage.rb', line 40

def bucket_destroy(bucket)
  if(bucket.persisted?)
    FileUtils.rmdir(full_path(bucket))
    true
  else
    false
  end
end

#bucket_path(bucket) ⇒ String

Returns escaped bucket name.

Returns:

  • (String)

    escaped bucket name



204
205
206
# File 'lib/miasma/contrib/local/storage.rb', line 204

def bucket_path(bucket)
  ::File.join(object_store_root, uri_escape(bucket.name))
end

#bucket_reload(bucket) ⇒ Models::Storage::Bucket

Reload the bucket

Parameters:

  • bucket (Models::Storage::Bucket)

Returns:

  • (Models::Storage::Bucket)


53
54
55
56
57
58
59
60
61
62
63
# File 'lib/miasma/contrib/local/storage.rb', line 53

def bucket_reload(bucket)
  if(bucket.persisted?)
    unless(::File.directory?(full_path(bucket)))
      bucket.data.clear
      bucket.dirty.clear
    else
      bucket.valid_state
    end
  end
  bucket
end

#bucket_save(bucket) ⇒ Models::Storage::Bucket

Save bucket

Parameters:

  • bucket (Models::Storage::Bucket)

Returns:

  • (Models::Storage::Bucket)


27
28
29
30
31
32
33
34
# File 'lib/miasma/contrib/local/storage.rb', line 27

def bucket_save(bucket)
  unless(bucket.persisted?)
    FileUtils.mkdir_p(full_path(bucket))
    bucket.id = bucket.name
    bucket.valid_state
  end
  bucket
end

#file_all(bucket) ⇒ Array<File>

TODO:

pagination auto-follow

Return all files within bucket

Parameters:

  • bucket (Bucket)

Returns:

  • (Array<File>)


105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/miasma/contrib/local/storage.rb', line 105

def file_all(bucket)
  Dir.glob(::File.join(full_path(bucket), '*')).map do |item|
    if(::File.file?(item) && !item.start_with?('.'))
      item_name = item.sub("#{full_path(bucket)}/", '')
      item_name = uri_unescape(item_name)
      File.new(
        bucket,
        :id => ::File.join(bucket.name, item_name),
        :name => item_name,
        :updated => File.mtime(item),
        :size => File.size(item)
      ).valid_state
    end
  end.compact
end

#file_body(file) ⇒ IO, HTTP::Response::Body

Fetch the contents of the file

Parameters:

  • file (Models::Storage::File)

Returns:

  • (IO, HTTP::Response::Body)


191
192
193
194
195
196
197
198
199
200
201
# File 'lib/miasma/contrib/local/storage.rb', line 191

def file_body(file)
  if(file.persisted?)
    tmp_file = Tempfile.new('miasma')
    tmp_file.delete
    FileUtils.cp(full_path(file), tmp_file.path)
    tmp_file.open
    tmp_file
  else
    StringIO.new('')
  end
end

#file_destroy(file) ⇒ TrueClass, FalseClass

Destroy file

Parameters:

  • file (Models::Storage::File)

Returns:

  • (TrueClass, FalseClass)


147
148
149
150
151
152
153
154
# File 'lib/miasma/contrib/local/storage.rb', line 147

def file_destroy(file)
  if(file.persisted?)
    FileUtils.rm(full_path(file))
    true
  else
    false
  end
end

#file_filter(bucket, args) ⇒ Array<Models::Storage::File>

Return filtered files

Parameters:

  • args (Hash)

    filter options

Returns:

  • (Array<Models::Storage::File>)


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/miasma/contrib/local/storage.rb', line 84

def file_filter(bucket, args)
  Dir.glob(::File.join(full_path(bucket), uri_escape(args[:prefix]), '*')).map do |item|
    if(::File.file?(item) && !item.start_with?('.'))
      item_name = item.sub("#{full_path(bucket)}/", '')
      item_name = uri_unescape(item_name)
      File.new(
        bucket,
        :id => ::File.join(bucket.name, item_name),
        :name => item_name,
        :updated => File.mtime(item),
        :size => File.size(item)
      ).valid_state
    end
  end.compact
end

#file_path(file) ⇒ String

Returns escaped file path.

Returns:

  • (String)

    escaped file path



209
210
211
212
213
# File 'lib/miasma/contrib/local/storage.rb', line 209

def file_path(file)
  file.name.split('/').map do |part|
    uri_escape(part)
  end.join('/')
end

#file_reload(file) ⇒ Models::Storage::File

Reload the file

Parameters:

  • file (Models::Storage::File)

Returns:

  • (Models::Storage::File)


160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/miasma/contrib/local/storage.rb', line 160

def file_reload(file)
  if(file.persisted?)
    new_info = Smash.new.tap do |data|
      data[:updated] = File.mtime(full_path(file))
      data[:size] = File.size(file_path(file))
      data[:etag] = Digest::MD5.hexdigest(content)
      data[:content_type] = MIME::Types.of(full_path(file))
    end
    file.load_data(file.attributes.deep_merge(new_info))
    file.valid_state
  end
  file
end

#file_save(file) ⇒ Models::Storage::File

Save file

Parameters:

  • file (Models::Storage::File)

Returns:

  • (Models::Storage::File)


125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/miasma/contrib/local/storage.rb', line 125

def file_save(file)
  if(file.dirty?)
    file.load_data(file.attributes)
    if(file.attributes[:body].is_a?(IO))
      file.body.rewind
      tmp_file = Tempfile.new('miasma')
      while(content = file.body.read(Storage::READ_BODY_CHUNK_SIZE))
        tmp_file.write content
      end
      tmp_file.close
      FileUtils.mv(tmp_file.path, full_path(file))
    end
    file.id = ::File.join(file.bucket.name, file.name)
    file.reload
  end
  file
end

#file_url(file, timeout_secs) ⇒ String

TODO:

where is this in swift?

Create publicly accessible URL

Parameters:

  • timeout_secs (Integer)

    seconds available

Returns:

  • (String)

    URL



179
180
181
182
183
184
185
# File 'lib/miasma/contrib/local/storage.rb', line 179

def file_url(file, timeout_secs)
  if(file.persisted?)
    raise NotImplementedError
  else
    raise Error::ModelPersistError.new "#{file} has not been saved!"
  end
end

#full_path(file_or_bucket) ⇒ String

Provide full path for object

Parameters:

  • file_or_bucket (File, Bucket)

Returns:

  • (String)


219
220
221
222
223
224
225
226
# File 'lib/miasma/contrib/local/storage.rb', line 219

def full_path(file_or_bucket)
  path = ''
  if(file_or_bucket.respond_to?(:bucket))
    path << '/' << bucket_path(file_or_bucket.bucket)
  end
  path << '/' << file_path(file_or_bucket)
  path
end

#uri_escape(string) ⇒ String

TODO:

move this to common module

URL string escape

Parameters:

  • string (String)

    string to escape

Returns:

  • (String)

    escaped string



233
234
235
236
237
# File 'lib/miasma/contrib/local/storage.rb', line 233

def uri_escape(string)
  string.to_s.gsub(/([^a-zA-Z0-9_.\-~])/) do
    '%' << $1.unpack('H2' * $1.bytesize).join('%').upcase
  end
end

#uri_unescape(string) ⇒ String

Un-escape URL escaped string

Parameters:

  • string (String)

Returns:

  • (String)


243
244
245
246
247
# File 'lib/miasma/contrib/local/storage.rb', line 243

def uri_unescape(string)
  string.to_s.gsub(/%([^%]{2})/) do
    [$1].pack('H2')
  end
end