Class: Timet::Database
- Inherits:
-
Object
- Object
- Timet::Database
- Defined in:
- lib/timet/database.rb
Overview
Provides database access for managing time tracking data.
Constant Summary collapse
- DEFAULT_DATABASE_PATH =
The default path to the SQLite database file.
File.join(Dir.home, '.timet', 'timet.db')
Class Method Summary collapse
-
.determine_status(result) ⇒ Symbol
Determines the status of a time tracking result based on the presence and end time of items.
-
.move_old_database_file(database_path) ⇒ Object
Moves the old database file to the new location if it exists.
Instance Method Summary collapse
-
#add_column(table_name, new_column_name, date_type) ⇒ void
Adds a new column to the specified table if it does not already exist.
-
#all_items ⇒ Array
Fetches all items from the items table that have a start time greater than or equal to today.
-
#close ⇒ void
Closes the database connection.
- #column_exists?(new_column_name) ⇒ Boolean
-
#create_table ⇒ void
Creates the items table if it doesn’t already exist.
-
#delete_item(id) ⇒ void
Deletes an item from the items table.
-
#execute_sql(sql, params = []) ⇒ Array
Executes a SQL query and returns the result.
-
#fetch_last_id ⇒ Integer?
Fetches the ID of the last inserted item.
-
#find_item(id) ⇒ Array?
Finds an item by its ID.
-
#initialize(database_path = DEFAULT_DATABASE_PATH) ⇒ void
constructor
Initializes a new instance of the Database class.
-
#insert_item(*args) ⇒ void
Inserts a new item into the items table.
-
#item_status(id = nil) ⇒ Symbol
Determines the status of the last item in the items table.
-
#last_item ⇒ Array?
Fetches the last item from the items table.
-
#seconds_to_hms(seconds) ⇒ String
Converts a given number of seconds into a human-readable HH:MM:SS format.
-
#update_item(id, field, value) ⇒ void
Updates an existing item in the items table.
-
#update_time_columns ⇒ void
Updates the
updated_atandcreated_atcolumns for items where either of these columns is null. - #update_timestamp_for_item(id, fallback_time) ⇒ Object
Constructor Details
#initialize(database_path = DEFAULT_DATABASE_PATH) ⇒ void
The method creates a new SQLite3 database connection and initializes the necessary tables if they
Initializes a new instance of the Database class.
connection and creating the necessary tables.
do not already exist.
26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/timet/database.rb', line 26 def initialize(database_path = DEFAULT_DATABASE_PATH) self.class.move_old_database_file(database_path) @db = SQLite3::Database.new(database_path) create_table add_column('items', 'notes', 'TEXT') add_column('items', 'pomodoro', 'INTEGER') add_column('items', 'updated_at', 'INTEGER') add_column('items', 'created_at', 'INTEGER') add_column('items', 'deleted', 'INTEGER') update_time_columns end |
Class Method Details
.determine_status(result) ⇒ Symbol
The method checks if the result set is empty and returns :no_items if true.
If the last item in the result set has no end time, it returns :in_progress.
If the last item in the result set has an end time, it returns :complete.
Determines the status of a time tracking result based on the presence and end time of items.
:no_items, :in_progress, or :complete.
285 286 287 288 289 290 291 292 |
# File 'lib/timet/database.rb', line 285 def self.determine_status(result) return :no_items unless result last_item_end = result[2] return :in_progress unless last_item_end :complete end |
.move_old_database_file(database_path) ⇒ Object
Moves the old database file to the new location if it exists.
297 298 299 300 301 302 303 304 |
# File 'lib/timet/database.rb', line 297 def self.move_old_database_file(database_path) old_file = File.join(Dir.home, '.timet.db') return unless File.exist?(old_file) dir = File.dirname(database_path) FileUtils.mkdir_p(dir) unless File.directory?(dir) FileUtils.mv(old_file, database_path) end |
Instance Method Details
#add_column(table_name, new_column_name, date_type) ⇒ void
The method first checks if the column already exists in the table using pragma_table_info.
If the column exists, the method returns without making any changes.
If the column does not exist, the method executes an SQL ‘ALTER TABLE` statement to add the column.
The method prints a message indicating that the column has been added.
This method returns an undefined value.
Adds a new column to the specified table if it does not already exist.
printing a message.
75 76 77 78 79 80 81 82 83 |
# File 'lib/timet/database.rb', line 75 def add_column(table_name, new_column_name, date_type) raise 'Invalid table name' unless table_name == 'items' raise 'Invalid column name' unless /\A[a-zA-Z0-9_]+\z/.match?(new_column_name) raise 'Invalid date type' unless %w[INTEGER TEXT BOOLEAN].include?(date_type) return if column_exists?(new_column_name) execute_sql("ALTER TABLE #{table_name} ADD COLUMN #{new_column_name} #{date_type}") puts "Column '#{new_column_name}' added to table '#{table_name}'." end |
#all_items ⇒ Array
The method executes SQL to fetch all items from the ‘items’ table that have a start time greater than
Fetches all items from the items table that have a start time greater than or equal to today.
or equal to today.
197 198 199 200 201 |
# File 'lib/timet/database.rb', line 197 def all_items today = TimeHelper.beginning_of_day.to_i execute_sql('SELECT * FROM items WHERE start >= ? AND (deleted IS NULL OR deleted = 0) ORDER BY start DESC', [today]) end |
#close ⇒ void
The method closes the SQLite3 database connection.
This method returns an undefined value.
Closes the database connection.
database connection.
244 245 246 |
# File 'lib/timet/database.rb', line 244 def close @db&.close end |
#column_exists?(new_column_name) ⇒ Boolean
85 86 87 88 |
# File 'lib/timet/database.rb', line 85 def column_exists?(new_column_name) execute_sql("SELECT count(*) FROM pragma_table_info('items') where name=?", [new_column_name]).first.first.positive? end |
#create_table ⇒ void
The method executes SQL to create the ‘items’ table with columns for id, start, end, and tag.
This method returns an undefined value.
Creates the items table if it doesn’t already exist.
create the table.
49 50 51 52 53 54 55 56 57 58 |
# File 'lib/timet/database.rb', line 49 def create_table execute_sql(" CREATE TABLE IF NOT EXISTS items (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n start INTEGER,\n end INTEGER,\n tag TEXT\n );\n SQL\nend\n") |
#delete_item(id) ⇒ void
The method executes SQL to delete the item with the given ID from the ‘items’ table.
This method returns an undefined value.
Deletes an item from the items table.
to delete the item.
141 142 143 144 |
# File 'lib/timet/database.rb', line 141 def delete_item(id) current_time = Time.now.to_i execute_sql('UPDATE items SET deleted = 1, updated_at = ? WHERE id = ?', [current_time, id]) end |
#execute_sql(sql, params = []) ⇒ Array
The method executes the given SQL query with the provided parameters and returns the result.
Executes a SQL query and returns the result.
231 232 233 |
# File 'lib/timet/database.rb', line 231 def execute_sql(sql, params = []) @db.execute(sql, params) end |
#fetch_last_id ⇒ Integer?
The method executes SQL to fetch the ID of the last inserted item.
Fetches the ID of the last inserted item.
154 155 156 157 |
# File 'lib/timet/database.rb', line 154 def fetch_last_id execute_sql('SELECT id FROM items WHERE deleted IS NULL OR deleted = 0 ORDER BY id DESC LIMIT 1') .then { |result| result.empty? ? nil : result.first.first } end |
#find_item(id) ⇒ Array?
The method executes a SQL query to find the item by its ID.
If the item is found, it returns the item as an array.
If the item is not found, it returns nil.
Finds an item by its ID.
184 185 186 |
# File 'lib/timet/database.rb', line 184 def find_item(id) execute_sql('SELECT * FROM items WHERE id = ?', [id]).first&.dup end |
#insert_item(*args) ⇒ void
The method executes SQL to insert a new row into the ‘items’ table.
This method returns an undefined value.
Inserts a new item into the items table.
to insert the item.
103 104 105 106 107 108 |
# File 'lib/timet/database.rb', line 103 def insert_item(*args) # Unpacking args into meaningful variables for clarity start, tag, notes, pomodoro, updated_at, created_at = args execute_sql('INSERT INTO items (start, tag, notes, pomodoro, updated_at, created_at) VALUES (?, ?, ?, ?, ?, ?)', [start, tag, notes, pomodoro, updated_at, created_at]) end |
#item_status(id = nil) ⇒ Symbol
The method executes SQL to fetch the last item and determines its status using the StatusHelper module.
Determines the status of the last item in the items table.
215 216 217 218 |
# File 'lib/timet/database.rb', line 215 def item_status(id = nil) id ||= fetch_last_id self.class.determine_status(find_item(id)) end |
#last_item ⇒ Array?
The method executes SQL to fetch the last item from the ‘items’ table.
Fetches the last item from the items table.
167 168 169 170 |
# File 'lib/timet/database.rb', line 167 def last_item execute_sql('SELECT * FROM items WHERE deleted IS NULL OR deleted = 0 ORDER BY id DESC LIMIT 1') .then { |result| result.empty? ? nil : result.first } end |
#seconds_to_hms(seconds) ⇒ String
The method converts the given number of seconds into hours, minutes, and seconds, and formats
Converts a given number of seconds into a human-readable HH:MM:SS format.
them as HH:MM:SS.
259 260 261 262 263 264 |
# File 'lib/timet/database.rb', line 259 def seconds_to_hms(seconds) hours, remainder = seconds.divmod(3600) minutes, seconds = remainder.divmod(60) format '%<hours>02d:%<minutes>02d:%<seconds>02d', hours: hours, minutes: minutes, seconds: seconds end |
#update_item(id, field, value) ⇒ void
The method executes SQL to update the specified field of the item with the given ID.
This method returns an undefined value.
Updates an existing item in the items table.
to update the item.
123 124 125 126 127 128 |
# File 'lib/timet/database.rb', line 123 def update_item(id, field, value) allowed_fields = %w[tag notes start end deleted updated_at created_at] raise "Invalid field: #{field}" unless allowed_fields.include?(field) execute_sql("UPDATE items SET #{field} = ?, updated_at = ? WHERE id = ?", [value, Time.now.utc.to_i, id]) end |
#update_time_columns ⇒ void
This method directly executes SQL queries on the database. Ensure that the execute_sql method is properly
This method returns an undefined value.
Updates the updated_at and created_at columns for items where either of these columns is null.
This method queries the database for items where the updated_at or created_at columns are null. For each item found, it sets both the updated_at and created_at columns to the value of the end_time column.
defined and handles SQL injection risks.
321 322 323 324 |
# File 'lib/timet/database.rb', line 321 def update_time_columns execute_sql('SELECT * FROM items WHERE updated_at IS NULL OR created_at IS NULL') .each { |item| (item[0], item[2] || item[1] || Time.now.to_i) } end |
#update_timestamp_for_item(id, fallback_time) ⇒ Object
326 327 328 |
# File 'lib/timet/database.rb', line 326 def (id, fallback_time) execute_sql('UPDATE items SET updated_at = ?, created_at = ? WHERE id = ?', [fallback_time, fallback_time, id]) end |