timet 1.6.1.1 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5827ed2755115ce5974bb35145f83b6d0de26d94e2e0fc60983117a55d4d8854
4
- data.tar.gz: de50d2db6b024c348b65bc00fb6020b1d92dcf5eeb78138dc2e2dc59cb117296
3
+ metadata.gz: 84fa974afe30946a8b292569e74917c3992097e0ae652339320981f2951f298d
4
+ data.tar.gz: dc6cf2d3f5bd30feebb93db4aa07c436203e53bf1d9d0dbba5166695b622b021
5
5
  SHA512:
6
- metadata.gz: 400c4b23c9260412c3afeb9ed62ebd51c545d5b689bf165e7c6c90abd01e8c665dbcbf6eb690ff030c2a42a9f83c8e2fe58258995c9130630fd9e3597a1082b3
7
- data.tar.gz: 6be9dc88ef4eca0ef785d6d5272195a1d6ad3b5c6f5a65bc44bd12d2d36c5d0fef7f11b8cabe741e92b83fe782433ffb74f01d4635c061e6b9e95753c593a3d1
6
+ metadata.gz: 49cf7cc38f9e44687d27bee93a8de5678963fd92a9589241e38635afcdf4b86f8229d1c401483d2d6e955ee83e5423ca10f832f4beb0101873e60f5d0ff34821
7
+ data.tar.gz: 2098f1a3c297277bd07425961b3e84425a1189ae5984e21c35649a3a2c517a5a175dfd5b477abb59ba49f78925a9c4ec872006d3be025ddc4ee363bf86ff7004
data/.qlty/qlty.toml ADDED
File without changes
data/.reek.yml CHANGED
@@ -3,4 +3,20 @@ detectors:
3
3
  TooManyStatements:
4
4
  max_statements: 7
5
5
  UncommunicativeVariableName:
6
- enabled: false
6
+ enabled: false
7
+ FeatureEnvy:
8
+ exclude:
9
+ - fetch_last_id
10
+ - last_item
11
+ - update_time_columns
12
+ TooManyMethods:
13
+ max_methods: 20
14
+ exclude:
15
+ - ValidationEditor
16
+ LongParameterList:
17
+ exclude:
18
+ - process_and_update_time_field
19
+ - invalid_time_value?
20
+ DataClump:
21
+ exclude:
22
+ - TimeValidationHelpers
data/.rubocop.yml CHANGED
@@ -4,6 +4,11 @@ AllCops:
4
4
  SuggestExtensions: false
5
5
  Exclude:
6
6
  - timet.gemspec
7
+ - "vendor/**/*" # Exclude vendor/bundle gems
8
+
9
+ Metrics/ModuleLength:
10
+ Exclude:
11
+ - 'lib/timet/tag_distribution.rb'
7
12
 
8
13
  Metrics/MethodLength:
9
14
  Max: 15
@@ -11,7 +16,7 @@ Metrics/MethodLength:
11
16
  plugins: rubocop-rspec
12
17
 
13
18
  RSpec/ExampleLength:
14
- Max: 15
19
+ Max: 15
15
20
 
16
21
  Metrics/CyclomaticComplexity:
17
22
  Max: 8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,40 @@
1
+ ## [1.6.3] - 2026-02-28
2
+
3
+ **Improvements:**
4
+
5
+ - **Validation Architecture:** Refactored validation logic from `ValidationEditHelper` module to `ValidationEditor` class for better encapsulation and testability.
6
+ - **Synchronization & Storage:** Simplified `DatabaseSyncer` and `S3Supabase` by extracting modular helper methods, introducing `S3Config` module, and `S3ObjectRef` struct.
7
+ - **Reporting Features:** Added `export_csv` and `export_icalendar` methods to `TimeReport` for enhanced data portability.
8
+ - **Database Refactoring:** Converted `Timet::Database` methods to class methods where appropriate, extracted column checks, and simplified item fetching logic.
9
+ - **Tag Distribution:** Split `TagDistribution` into dedicated formatting and logic modules using a Context struct for clearer rendering.
10
+ - **Dependencies:** Updated `aws-sdk-s3` to `~> 1.213`, removed unused `httparty` gem, and bumped RuboCop, parser, and thor dependencies.
11
+ - **Code Quality:** Updated `.reek.yml` and RuboCop configs to accommodate new method structures, exclusions, and added code coverage badge to README.
12
+ - **Cleanup:** Removed obsolete helper modules (`item_data_helper`, `time_report_helper`, `time_update_helper`, `time_validation_helper`).
13
+
14
+ **Bug Fixes:**
15
+
16
+ - **Status Determination:** Added nil guards to `determine_status` to prevent runtime errors during item status checks.
17
+ - **Data Integrity:** Resolved duplicated `get_item_values` logic in syncer to ensure consistency during inserts and updates.
18
+ - **Validation Logic:** Updated validation methods to correctly handle end datetime adjustments for the next day.
19
+
20
+ ## [1.6.2] - 2025-12-28
21
+
22
+ **Improvements:**
23
+
24
+ - **Database Hardening:** Added strict validations for table/column names in `add_column` and allowed fields in `update_item`. `execute_sql` now raises `SQLite3::SQLException` instead of suppressing it, improving error visibility.
25
+ - **Time Parsing Robustness:** Enhanced `TimeHelper#update_time_field` to robustly parse "HH:MM:SS" and "HH:MM" time strings using proper time construction.
26
+ - **Documentation Updates:** Updated README with explicit examples for `resume --pomodoro` and `summary --report` usage, and improved command reference formatting.
27
+ - **Refactoring:** Renamed `Timet::Utils.convert_to_datetime` to `convert_to_time` to better reflect that it returns a `Time` object, and updated related specs.
28
+ - **Dependency Updates:** Updated `aws-sdk-s3` to `~> 1.209.0`, `dotenv` to `~> 3.2`, `rubocop-rake` to `~> 0.7`, and other dependencies in `Gemfile` and `Gemfile.lock`.
29
+ - **CI/CD Enhancements:** Replaced DeepSource integration with Qlty for code analysis and test coverage reporting. Simplified CI workflow and added RuboCop with `continue-on-error` configuration.
30
+ - **Code Quality:** Applied RuboCop fixes including frozen string literals, numeric predicate corrections, and redundant interpolation fixes.
31
+
32
+ **Bug Fixes:**
33
+
34
+ - **Data Consistency:** Updated `update_time_columns` to ensure `updated_at` and `created_at` are populated with a fallback time (start time or current time) if the end time is nil.
35
+ - **Error Propagation:** Fixed `execute_sql` to raise exceptions instead of silently returning empty arrays, improving debugging capabilities.
36
+ - **Configuration:** Updated `.rubocop.yml` to exclude vendor directory and prevent interference from gem configurations.
37
+
1
38
  ## [1.6.1] - 2025-10-10
2
39
 
3
40
  **New Features:**
@@ -11,7 +48,6 @@
11
48
  - **README Updates:** Added new examples for the `--search` option and updated the project homepage URL.
12
49
  - **Time Report Filtering:** Enhanced `TimeReport` to incorporate the `--search` option for filtering items by tag or notes.
13
50
 
14
-
15
51
  ## [1.6.0] - 2025-09-24
16
52
 
17
53
  **New Features:**
@@ -28,7 +64,6 @@
28
64
  - **README Updates:** Added new interactive mode examples for the `edit` command and updated the project homepage URL.
29
65
  - **Timezone Consistency:** Improved time handling in `ValidationEditHelper` specs by consistently using `Time.parse().getlocal()` for better timezone accuracy.
30
66
 
31
-
32
67
  ## [1.5.9] - 2025-07-30
33
68
 
34
69
  **Improvements:**
@@ -424,7 +459,6 @@
424
459
  **Improvements:**
425
460
 
426
461
  - **Refactor `TimeReport` to use `TimeReportHelper` module for utility methods:**
427
-
428
462
  - Extracted utility methods (`add_hashes`, `date_ranges`, `format_item`, `valid_date_format?`) into a new `TimeReportHelper` module.
429
463
  - Updated `TimeReport` class to include `TimeReportHelper` module.
430
464
  - Removed redundant utility methods from `TimeReport` class.
@@ -434,7 +468,6 @@
434
468
  - Adjusted formatting in `total` method for better alignment.
435
469
 
436
470
  - **Refactor `Timet::Formatter` to improve readability and modularity:**
437
-
438
471
  - Introduced a constant `CHAR_MAPPING` to store block characters for different value ranges.
439
472
  - Refactored `format_notes` method to use a more descriptive variable name for the maximum length.
440
473
  - Updated `format_tag_distribution` method to accept `colors` parameter and pass it to `process_and_print_tags`.
data/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/timet.svg)](https://badge.fury.io/rb/timet)
2
2
  ![timet workflow](https://github.com/frankvielma/timet/actions/workflows/ci.yml/badge.svg)
3
- [![DeepSource](https://app.deepsource.com/gh/frankvielma/timet.svg/?label=active+issues&show_trend=true&token=RV8_VCNrXIfEU7NL9mk9MSuP)](https://app.deepsource.com/gh/frankvielma/timet/)
3
+ [![Maintainability](https://qlty.sh/gh/frankvielma/projects/timet/maintainability.svg)](https://qlty.sh/gh/frankvielma/projects/timet)
4
+ [![Code Coverage](https://qlty.sh/gh/frankvielma/projects/timet/coverage.svg)](https://qlty.sh/gh/frankvielma/projects/timet)
5
+
4
6
  # Timet
5
7
 
6
8
  ![Timet](timet.webp)
7
9
 
8
-
9
10
  ## Table of Contents
10
11
 
11
12
  - [🔑 Key Features](#key-features)
@@ -19,7 +20,6 @@
19
20
  - [Contributing](#contributing)
20
21
  - [License](#license)
21
22
 
22
-
23
23
  [Timet](https://rubygems.org/gems/timet) is a command-line tool designed to track your activities by recording the time spent on each task. This tool allows you to monitor your work hours and productivity directly from your terminal, eliminating the need for a graphical interface. Essentially, it's a way to log your time spent on different projects or tasks using simple text commands.
24
24
 
25
25
  <h2 id="key-features">🔑 Key Features:</h2>
@@ -45,6 +45,7 @@
45
45
  ![Timet demo](timet1.gif)
46
46
 
47
47
  <a name="requirements"></a>
48
+
48
49
  <h2 id="requirements">✔️ Requirements</h2>
49
50
 
50
51
  - Ruby version: >= 3.0.0
@@ -56,6 +57,7 @@ For older versions of Ruby and Sqlite:
56
57
  - [Ruby >= 2.4](https://github.com/frankvielma/timet/tree/ruby-2.4.0)
57
58
 
58
59
  <a name="installation"></a>
60
+
59
61
  ## 💾 Installation
60
62
 
61
63
  Install the gem by executing:
@@ -65,6 +67,7 @@ gem install timet
65
67
  ```
66
68
 
67
69
  <a name="usage"></a>
70
+
68
71
  ## ⏳ Usage
69
72
 
70
73
  ### Command Aliases
@@ -125,6 +128,7 @@ gem install timet
125
128
  Once configured, Timet will automatically send a notification to your Discord channel when a Pomodoro session ends.
126
129
 
127
130
  ---
131
+
128
132
  ---
129
133
 
130
134
  - **`timet stop`:** Stops tracking the current task, records the elapsed time, and displays the total time spent on all tasks.
@@ -152,6 +156,12 @@ Once configured, Timet will automatically send a notification to your Discord ch
152
156
  timet resume 1
153
157
  ```
154
158
 
159
+ To resume with a Pomodoro timer:
160
+
161
+ ```bash
162
+ timet resume 1 --pomodoro=25
163
+ ```
164
+
155
165
  ```
156
166
  Tracked time report [today]:
157
167
  +-------+------------+--------+----------+----------+----------+--------------------------+
@@ -216,27 +226,33 @@ Once configured, Timet will automatically send a notification to your Discord ch
216
226
  ```
217
227
 
218
228
  <a name="command-reference"></a>
229
+
219
230
  ## 📋 Command Reference
220
231
 
221
- | Command | Description | Example Usage |
222
- | -------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------- |
223
- | `timet start [tag] --notes='' --pomodoro=[time]` | Start tracking time for a task labeled [tag] and notes (optional). | `timet start Task "My notes" 25` |
224
- | `timet stop` | Stop tracking time. | `timet stop` |
225
- | `timet summary today (t)` | Display a report of tracked time for today. | `timet su t` or `timet su` |
226
- | `timet summary yesterday (y)` | Display a report of tracked time for yesterday. | `timet su y` |
227
- | `timet summary week (w)` | Display a report of tracked time for the week. | `timet su w` |
228
- | `timet summary month (m)` | Display a report of tracked time for the month. | `timet su m` |
229
- | `timet su t --csv=[filename]` | Display a report of tracked time for today and export to CSV file | `timet su t --csv=file.csv` |
230
- | `timet su w --ics=[filename]` | Display a report of tracked time for week and export to iCalendar file | `timet su w --ics=file.csv` |
231
- | `timet su t --report` | Display a detailed report of tag distribution for today. | `timet su t --report` |
232
- | `timet summary [time_scope] --search=[query]`| Display a report of tracked time filtered by tag or notes. | `timet su week --search="bug"` |
233
- | `timet delete [id]` | Delete a task by its ID. | `timet d [id]` |
234
- | `timet cancel` | Cancel active time tracking. | `timet c` |
235
- | `timet edit [id]` | Update a task's notes, tag, start, or end fields. | `timet e [id]` |
236
- | `timet su [date]` | Display a report of tracked time for a specific date. | `timet su 2024-01-03` |
237
- | `timet su [start_date]..[end_date]` | Display a report of tracked time for a date range. | `timet su 2024-01-02..2024-01-03` |
238
- | `timet resume (r) [id]` | Resume tracking a task by ID or the last completed task. | `timet resume [id]` |
239
- | `timet sync` | Sync local db with remote (S3) external db | `timet sync` |
232
+ | Command | Description | Example Usage |
233
+ | ------------------------------------------------ | ---------------------------------------------------------------------- | --------------------------------- |
234
+ | `timet start [tag] --notes='' --pomodoro=[time]` | Start tracking time for a task labeled [tag] and notes (optional). | `timet start Task "My notes" 25` |
235
+ | `timet stop` | Stop tracking time. | `timet stop` |
236
+ | `timet summary today (t)` | Display a report of tracked time for today. | `timet su t` or `timet su` |
237
+ | `timet summary yesterday (y)` | Display a report of tracked time for yesterday. | `timet su y` |
238
+ | `timet summary week (w)` | Display a report of tracked time for the week. | `timet su w` |
239
+ | `timet summary month (m)` | Display a report of tracked time for the month. | `timet su m` |
240
+ | `timet su t --csv=[filename]` | Display a report of tracked time for today and export to CSV file | `timet su t --csv=file.csv` |
241
+ | `timet su w --ics=[filename]` | Display a report of tracked time for week and export to iCalendar file | `timet su w --ics=file.csv` |
242
+ | `timet su --report` | Display a detailed report of tag distribution for today. | `timet su --report` |
243
+ | `timet su t --report` | Display a detailed report of tag distribution for today. | `timet su t --report` |
244
+ | `timet su w --report` | Display a detailed report of tag distribution for the week. | `timet su w --report` |
245
+ | `timet summary [time_scope] [tag]` | Display a report of tracked time filtered by tag. | `timet su week mytag` |
246
+ | `timet summary [time_scope] --search=[query]` | Display a report of tracked time filtered by tag or notes. | `timet su week --search="bug"` |
247
+ | `timet delete [id]` | Delete a task by its ID. | `timet d [id]` |
248
+ | `timet cancel` | Cancel active time tracking. | `timet c` |
249
+ | `timet edit [id]` | Update a task's notes, tag, start, or end fields. | `timet e [id]` |
250
+ | `timet su [date]` | Display a report of tracked time for a specific date. | `timet su 2024-01-03` |
251
+ | `timet su [start_date]..[end_date]` | Display a report of tracked time for a date range. | `timet su 2024-01-02..2024-01-03` |
252
+ | `timet resume (r) [id]` | Resume tracking a task by ID or the last completed task. | `timet resume [id]` |
253
+ | `timet resume (r) [id] --pomodoro=[minutes]` | Resume tracking with a Pomodoro timer. | `timet resume 1 --pomodoro=25` |
254
+ | `timet sync` | Sync local db with remote (S3) external db | `timet sync` |
255
+ | `timet version` | Display the current version. | `timet version` |
240
256
 
241
257
  ### Date Range in Summary
242
258
 
@@ -257,11 +273,13 @@ The `timet summary` command now supports specifying a date range for generating
257
273
  ```
258
274
 
259
275
  <a name="data"></a>
276
+
260
277
  ## 🗃️ Data
261
278
 
262
279
  Timet's data is stored in `~/.timet`.
263
280
 
264
281
  <a name="s3-cloud-backup-configuration"></a>
282
+
265
283
  ## 🔒 S3 Cloud Backup Configuration
266
284
 
267
285
  Timet supports backing up and syncing your time tracking data with S3-compatible storage services (such as Supabase S3). To configure S3 backup, follow these steps:
@@ -284,8 +302,6 @@ S3_REGION=your_s3_region
284
302
  - Regularly rotate your S3 access credentials
285
303
  - Implement appropriate IAM policies to restrict bucket access
286
304
 
287
-
288
-
289
305
  ## Development
290
306
 
291
307
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -4,7 +4,7 @@ require 'thor'
4
4
  require 'tty-prompt'
5
5
  require 'icalendar'
6
6
  require_relative 's3_supabase'
7
- require_relative 'validation_edit_helper'
7
+ require_relative 'validation_editor'
8
8
  require_relative 'application_helper'
9
9
  require_relative 'time_helper'
10
10
  require_relative 'version'
@@ -22,7 +22,6 @@ module Timet
22
22
  # - delete: Delete a task
23
23
  # - cancel: Cancel active time tracking
24
24
  class Application < Thor
25
- include ValidationEditHelper
26
25
  include ApplicationHelper
27
26
  include TimeHelper
28
27
 
@@ -271,7 +270,8 @@ Update start time => tt edit 12 start 12:33'
271
270
  new_value = prompt_for_new_value(item, field)
272
271
  end
273
272
 
274
- updated_item = validate_and_update(item, field, new_value)
273
+ editor = Timet::ValidationEditor.new(item, @db)
274
+ updated_item = editor.update(field, new_value)
275
275
  @db.update_item(id, field, updated_item[FIELD_INDEX[field]])
276
276
  display_item(updated_item)
277
277
  end
@@ -24,7 +24,7 @@ module Timet
24
24
  # @note The method creates a new SQLite3 database connection and initializes the necessary tables if they
25
25
  # do not already exist.
26
26
  def initialize(database_path = DEFAULT_DATABASE_PATH)
27
- move_old_database_file(database_path)
27
+ self.class.move_old_database_file(database_path)
28
28
 
29
29
  @db = SQLite3::Database.new(database_path)
30
30
  create_table
@@ -73,14 +73,20 @@ module Timet
73
73
  # @note If the column does not exist, the method executes an SQL `ALTER TABLE` statement to add the column.
74
74
  # @note The method prints a message indicating that the column has been added.
75
75
  def add_column(table_name, new_column_name, date_type)
76
- result = execute_sql("SELECT count(*) FROM pragma_table_info('items') where name='#{new_column_name}'")
77
- column_exists = result[0][0].positive?
78
- return if column_exists
76
+ raise 'Invalid table name' unless table_name == 'items'
77
+ raise 'Invalid column name' unless /\A[a-zA-Z0-9_]+\z/.match?(new_column_name)
78
+ raise 'Invalid date type' unless %w[INTEGER TEXT BOOLEAN].include?(date_type)
79
+ return if column_exists?(new_column_name)
79
80
 
80
81
  execute_sql("ALTER TABLE #{table_name} ADD COLUMN #{new_column_name} #{date_type}")
81
82
  puts "Column '#{new_column_name}' added to table '#{table_name}'."
82
83
  end
83
84
 
85
+ def column_exists?(new_column_name)
86
+ execute_sql("SELECT count(*) FROM pragma_table_info('items') where name=?",
87
+ [new_column_name]).first.first.positive?
88
+ end
89
+
84
90
  # Inserts a new item into the items table.
85
91
  #
86
92
  # @param start [Integer] The start time of the item.
@@ -115,6 +121,9 @@ module Timet
115
121
  #
116
122
  # @note The method executes SQL to update the specified field of the item with the given ID.
117
123
  def update_item(id, field, value)
124
+ allowed_fields = %w[tag notes start end deleted updated_at created_at]
125
+ raise "Invalid field: #{field}" unless allowed_fields.include?(field)
126
+
118
127
  execute_sql("UPDATE items SET #{field} = ?, updated_at = ? WHERE id = ?", [value, Time.now.utc.to_i, id])
119
128
  end
120
129
 
@@ -143,8 +152,8 @@ module Timet
143
152
  #
144
153
  # @note The method executes SQL to fetch the ID of the last inserted item.
145
154
  def fetch_last_id
146
- result = execute_sql('SELECT id FROM items WHERE deleted IS NULL OR deleted = 0 ORDER BY id DESC LIMIT 1')
147
- result.empty? ? nil : result[0][0]
155
+ execute_sql('SELECT id FROM items WHERE deleted IS NULL OR deleted = 0 ORDER BY id DESC LIMIT 1')
156
+ .then { |result| result.empty? ? nil : result.first.first }
148
157
  end
149
158
 
150
159
  # Fetches the last item from the items table.
@@ -156,8 +165,8 @@ module Timet
156
165
  #
157
166
  # @note The method executes SQL to fetch the last item from the 'items' table.
158
167
  def last_item
159
- result = execute_sql('SELECT * FROM items WHERE deleted IS NULL OR deleted = 0 ORDER BY id DESC LIMIT 1')
160
- result.empty? ? nil : result[0]
168
+ execute_sql('SELECT * FROM items WHERE deleted IS NULL OR deleted = 0 ORDER BY id DESC LIMIT 1')
169
+ .then { |result| result.empty? ? nil : result.first }
161
170
  end
162
171
 
163
172
  # Finds an item by its ID.
@@ -173,8 +182,7 @@ module Timet
173
182
  # @note If the item is found, it returns the item as an array.
174
183
  # @note If the item is not found, it returns nil.
175
184
  def find_item(id)
176
- result = execute_sql('SELECT * FROM items WHERE id = ?', [id])
177
- result.first.dup if result.any? # Add .dup to create a copy
185
+ execute_sql('SELECT * FROM items WHERE id = ?', [id]).first&.dup
178
186
  end
179
187
 
180
188
  # Fetches all items from the items table that have a start time greater than or equal to today.
@@ -203,9 +211,10 @@ module Timet
203
211
  #
204
212
  # @param id [Integer, nil] The ID of the item to check. If nil, the last item in the table is used.
205
213
  #
214
+ # @see StatusHelper#determine_status
206
215
  def item_status(id = nil)
207
- id = fetch_last_id if id.nil?
208
- determine_status(find_item(id))
216
+ id ||= fetch_last_id
217
+ self.class.determine_status(find_item(id))
209
218
  end
210
219
 
211
220
  # Executes a SQL query and returns the result.
@@ -221,9 +230,6 @@ module Timet
221
230
  # @note The method executes the given SQL query with the provided parameters and returns the result.
222
231
  def execute_sql(sql, params = [])
223
232
  @db.execute(sql, params)
224
- rescue SQLite3::SQLException => e
225
- puts "Error: #{e.message}"
226
- []
227
233
  end
228
234
 
229
235
  # Closes the database connection.
@@ -276,8 +282,8 @@ module Timet
276
282
  # @note The method checks if the result set is empty and returns :no_items if true.
277
283
  # @note If the last item in the result set has no end time, it returns :in_progress.
278
284
  # @note If the last item in the result set has an end time, it returns :complete.
279
- def determine_status(result)
280
- return :no_items if result.nil?
285
+ def self.determine_status(result)
286
+ return :no_items unless result
281
287
 
282
288
  last_item_end = result[2]
283
289
  return :in_progress unless last_item_end
@@ -288,11 +294,12 @@ module Timet
288
294
  # Moves the old database file to the new location if it exists.
289
295
  #
290
296
  # @param database_path [String] The path to the new SQLite database file.
291
- def move_old_database_file(database_path)
297
+ def self.move_old_database_file(database_path)
292
298
  old_file = File.join(Dir.home, '.timet.db')
293
299
  return unless File.exist?(old_file)
294
300
 
295
- FileUtils.mkdir_p(File.dirname(database_path)) unless File.directory?(File.dirname(database_path))
301
+ dir = File.dirname(database_path)
302
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
296
303
  FileUtils.mv(old_file, database_path)
297
304
  end
298
305
 
@@ -312,12 +319,12 @@ module Timet
312
319
  # @raise [StandardError] If there is an issue executing the SQL queries, an error may be raised.
313
320
  #
314
321
  def update_time_columns
315
- result = execute_sql('SELECT * FROM items WHERE updated_at IS NULL OR created_at IS NULL')
316
- result.each do |item|
317
- id = item[0]
318
- end_time = item[2]
319
- execute_sql('UPDATE items SET updated_at = ?, created_at = ? WHERE id = ?', [end_time, end_time, id])
320
- end
322
+ execute_sql('SELECT * FROM items WHERE updated_at IS NULL OR created_at IS NULL')
323
+ .each { |item| update_timestamp_for_item(item[0], item[2] || item[1] || Time.now.to_i) }
324
+ end
325
+
326
+ def update_timestamp_for_item(id, fallback_time)
327
+ execute_sql('UPDATE items SET updated_at = ?, created_at = ? WHERE id = ?', [fallback_time, fallback_time, id])
321
328
  end
322
329
  end
323
330
  end