Class: Atech::ObjectStore::File

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

Defined Under Namespace

Classes: CannotEditFrozenFile, FileDataTooBig, FileNotFound, InsertError, 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



87
88
89
# File 'lib/atech/object_store/file.rb', line 87

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:



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/atech/object_store/file.rb', line 60

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

  last_insert_id = insert_into_database(options)

  ## Return a new File object
  self.new(options.merge(:id => last_insert_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.



47
48
49
50
51
52
53
54
55
56
# File 'lib/atech/object_store/file.rb', line 47

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 single query on a backend connection. This should only be used when running a single query. If you need to do multiple things on the same connection (e.g. INSERT and then get LAST_INSERT_ID) you should checkot your own connection using ObejctStore::Connection.client



22
23
24
25
26
27
28
29
30
# File 'lib/atech/object_store/file.rb', line 22

def self.execute_query(query)
  tries ||= 3
  ObjectStore::Connection.client do |client|
    client.query(query)
  end
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.



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

def self.find_by_id(id)
  result = File.execute_query("SELECT * FROM files WHERE id = #{id.to_i}")
  result = result.first if result

  if result
    self.new(result)
  else
    raise(FileNotFound, "File not found with id '#{id.to_i}'")
  end
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.



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

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



122
123
124
# File 'lib/atech/object_store/file.rb', line 122

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.



133
134
135
# File 'lib/atech/object_store/file.rb', line 133

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

#created_atObject

Returns the date the file was created



112
113
114
# File 'lib/atech/object_store/file.rb', line 112

def created_at
  @attributes['created_at']
end

#deleteObject

Removes the file from the database



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

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)


127
128
129
# File 'lib/atech/object_store/file.rb', line 127

def frozen?
  !!@frozen
end

#idObject

Returns the ID of the file



97
98
99
# File 'lib/atech/object_store/file.rb', line 97

def id
  @attributes['id']
end

#inspectObject

Returns details about the file



92
93
94
# File 'lib/atech/object_store/file.rb', line 92

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

#nameObject

Returns the name of the file



102
103
104
# File 'lib/atech/object_store/file.rb', line 102

def name
  @attributes['name']
end

#overwrite(data) ⇒ Object

Overwrites any data which is stored in the file



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

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



168
169
170
171
# File 'lib/atech/object_store/file.rb', line 168

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



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

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



107
108
109
# File 'lib/atech/object_store/file.rb', line 107

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

#updated_atObject

Returns the date the file was last updated



117
118
119
# File 'lib/atech/object_store/file.rb', line 117

def updated_at
  @attributes['updated_at']
end