todo-fede 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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__)
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ Dir['./lib/**/*.rb'].each { |f| require(f) }
5
+
6
+ TodoList.load
7
+ Main.start(ARGV)
8
+ TodoList.dump
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Error to be raised when there is no registry of a todo with certain ID.
4
+ class TodoNotFoundError < StandardError
5
+ def message
6
+ 'Sorry, there is no Todo item with such ID'
7
+ end
8
+ end
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Version
4
+ VERSION = '1.0.0'
5
+ end
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: []