todo-fede 1.0.0
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 +7 -0
- data/bin/console +10 -0
- data/bin/setup +6 -0
- data/bin/todo +8 -0
- data/lib/errors/todo_not_found_error.rb +8 -0
- data/lib/helpers/main_helper.rb +25 -0
- data/lib/helpers/todo_helper.rb +57 -0
- data/lib/main.rb +91 -0
- data/lib/singleton_storer.rb +48 -0
- data/lib/todo.rb +16 -0
- data/lib/todo_list.rb +68 -0
- data/lib/todos_controller.rb +35 -0
- data/lib/version.rb +5 -0
- metadata +128 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 58ded6bb5a70de8630f77cfa4e978fbdc2439de65024019dfc6f7a6de82c6744
|
4
|
+
data.tar.gz: cdf5570db57cea5f4adde6ba8496c0d4cbb69016e1381c7030caf0738d8c514e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3bb3dd42868f82c75beb57206adfb5eadd1849b07f2eb99c97d555e20c3c6ed4b43889a523300ed8ccad347185ef31f3dba7be1a19cf2c7a579a96ed8f0b25dd
|
7
|
+
data.tar.gz: ce42f10559aa1f28e41cef9a7d00e4190ca9aca8469be37481ede30e242dc8353c600e545bd6a30046d1a78706e9a054e36019fdcf5099806711b31ae89959cc
|
data/bin/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
Dir['./lib/**/*.rb'].each { |f| require(f) }
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
require 'irb'
|
10
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/bin/todo
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This module provides helper methods to display
|
4
|
+
# informative messages to the user
|
5
|
+
module MainHelper
|
6
|
+
def display_description_needed_message
|
7
|
+
puts 'You must provide a description for the task'
|
8
|
+
end
|
9
|
+
|
10
|
+
def display_something_went_wrong_message(msg)
|
11
|
+
puts "Sorry, something went wrong: #{msg}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def display_created_task_message(idx)
|
15
|
+
puts "Created task #{idx}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def confirm_deletion_message(idx, todo)
|
19
|
+
"Permanently delete task #{idx + 1} #{todo.description}? (yes/no)"
|
20
|
+
end
|
21
|
+
|
22
|
+
def print_successfull_deletion_message
|
23
|
+
puts 'To-Do successfully deleted'
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This module provides helper methods to display the
|
4
|
+
# information of the TodoList instance to the user.
|
5
|
+
module TodoHelper
|
6
|
+
def display_all_todos(undone:, done:)
|
7
|
+
if undone.any? || done.any?
|
8
|
+
_display_todos(undone)
|
9
|
+
_display_done_todos(done)
|
10
|
+
_display_todos_count_message(undone)
|
11
|
+
else
|
12
|
+
_display_no_matches
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def display_undone_todos(todos_list)
|
17
|
+
if todos_list.any?
|
18
|
+
_display_todos(todos_list)
|
19
|
+
_display_todos_count_message(todos_list)
|
20
|
+
else
|
21
|
+
_display_no_matches
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def _display_done_todos(todos_list)
|
26
|
+
todos_list.each do |todo|
|
27
|
+
puts "* ~~#{todo.description}~~"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def _display_todos(todos_list)
|
32
|
+
puts 'ID Description'
|
33
|
+
puts '-- -----------'
|
34
|
+
todos_list.each_with_index do |todo, idx|
|
35
|
+
puts "#{_two_characters_format(idx + 1)} #{todo.description}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def _display_todos_count_message(todos_list)
|
40
|
+
todos_count = todos_list.length
|
41
|
+
if todos_count > 1
|
42
|
+
puts "\n#{todos_count} tasks."
|
43
|
+
else
|
44
|
+
puts "\n#{todos_count} task."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def _two_characters_format(number)
|
49
|
+
return number.to_s if number > 9
|
50
|
+
|
51
|
+
"#{number} "
|
52
|
+
end
|
53
|
+
|
54
|
+
def _display_no_matches
|
55
|
+
puts 'No matches'
|
56
|
+
end
|
57
|
+
end
|
data/lib/main.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require_relative 'helpers/todo_helper'
|
5
|
+
require_relative 'helpers/main_helper'
|
6
|
+
|
7
|
+
# It's responsible for the application initialization and
|
8
|
+
# for the client communication interface.
|
9
|
+
class Main < Thor
|
10
|
+
include TodoHelper
|
11
|
+
include MainHelper
|
12
|
+
|
13
|
+
desc 'add TASK DESCRIPTION', 'Add tasks to a todo list'
|
14
|
+
def add(*description)
|
15
|
+
return unless validate_description_presence(description)
|
16
|
+
|
17
|
+
todo_idx = with_rescue do
|
18
|
+
todos_controller.add(description: description.join(' '))
|
19
|
+
end
|
20
|
+
display_created_task_message(todo_idx)
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'done IDX', 'Mark the todo with the provided <<IDX>> as done'
|
24
|
+
def done(idx)
|
25
|
+
with_rescue do
|
26
|
+
todos_controller.done(idx.to_i - 1)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'delete IDX', 'Delete the task with the given IDX'
|
31
|
+
def delete(idx)
|
32
|
+
with_rescue do
|
33
|
+
index = idx.to_i - 1
|
34
|
+
todo = todos_controller.find(index)
|
35
|
+
if require_deletion_confirmation(index, todo)
|
36
|
+
todos_controller.delete(index)
|
37
|
+
print_successfull_deletion_message
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'list', 'Display a list of the tasks'
|
43
|
+
option :all
|
44
|
+
def list
|
45
|
+
todos = with_rescue do
|
46
|
+
todos_controller.list
|
47
|
+
end
|
48
|
+
|
49
|
+
if options['all']
|
50
|
+
display_all_todos(undone: todos[:undone_items], done: todos[:done_items])
|
51
|
+
else
|
52
|
+
display_undone_todos(todos[:undone_items])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class << self
|
57
|
+
def exit_on_failure?
|
58
|
+
true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def validate_description_presence(description)
|
65
|
+
return true if description.count.positive?
|
66
|
+
|
67
|
+
display_description_needed_message
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
def todos_controller
|
72
|
+
TodosController.new
|
73
|
+
end
|
74
|
+
|
75
|
+
def require_deletion_confirmation(idx, todo)
|
76
|
+
confirm = nil
|
77
|
+
until %w[y n].include?(confirm)
|
78
|
+
confirm = ask(confirm_deletion_message(idx, todo))
|
79
|
+
end
|
80
|
+
|
81
|
+
confirm == 'y'
|
82
|
+
end
|
83
|
+
|
84
|
+
def with_rescue
|
85
|
+
yield
|
86
|
+
rescue TodoNotFoundError => e
|
87
|
+
puts e.message.to_s
|
88
|
+
rescue StandardError => e
|
89
|
+
display_something_went_wrong_message(e.message)
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Mixin module, adds the ability to persist a Singleton class in a
|
4
|
+
# local file and also de ability to load the Singleton class from that file.
|
5
|
+
# In order to work properply the class that include this modules must also
|
6
|
+
# include the ruby module Singleton
|
7
|
+
module SingletonStorer
|
8
|
+
# This module allows to embed class methods as part of the mixin.
|
9
|
+
module ClassMethods
|
10
|
+
def dump
|
11
|
+
instance._dump
|
12
|
+
end
|
13
|
+
|
14
|
+
def load
|
15
|
+
instance._load
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.included(base)
|
20
|
+
base.extend(ClassMethods)
|
21
|
+
end
|
22
|
+
|
23
|
+
def _load
|
24
|
+
return unless File.exist?(persistence_file_name)
|
25
|
+
|
26
|
+
attributes = Marshal.load(File.read(persistence_file_name))
|
27
|
+
attributes.each do |attr, value|
|
28
|
+
instance_variable_set("@#{attr}".to_sym, value)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def _dump
|
33
|
+
File.write(persistence_file_name, Marshal.dump(attrs_to_hash))
|
34
|
+
end
|
35
|
+
|
36
|
+
def persistence_file_name
|
37
|
+
"#{self.class.name.downcase}.mp"
|
38
|
+
end
|
39
|
+
|
40
|
+
def attrs_to_hash
|
41
|
+
attrs = {}
|
42
|
+
self.class::PERSISTED_ATTRIBUTES.each do |attr|
|
43
|
+
attrs[attr] = send(attr)
|
44
|
+
end
|
45
|
+
|
46
|
+
attrs
|
47
|
+
end
|
48
|
+
end
|
data/lib/todo.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Representation of the main entity of the program, a to do item.
|
4
|
+
class Todo
|
5
|
+
attr_accessor(:description)
|
6
|
+
|
7
|
+
def initialize(description:)
|
8
|
+
@description = description
|
9
|
+
end
|
10
|
+
|
11
|
+
def update(**attrs)
|
12
|
+
attrs.each do |attr, value|
|
13
|
+
instance_variable_set("@#{attr}".to_sym, value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/todo_list.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
require 'singleton_storer'
|
5
|
+
|
6
|
+
# Singleton class resposible for managing the CRUD operations related
|
7
|
+
# to a Todo instance.
|
8
|
+
class TodoList
|
9
|
+
PERSISTED_ATTRIBUTES = %i[undone_todos done_todos].freeze
|
10
|
+
|
11
|
+
include Singleton
|
12
|
+
include SingletonStorer
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
set_defaults
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(todo)
|
19
|
+
@undone_todos << todo
|
20
|
+
end
|
21
|
+
|
22
|
+
def move_to_done(idx)
|
23
|
+
raise TodoNotFoundError unless in_range?(idx)
|
24
|
+
|
25
|
+
@done_todos << remove_from_undone(idx)
|
26
|
+
end
|
27
|
+
|
28
|
+
def done
|
29
|
+
@done_todos
|
30
|
+
end
|
31
|
+
|
32
|
+
def undone
|
33
|
+
@undone_todos
|
34
|
+
end
|
35
|
+
|
36
|
+
def undone_count
|
37
|
+
@undone_todos.length
|
38
|
+
end
|
39
|
+
|
40
|
+
def find(idx)
|
41
|
+
raise TodoNotFoundError unless in_range?(idx)
|
42
|
+
|
43
|
+
@undone_todos[idx]
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete(idx)
|
47
|
+
remove_from_undone idx
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
attr_accessor(*PERSISTED_ATTRIBUTES)
|
53
|
+
|
54
|
+
def set_defaults
|
55
|
+
@undone_todos = []
|
56
|
+
@done_todos = []
|
57
|
+
end
|
58
|
+
|
59
|
+
def remove_from_undone(idx)
|
60
|
+
raise TodoNotFoundError unless in_range?(idx)
|
61
|
+
|
62
|
+
@undone_todos.delete_at(idx)
|
63
|
+
end
|
64
|
+
|
65
|
+
def in_range?(idx)
|
66
|
+
(0..(@undone_todos.length - 1)).include?(idx)
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Plays the role of intermediary between the Main class and the Todo class
|
4
|
+
class TodosController
|
5
|
+
def add(description:)
|
6
|
+
todo = Todo.new(description: description)
|
7
|
+
todo_list.add(todo)
|
8
|
+
todo_list.undone_count
|
9
|
+
end
|
10
|
+
|
11
|
+
def list
|
12
|
+
{
|
13
|
+
done_items: todo_list.done,
|
14
|
+
undone_items: todo_list.undone
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def done(idx)
|
19
|
+
todo_list.move_to_done(idx)
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete(idx)
|
23
|
+
todo_list.delete(idx)
|
24
|
+
end
|
25
|
+
|
26
|
+
def find(idx)
|
27
|
+
todo_list.find(idx)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def todo_list
|
33
|
+
TodoList.instance
|
34
|
+
end
|
35
|
+
end
|
data/lib/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: todo-fede
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Federico Moya
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-02-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rubocop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.79'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.79'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '11'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '11'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: thor
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.1
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.1
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- federicomoyamartin@gmail.com
|
86
|
+
executables:
|
87
|
+
- console
|
88
|
+
- setup
|
89
|
+
- todo
|
90
|
+
extensions: []
|
91
|
+
extra_rdoc_files: []
|
92
|
+
files:
|
93
|
+
- bin/console
|
94
|
+
- bin/setup
|
95
|
+
- bin/todo
|
96
|
+
- lib/errors/todo_not_found_error.rb
|
97
|
+
- lib/helpers/main_helper.rb
|
98
|
+
- lib/helpers/todo_helper.rb
|
99
|
+
- lib/main.rb
|
100
|
+
- lib/singleton_storer.rb
|
101
|
+
- lib/todo.rb
|
102
|
+
- lib/todo_list.rb
|
103
|
+
- lib/todos_controller.rb
|
104
|
+
- lib/version.rb
|
105
|
+
homepage:
|
106
|
+
licenses:
|
107
|
+
- MIT
|
108
|
+
metadata: {}
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.7.0
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubygems_version: 3.1.2
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Cool todo app
|
128
|
+
test_files: []
|