Class: Atech::ObjectStore::File

Inherits:
Object
  • Object
show all
Defined in:
lib/atech/object_store/file.rb

Defined Under Namespace

Classes: CannotEditFrozenFile, FileDataTooBig, FileNotFound, ValidationError

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes) ⇒ File

Initialises a new File object with the hash of attributes from a MySQL query ensuring that all symbols are strings



79
80
81
# File 'lib/atech/object_store/file.rb', line 79

def initialize(attributes)
  @attributes = parsed_attributes(attributes)
end

Class Method Details

.add_file(filename, data = '', options = {}) ⇒ Object

Inserts a new File into the database. Returns a new object if successfully inserted or raises an error. Filename & data must be provided, options options will be added automatically unless specified.

Raises:



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/atech/object_store/file.rb', line 48

def self.add_file(filename, data = '', options = {})

  if data.bytesize > Atech::ObjectStore.maximum_file_size
    raise FileDataTooBig, "Data provided was #{data.bytesize} and the maximum size is #{Atech::ObjectStore.maximum_file_size}"
  end

  ## Create a hash of properties to be for this class
  options[:name]          = filename
  options[:size]        ||= data.bytesize
  options[:blob]          = data
  options[:created_at]  ||= Time.now
  options[:updated_at]  ||= Time.now

  ## Ensure that new files have a filename & data
  raise ValidationError, "A 'name' must be provided to add a new file" if options[:name].nil?

  ## Encode timestamps
  options[:created_at] = options[:created_at].utc
  options[:updated_at] = options[:updated_at].utc

  ##Create an insert query
  columns = options.keys.join('`,`')
  data    = options.values.map { |data| escape_and_quote(data) }.join(',')
  File.execute_query("INSERT INTO files (`#{columns}`) VALUES (#{data})")

  ## Return a new File object
  self.new(options.merge({:id => ObjectStore.backend.last_id}))
end

.add_local_file(path) ⇒ Object

Imports a new file by passing a path and returning a new File object once it has been added to the database. If the file does not exist a ValidationError will be raised.



35
36
37
38
39
40
41
42
43
44
# File 'lib/atech/object_store/file.rb', line 35

def self.add_local_file(path)
  if ::File.exist?(path)
    file_stat = ::File.stat(path)
    file_data = ::File.read(path)
    file_name = path.split('/').last
    add_file(file_name, file_data, :created_at => file_stat.ctime, :updated_at => file_stat.mtime)
  else
    raise ValidationError, "File does not exist at '#{path}' to add"
  end
end

.execute_query(query) ⇒ Object

Run a query on the backend database, attempt to run the query up to 3 times



18
19
20
21
22
23
24
# File 'lib/atech/object_store/file.rb', line 18

def self.execute_query(query)
  tries ||= 3
  ObjectStore.backend.query(query)
rescue Mysql2::Error => e
  retry unless (tries -= 1).zero?
  raise
end

.find_by_id(id) ⇒ Object

Returns a new file object for the given ID. If no file is found a FileNotFound exception will be raised otherwise the File object will be returned.



28
29
30
31
# File 'lib/atech/object_store/file.rb', line 28

def self.find_by_id(id)
  result = File.execute_query("SELECT * FROM files WHERE id = #{id.to_i}").first || raise(FileNotFound, "File not found with id '#{id.to_i}'")
  self.new(result)
end

Instance Method Details

#append(data) ⇒ Object

Appends data to the end of the current blob and updates the size and update time as appropriate.



130
131
132
133
134
# File 'lib/atech/object_store/file.rb', line 130

def append(data)
  raise CannotEditFrozenFile, "This file has been frozen and cannot be appended to" if frozen?
  File.execute_query("UPDATE files SET `blob` = CONCAT(`blob`, #{self.class.escape_and_quote(data)}), `size` = `size` + #{data.bytesize}, `updated_at` = '#{self.class.time_now}' WHERE id = #{@attributes['id']}")
  reload(true)
end

#blobObject

Returns the blob data



114
115
116
# File 'lib/atech/object_store/file.rb', line 114

def blob
  @attributes['blob']
end

#copy(path) ⇒ Object

Downloads the current file to a path on your local server. If a file already exists at the path entered, it will be overriden.



125
126
127
# File 'lib/atech/object_store/file.rb', line 125

def copy(path)
  ::File.open(path, 'w') { |f| f.write(blob) }
end

#created_atObject

Returns the date the file was created



104
105
106
# File 'lib/atech/object_store/file.rb', line 104

def created_at
  @attributes['created_at']
end

#deleteObject

Removes the file from the database



152
153
154
155
156
# File 'lib/atech/object_store/file.rb', line 152

def delete
  raise CannotEditFrozenFile, "This file has been frozen and cannot be deleted" if frozen?
  File.execute_query("DELETE FROM files WHERE id = #{@attributes['id']}")
  @frozen = true
end

#frozen?Boolean

Returns whether this objec tis frozen or not

Returns:

  • (Boolean)


119
120
121
# File 'lib/atech/object_store/file.rb', line 119

def frozen?
  !!@frozen
end

#idObject

Returns the ID of the file



89
90
91
# File 'lib/atech/object_store/file.rb', line 89

def id
  @attributes['id']
end

#inspectObject

Returns details about the file



84
85
86
# File 'lib/atech/object_store/file.rb', line 84

def inspect
  "#<Atech::ObjectStore::File[#{id}] name=#{name}>"
end

#nameObject

Returns the name of the file



94
95
96
# File 'lib/atech/object_store/file.rb', line 94

def name
  @attributes['name']
end

#overwrite(data) ⇒ Object

Overwrites any data which is stored in the file



137
138
139
140
141
142
# File 'lib/atech/object_store/file.rb', line 137

def overwrite(data)
  raise CannotEditFrozenFile, "This file has been frozen and cannot be overwriten" if frozen?
  File.execute_query("UPDATE files SET `blob` = #{self.class.escape_and_quote(data)}, `size` = #{data.bytesize}, `updated_at` = '#{self.class.time_now}' WHERE id = #{@attributes['id']}")
  @attributes['blob'] = data
  reload
end

#reload(include_blob = false) ⇒ Object

Reload properties from the database. Optionally, pass true to include the blob in the update



160
161
162
163
# File 'lib/atech/object_store/file.rb', line 160

def reload(include_blob = false)
  query = File.execute_query("SELECT #{include_blob ? '*' : '`id`, `name`, `size`, `created_at`, `updated_at`'} FROM files WHERE id = #{@attributes['id']}").first
  @attributes.merge!(parsed_attributes(query))
end

#rename(name) ⇒ Object

Changes the name for a file



145
146
147
148
149
# File 'lib/atech/object_store/file.rb', line 145

def rename(name)
  raise CannotEditFrozenFile, "This file has been frozen and cannot be renamed" if frozen?
  File.execute_query("UPDATE files SET `name` = #{self.class.escape_and_quote(name)}, `updated_at` = '#{self.class.time_now}' WHERE id = #{@attributes['id']}")
  reload
end

#sizeObject

Returns the size of the file as an integer



99
100
101
# File 'lib/atech/object_store/file.rb', line 99

def size
  @attributes['size'].to_i
end

#updated_atObject

Returns the date the file was last updated



109
110
111
# File 'lib/atech/object_store/file.rb', line 109

def updated_at
  @attributes['updated_at']
end