Class: TheFox::Timr::Model::BasicModel
- Inherits:
-
Object
- Object
- TheFox::Timr::Model::BasicModel
- Extended by:
- Error
- Includes:
- Error
- Defined in:
- lib/timr/model/basic_model.rb
Overview
Basic Class
Models hold data and can be stored to YAML files. Except for [Tracks](Track). Tracks are stored to a Task file.
Direct Known Subclasses
Config, ForeignIdDb, Stack, Task, Track
Instance Attribute Summary collapse
-
#file_path ⇒ Object
Path to file.
-
#has_changed ⇒ Object
When calling ‘save_to_file`, it will only write the file if `@has_changed` is `true`.
Class Method Summary collapse
-
.create_path_by_id(base_path, id) ⇒ Object
Converts an [SHA1](ruby-doc.org/stdlib-2.4.1/libdoc/digest/rdoc/Digest/SHA1.html) Hash into a path.
-
.find_file_by_id(base_path, id) ⇒ Object
Opposite of ‘get_id_from_path`.
-
.get_id_from_path(base_path, path) ⇒ Object
Opposite of ‘find_file_by_id`.
Instance Method Summary collapse
-
#changed ⇒ Object
Mark an object as changed.
-
#created=(created) ⇒ Object
Set created Time String.
-
#delete_file(path = nil) ⇒ Object
Delete the file.
-
#id ⇒ Object
Get ID.
-
#id=(id) ⇒ Object
Set ID.
-
#initialize ⇒ BasicModel
constructor
A new instance of BasicModel.
-
#load_from_file(path = nil) ⇒ Object
Load an entity into the current instance.
-
#modified=(modified) ⇒ Object
Set modified Time String.
-
#post_load_from_file ⇒ Object
Hook function for subclass called after ‘load_from_file` payload was executed.
-
#post_save_to_file ⇒ Object
Hook function for subclass called after ‘save_to_file` payload was executed.
-
#pre_load_from_file ⇒ Object
Hook function for subclass called before ‘load_from_file` payload will be executed.
-
#pre_save_to_file ⇒ Object
Hook function for subclass called before ‘save_to_file` payload will be executed.
-
#save_to_file(path = nil, force = false) ⇒ Object
Save an entity to a YAML file.
-
#short_id ⇒ Object
Get Short ID.
Constructor Details
#initialize ⇒ BasicModel
Returns a new instance of BasicModel.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/timr/model/basic_model.rb', line 27 def initialize # id 40 chars long. id = Digest::SHA1.hexdigest(UUID.new.generate) @meta = { 'id' => id, 'short_id' => id[0, 6], 'created' => Time.now.utc.strftime(MODEL_DATETIME_FORMAT), 'modified' => Time.now.utc.strftime(MODEL_DATETIME_FORMAT), } @data = nil @has_changed = false @file_path = nil end |
Instance Attribute Details
#file_path ⇒ Object
Path to file.
25 26 27 |
# File 'lib/timr/model/basic_model.rb', line 25 def file_path @file_path end |
#has_changed ⇒ Object
When calling ‘save_to_file`, it will only write the file if `@has_changed` is `true`.
22 23 24 |
# File 'lib/timr/model/basic_model.rb', line 22 def has_changed @has_changed end |
Class Method Details
.create_path_by_id(base_path, id) ⇒ Object
Converts an [SHA1](ruby-doc.org/stdlib-2.4.1/libdoc/digest/rdoc/Digest/SHA1.html) Hash into a path.
Function IO:
“‘ 3dd50a2b50eabc84022a23ad2c06d9bb6396f978 <- input 3d/d50a2b50eabc84022a23ad2c06d9bb6396f978 3d/d50a2b50eabc84022a23ad2c06d9bb6396f978 3d/d5/0a2b50eabc84022a23ad2c06d9bb6396f978 3d/d5/0a/2b50eabc84022a23ad2c06d9bb6396f978 3d/d5/0a/2b50eabc84022a23ad2c06d9bb6396f978.yml <- output “`
187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/timr/model/basic_model.rb', line 187 def create_path_by_id(base_path, id) if base_path.is_a?(String) base_path = Pathname.new(base_path) end unless id.is_a?(String) raise IdError, "ID is not a String. #{id.class} given." end if id.length <= 6 raise IdError, "ID is too short for creating a path. Minimum length: 7" end path_s = '%s/%s/%s/%s.yml' % [id[0, 2], id[2, 2], id[4, 2], id[6..-1]] Pathname.new(path_s).(base_path) end |
.find_file_by_id(base_path, id) ⇒ Object
Opposite of ‘get_id_from_path`.
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/timr/model/basic_model.rb', line 215 def find_file_by_id(base_path, id) if base_path.is_a?(String) base_path = Pathname.new(base_path) end unless id.is_a?(String) raise IdError, "ID '#{id}' is not a String. #{id.class} given." end if id.length < 4 raise IdError, "ID '#{id}' is too short for find. Minimum length: 4" end if id.length == 40 path = create_path_by_id(base_path, id) else # 12/34 search_path = '%s/%s' % [id[0, 2], id[2, 2]] if id.length >= 5 # 12/34/5 search_path << '/' << id[4] if id.length >= 6 # 12/34/56 search_path << id[5] if id.length >= 7 # 12/34/56/xxxxxx search_path << '/' << id[6..-1] end end end search_path << '*' path = nil base_path.find.each do |file| # Filter all directories. unless file.file? next end # Filter all non-yaml files. unless file.basename.fnmatch('*.yml') next end rel_path = file.relative_path_from(base_path) unless rel_path.fnmatch(search_path) next end if path raise ModelError.new(id), "ID '#{id}' is not a unique identifier." else path = file # Do not break the loop here. # Iterate all keys to make sure the ID is unique. end end end if path && path.exist? return path end raise ModelError, "Could not find a file for ID '#{id}' at #{base_path}." end |
.get_id_from_path(base_path, path) ⇒ Object
Opposite of ‘find_file_by_id`.
Function IO:
“‘ 3d/d5/0a/2b50eabc84022a23ad2c06d9bb6396f978.yml <- input 3dd50a2b50eabc84022a23ad2c06d9bb6396f978 <- output “`
210 211 212 |
# File 'lib/timr/model/basic_model.rb', line 210 def get_id_from_path(base_path, path) path.relative_path_from(base_path).to_s.gsub('/', '')[0..-5] end |
Instance Method Details
#changed ⇒ Object
Mark an object as changed. Only changed objects are stored to files on save_to_file().
70 71 72 73 |
# File 'lib/timr/model/basic_model.rb', line 70 def changed @meta['modified'] = Time.now.utc.strftime(MODEL_DATETIME_FORMAT) @has_changed = true end |
#created=(created) ⇒ Object
Set created Time String.
60 61 62 |
# File 'lib/timr/model/basic_model.rb', line 60 def created=(created) @meta['created'] = created end |
#delete_file(path = nil) ⇒ Object
Delete the file.
161 162 163 164 165 166 167 168 |
# File 'lib/timr/model/basic_model.rb', line 161 def delete_file(path = nil) path ||= @file_path if path.nil? raise ModelError, 'Path cannot be nil.' end path.delete end |
#id ⇒ Object
Get ID.
50 51 52 |
# File 'lib/timr/model/basic_model.rb', line 50 def id @meta['id'] end |
#id=(id) ⇒ Object
Set ID.
43 44 45 46 47 |
# File 'lib/timr/model/basic_model.rb', line 43 def id=(id) @meta['id'] = id changed end |
#load_from_file(path = nil) ⇒ Object
Load an entity into the current instance.
If ‘path` is not given `@file_path` will be taken. If `@file_path` is also not given throw ModelError exception.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/timr/model/basic_model.rb', line 78 def load_from_file(path = nil) load = pre_load_from_file if path.nil? path = @file_path if path.nil? raise ModelError, 'Path cannot be nil.' end else @file_path = path end if load content = YAML::load_file(path) @meta = content['meta'] @data = content['data'] @has_changed = false end post_load_from_file end |
#modified=(modified) ⇒ Object
Set modified Time String.
65 66 67 |
# File 'lib/timr/model/basic_model.rb', line 65 def modified=(modified) @meta['modified'] = modified end |
#post_load_from_file ⇒ Object
Hook function for subclass called after ‘load_from_file` payload was executed.
Subclasses can access ‘@meta` and `@data` to write values into instance variables, or to convert data to other formats.
See ‘pre_save_to_file`.
110 111 |
# File 'lib/timr/model/basic_model.rb', line 110 def post_load_from_file end |
#post_save_to_file ⇒ Object
Hook function for subclass called after ‘save_to_file` payload was executed.
157 158 |
# File 'lib/timr/model/basic_model.rb', line 157 def post_save_to_file end |
#pre_load_from_file ⇒ Object
Hook function for subclass called before ‘load_from_file` payload will be executed.
101 102 103 |
# File 'lib/timr/model/basic_model.rb', line 101 def pre_load_from_file true end |
#pre_save_to_file ⇒ Object
Hook function for subclass called before ‘save_to_file` payload will be executed.
Subclasses can modify ‘@meta` and `@data` in this method to store more informations to the meta Hash, or to convert data to other formats that can be better written to file.
For example, it’s probably better to convert a floating point number to a ‘%.2f` formatted String and convert it back to float on `post_load_from_file`.
See Floating Point Math <0.30000000000000004.com>.
152 153 154 |
# File 'lib/timr/model/basic_model.rb', line 152 def pre_save_to_file true end |
#save_to_file(path = nil, force = false) ⇒ Object
Save an entity to a YAML file.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/timr/model/basic_model.rb', line 114 def save_to_file(path = nil, force = false) store = pre_save_to_file if path.nil? path = @file_path if path.nil? raise ModelError, 'Path cannot be nil.' end else @file_path = path end if force || (store && @has_changed) @meta['modified'] = Time.now.utc.strftime(MODEL_DATETIME_FORMAT) # Create underlying directories. unless path.dirname.exist? path.dirname.mkpath end store = YAML::Store.new(path) store.transaction do store['meta'] = @meta store['data'] = @data end @has_changed = false end post_save_to_file end |
#short_id ⇒ Object
Get Short ID. Only 6 chars long.
55 56 57 |
# File 'lib/timr/model/basic_model.rb', line 55 def short_id @meta['id'][0, 6] end |