abt-cli 0.0.21 → 0.0.22

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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/bin/abt +3 -3
  3. data/lib/abt.rb +6 -6
  4. data/lib/abt/ari.rb +1 -1
  5. data/lib/abt/ari_list.rb +1 -1
  6. data/lib/abt/base_command.rb +7 -7
  7. data/lib/abt/cli.rb +27 -40
  8. data/lib/abt/cli/arguments_parser.rb +5 -9
  9. data/lib/abt/cli/global_commands.rb +23 -0
  10. data/lib/abt/cli/global_commands/commands.rb +2 -2
  11. data/lib/abt/cli/global_commands/examples.rb +2 -2
  12. data/lib/abt/cli/global_commands/help.rb +2 -2
  13. data/lib/abt/cli/global_commands/readme.rb +2 -2
  14. data/lib/abt/cli/global_commands/share.rb +6 -6
  15. data/lib/abt/cli/global_commands/version.rb +2 -2
  16. data/lib/abt/cli/prompt.rb +51 -20
  17. data/lib/abt/docs.rb +39 -33
  18. data/lib/abt/docs/cli.rb +3 -3
  19. data/lib/abt/docs/markdown.rb +5 -5
  20. data/lib/abt/git_config.rb +4 -6
  21. data/lib/abt/providers/asana/api.rb +9 -9
  22. data/lib/abt/providers/asana/base_command.rb +8 -10
  23. data/lib/abt/providers/asana/commands/add.rb +13 -12
  24. data/lib/abt/providers/asana/commands/branch_name.rb +8 -8
  25. data/lib/abt/providers/asana/commands/clear.rb +7 -8
  26. data/lib/abt/providers/asana/commands/current.rb +14 -14
  27. data/lib/abt/providers/asana/commands/finalize.rb +11 -12
  28. data/lib/abt/providers/asana/commands/harvest_time_entry_data.rb +11 -11
  29. data/lib/abt/providers/asana/commands/init.rb +8 -41
  30. data/lib/abt/providers/asana/commands/pick.rb +17 -17
  31. data/lib/abt/providers/asana/commands/projects.rb +5 -5
  32. data/lib/abt/providers/asana/commands/share.rb +5 -5
  33. data/lib/abt/providers/asana/commands/start.rb +21 -20
  34. data/lib/abt/providers/asana/commands/tasks.rb +6 -6
  35. data/lib/abt/providers/asana/configuration.rb +25 -25
  36. data/lib/abt/providers/asana/path.rb +5 -5
  37. data/lib/abt/providers/devops/api.rb +12 -12
  38. data/lib/abt/providers/devops/base_command.rb +10 -10
  39. data/lib/abt/providers/devops/commands/boards.rb +5 -7
  40. data/lib/abt/providers/devops/commands/branch_name.rb +9 -9
  41. data/lib/abt/providers/devops/commands/clear.rb +7 -8
  42. data/lib/abt/providers/devops/commands/current.rb +17 -17
  43. data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +13 -13
  44. data/lib/abt/providers/devops/commands/init.rb +17 -13
  45. data/lib/abt/providers/devops/commands/pick.rb +11 -11
  46. data/lib/abt/providers/devops/commands/share.rb +5 -5
  47. data/lib/abt/providers/devops/commands/{work-items.rb → work_items.rb} +3 -3
  48. data/lib/abt/providers/devops/configuration.rb +19 -15
  49. data/lib/abt/providers/devops/path.rb +5 -4
  50. data/lib/abt/providers/git/commands/branch.rb +17 -19
  51. data/lib/abt/providers/harvest/api.rb +8 -8
  52. data/lib/abt/providers/harvest/base_command.rb +6 -8
  53. data/lib/abt/providers/harvest/commands/clear.rb +7 -8
  54. data/lib/abt/providers/harvest/commands/current.rb +13 -13
  55. data/lib/abt/providers/harvest/commands/init.rb +10 -38
  56. data/lib/abt/providers/harvest/commands/pick.rb +11 -11
  57. data/lib/abt/providers/harvest/commands/projects.rb +5 -5
  58. data/lib/abt/providers/harvest/commands/share.rb +5 -5
  59. data/lib/abt/providers/harvest/commands/start.rb +5 -3
  60. data/lib/abt/providers/harvest/commands/stop.rb +12 -12
  61. data/lib/abt/providers/harvest/commands/tasks.rb +7 -7
  62. data/lib/abt/providers/harvest/commands/track.rb +21 -20
  63. data/lib/abt/providers/harvest/configuration.rb +18 -18
  64. data/lib/abt/providers/harvest/path.rb +5 -5
  65. data/lib/abt/version.rb +1 -1
  66. metadata +6 -5
data/lib/abt/docs.rb CHANGED
@@ -9,37 +9,39 @@ module Abt
9
9
  class << self
10
10
  def basic_examples
11
11
  {
12
- 'Getting started:' => {
13
- 'abt init asana harvest' => 'Setup asana and harvest project for local git repo',
14
- 'abt pick harvest' => 'Pick harvest task. This will likely stay the same throughout the project',
15
- 'abt pick asana | abt start harvest' => 'Pick asana task and start tracking time',
16
- 'abt stop harvest' => 'Stop time tracker',
17
- 'abt start asana harvest' => 'Continue working, e.g., after a break',
18
- 'abt finalize asana' => 'Finalize the selected asana task'
12
+ "Getting started:" => {
13
+ "abt init asana harvest" => "Setup asana and harvest project for local git repo",
14
+ "abt pick harvest" => "Pick harvest task. This will likely stay the same throughout the project",
15
+ "abt pick asana | abt start harvest" => "Pick asana task and start tracking time",
16
+ "abt stop harvest" => "Stop time tracker",
17
+ "abt start asana harvest" => "Continue working, e.g., after a break",
18
+ "abt finalize asana" => "Finalize the selected asana task"
19
19
  }
20
20
  }
21
21
  end
22
22
 
23
- def extended_examples
23
+ def extended_examples # rubocop:disable Metrics/MethodLength
24
24
  {
25
- 'Tracking meetings (without switching current task setting):' => {
26
- 'abt pick asana -d | abt track harvest' => 'Track on asana meeting task',
27
- 'abt pick harvest -d | abt track harvest -c "Name of meeting"' => 'Track on separate harvest-task'
25
+ "Tracking meetings (without switching current task setting):" => {
26
+ "abt pick asana -d | abt track harvest" => "Track on asana meeting task",
27
+ 'abt pick harvest -d | abt track harvest -c "Name of meeting"' => "Track on separate harvest-task"
28
28
  },
29
- 'Many commands output ARIs that can be piped into other commands:' => {
30
- 'abt tasks asana | grep -i <name of task>' => nil,
31
- 'abt tasks asana | grep -i <name of task> | abt start' => nil
29
+ "Many commands output ARIs that can be piped into other commands:" => {
30
+ "abt tasks asana | grep -i <name of task>" => nil,
31
+ "abt tasks asana | grep -i <name of task> | abt start" => nil
32
32
  },
33
- 'Sharing ARIs:' => {
34
- 'abt share asana harvest | tr "\n" " "' => 'Print current asana and harvest ARIs on a single line',
35
- 'abt share asana harvest | tr "\n" " " | pbcopy' => 'Copy ARIs to clipboard (mac only)',
36
- 'abt start <ARIs from coworker>' => 'Work on a task your coworker shared with you',
37
- 'abt current <ARIs from coworker> | abt start' => 'Set task as current, then start it'
33
+ "Sharing ARIs:" => {
34
+ 'abt share asana harvest | tr "\n" " "' => "Print current asana and harvest ARIs on a single line",
35
+ 'abt share asana harvest | tr "\n" " " | pbcopy' => "Copy ARIs to clipboard (mac only)",
36
+ "abt start <ARIs from coworker>" => "Work on a task your coworker shared with you",
37
+ "abt current <ARIs from coworker> | abt start" => "Set task as current, then start it"
38
38
  },
39
- 'Flags:' => {
40
- 'abt start harvest -c "comment"' => 'Add command flags after ARIs',
41
- 'abt start harvest -c "comment" -- asana' => 'Use -- to end a list of flags, so that it can be followed by another ARI',
42
- 'abt pick harvest | abt start -c "comment"' => 'Flags placed directly after a command applies to the piped in ARI'
39
+ "Flags:" => {
40
+ 'abt start harvest -c "comment"' => "Add command flags after ARIs",
41
+ 'abt start harvest -c "comment" -- asana' =>
42
+ "Use -- to end a list of flags, so that it can be followed by another ARI",
43
+ 'abt pick harvest | abt start -c "comment"' =>
44
+ "Flags placed directly after a command applies to the piped in ARI"
43
45
  }
44
46
  }
45
47
  end
@@ -48,15 +50,7 @@ module Abt
48
50
  @providers ||= begin
49
51
  providers = {}
50
52
 
51
- global_command_names = Abt::Cli.global_command_names
52
- providers['Global'] = global_command_names.each_with_object({}) do |name, definition|
53
- command_class = Abt::Cli.global_command_class(name)
54
- full_name = "abt #{name}"
55
-
56
- if command_class.respond_to?(:usage) && command_class.respond_to?(:description)
57
- definition[full_name] = [command_class.usage, command_class.description]
58
- end
59
- end
53
+ providers["Global"] = global_command_definitions
60
54
 
61
55
  Abt.schemes.sort.each_with_object(providers) do |scheme, definition|
62
56
  definition[scheme] = command_definitions(scheme)
@@ -68,6 +62,18 @@ module Abt
68
62
 
69
63
  private
70
64
 
65
+ def global_command_definitions
66
+ global_command_names = Abt::Cli::GlobalCommands.command_names
67
+ global_command_names.each_with_object({}) do |name, definition|
68
+ command_class = Abt::Cli::GlobalCommands.command_class(name)
69
+ full_name = "abt #{name}"
70
+
71
+ if command_class.respond_to?(:usage) && command_class.respond_to?(:description)
72
+ definition[full_name] = [command_class.usage.strip, command_class.description.strip]
73
+ end
74
+ end
75
+ end
76
+
71
77
  def command_definitions(scheme)
72
78
  provider = Abt.scheme_provider(scheme)
73
79
  provider.command_names.each_with_object({}) do |name, definition|
@@ -75,7 +81,7 @@ module Abt
75
81
  full_name = "abt #{name} #{scheme}"
76
82
 
77
83
  if command_class.respond_to?(:usage) && command_class.respond_to?(:description)
78
- definition[full_name] = [command_class.usage, command_class.description]
84
+ definition[full_name] = [command_class.usage.strip, command_class.description.strip]
79
85
  end
80
86
  end
81
87
  end
data/lib/abt/docs/cli.rb CHANGED
@@ -45,14 +45,14 @@ module Abt
45
45
  private
46
46
 
47
47
  def usage_line
48
- 'abt <command> [<ARI>] [<options> --] [<ARI>] ...'
48
+ "abt <command> [<ARI>] [<options> --] [<ARI>] ..."
49
49
  end
50
50
 
51
51
  def formatted_examples(example_groups)
52
52
  lines = []
53
53
 
54
54
  example_groups.each_with_index do |(title, examples), index|
55
- lines << '' unless index.zero?
55
+ lines << "" unless index.zero?
56
56
  lines << title
57
57
 
58
58
  max_length = examples.keys.map(&:length).max
@@ -68,7 +68,7 @@ module Abt
68
68
  lines = []
69
69
 
70
70
  Docs.providers.each_with_index do |(scheme, commands_definition), index|
71
- lines << '' unless index.zero?
71
+ lines << "" unless index.zero?
72
72
  lines << "#{inflector.humanize(scheme)}:"
73
73
 
74
74
  max_length = commands_definition.keys.map(&:length).max
@@ -52,11 +52,11 @@ module Abt
52
52
 
53
53
  examples = Docs.basic_examples.merge(Docs.extended_examples)
54
54
  examples.each_with_index do |(title, commands), index|
55
- lines << '' unless index.zero?
55
+ lines << "" unless index.zero?
56
56
  lines << title
57
57
 
58
58
  commands.each do |(command, description)|
59
- formatted_description = description.nil? ? '' : ": #{description}"
59
+ formatted_description = description.nil? ? "" : ": #{description}"
60
60
  lines << "- `#{command}`#{formatted_description}"
61
61
  end
62
62
  end
@@ -68,10 +68,10 @@ module Abt
68
68
  lines = []
69
69
 
70
70
  Docs.providers.each_with_index do |(scheme, commands), index|
71
- lines << '' unless index.zero?
71
+ lines << "" unless index.zero?
72
72
  lines << "### #{inflector.humanize(scheme)}"
73
- lines << '| Command | Description |'
74
- lines << '| :------ | :---------- |'
73
+ lines << "| Command | Description |"
74
+ lines << "| :------ | :---------- |"
75
75
 
76
76
  max_length = commands.values.map(&:first).map(&:length).max
77
77
 
@@ -6,12 +6,10 @@ module Abt
6
6
 
7
7
  class UnsafeNamespaceError < StandardError; end
8
8
 
9
- def initialize(scope = 'local', namespace = '')
9
+ def initialize(scope = "local", namespace = "")
10
10
  @namespace = namespace
11
11
 
12
- unless %w[local global].include? scope
13
- raise ArgumentError, 'scope must be "local" or "global"'
14
- end
12
+ raise ArgumentError, 'scope must be "local" or "global"' unless %w[local global].include?(scope)
15
13
 
16
14
  @scope = scope
17
15
  end
@@ -50,7 +48,7 @@ module Abt
50
48
  end
51
49
 
52
50
  def clear(output: nil)
53
- raise UnsafeNamespaceError, 'Keys can only be cleared within a namespace' if namespace.empty?
51
+ raise UnsafeNamespaceError, "Keys can only be cleared within a namespace" if namespace.empty?
54
52
 
55
53
  keys.each do |key|
56
54
  output&.puts "Clearing #{scope}: #{key_with_namespace(key)}"
@@ -67,7 +65,7 @@ module Abt
67
65
  def ensure_scope_available!
68
66
  return if available?
69
67
 
70
- raise StandardError, 'Local configuration is not available outside a git repository'
68
+ raise StandardError, "Local configuration is not available outside a git repository"
71
69
  end
72
70
 
73
71
  def key_with_namespace(key)
@@ -4,8 +4,8 @@ module Abt
4
4
  module Providers
5
5
  module Asana
6
6
  class Api
7
- API_ENDPOINT = 'https://app.asana.com/api/1.0'
8
- VERBS = %i[get post put].freeze
7
+ API_ENDPOINT = "https://app.asana.com/api/1.0"
8
+ VERBS = [:get, :post, :put].freeze
9
9
 
10
10
  attr_reader :access_token
11
11
 
@@ -15,7 +15,7 @@ module Abt
15
15
 
16
16
  VERBS.each do |verb|
17
17
  define_method(verb) do |*args|
18
- request(verb, *args)['data']
18
+ request(verb, *args)["data"]
19
19
  end
20
20
  end
21
21
 
@@ -24,10 +24,10 @@ module Abt
24
24
 
25
25
  loop do
26
26
  result = request(:get, path, query.merge(limit: 100))
27
- records += result['data']
28
- break if result['next_page'].nil?
27
+ records += result["data"]
28
+ break if result["next_page"].nil?
29
29
 
30
- path = result['next_page']['path'][1..-1]
30
+ path = result["next_page"]["path"][1..-1]
31
31
  end
32
32
 
33
33
  records
@@ -40,15 +40,15 @@ module Abt
40
40
  Oj.load(response.body)
41
41
  else
42
42
  error_class = Abt::HttpError.error_class_for_status(response.status)
43
- encoded_response_body = response.body.force_encoding('utf-8')
43
+ encoded_response_body = response.body.force_encoding("utf-8")
44
44
  raise error_class, "Code: #{response.status}, body: #{encoded_response_body}"
45
45
  end
46
46
  end
47
47
 
48
48
  def connection
49
49
  @connection ||= Faraday.new(API_ENDPOINT) do |connection|
50
- connection.headers['Authorization'] = "Bearer #{access_token}"
51
- connection.headers['Content-Type'] = 'application/json'
50
+ connection.headers["Authorization"] = "Bearer #{access_token}"
51
+ connection.headers["Content-Type"] = "application/json"
52
52
  end
53
53
  end
54
54
  end
@@ -21,25 +21,23 @@ module Abt
21
21
  private
22
22
 
23
23
  def require_project!
24
- abort 'No current/specified project. Did you initialize Asana?' if project_gid.nil?
24
+ abort("No current/specified project. Did you initialize Asana?") if project_gid.nil?
25
25
  end
26
26
 
27
27
  def require_task!
28
- if project_gid.nil?
29
- abort 'No current/specified project. Did you initialize Asana and pick a task?'
30
- end
31
- abort 'No current/specified task. Did you pick an Asana task?' if task_gid.nil?
28
+ abort("No current/specified project. Did you initialize Asana and pick a task?") if project_gid.nil?
29
+ abort("No current/specified task. Did you pick an Asana task?") if task_gid.nil?
32
30
  end
33
31
 
34
32
  def print_project(project)
35
- cli.print_ari('asana', project['gid'], project['name'])
36
- warn project['permalink_url'] if project.key?('permalink_url') && cli.output.isatty
33
+ cli.print_ari("asana", project["gid"], project["name"])
34
+ warn(project["permalink_url"]) if project.key?("permalink_url") && cli.output.isatty
37
35
  end
38
36
 
39
37
  def print_task(project, task)
40
- project = { 'gid' => project } if project.is_a?(String)
41
- cli.print_ari('asana', "#{project['gid']}/#{task['gid']}", task['name'])
42
- warn task['permalink_url'] if task.key?('permalink_url') && cli.output.isatty
38
+ project = { "gid" => project } if project.is_a?(String)
39
+ cli.print_ari("asana", "#{project['gid']}/#{task['gid']}", task["name"])
40
+ warn(task["permalink_url"]) if task.key?("permalink_url") && cli.output.isatty
43
41
  end
44
42
 
45
43
  def api
@@ -6,22 +6,22 @@ module Abt
6
6
  module Commands
7
7
  class Add < BaseCommand
8
8
  def self.usage
9
- 'abt add asana[:<project-gid>]'
9
+ "abt add asana[:<project-gid>]"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Create a new task for the current/specified Asana project'
13
+ "Create a new task for the current/specified Asana project"
14
14
  end
15
15
 
16
16
  def perform
17
17
  require_project!
18
18
 
19
19
  task
20
- warn 'Task created'
20
+ warn("Task created")
21
21
 
22
22
  if section
23
23
  move_task
24
- warn "Moved to section: #{section['name']}"
24
+ warn("Moved to section: #{section['name']}")
25
25
  end
26
26
 
27
27
  print_task(project, task)
@@ -38,36 +38,37 @@ module Abt
38
38
  projects: [project_gid]
39
39
  }
40
40
  }
41
- api.post('tasks', Oj.dump(body, mode: :json))
41
+ api.post("tasks", Oj.dump(body, mode: :json))
42
42
  end
43
43
  end
44
44
 
45
45
  def move_task
46
- body = { data: { task: task['gid'] } }
46
+ body = { data: { task: task["gid"] } }
47
47
  body_json = Oj.dump(body, mode: :json)
48
48
  api.post("sections/#{section['gid']}/addTask", body_json)
49
49
  end
50
50
 
51
51
  def name
52
- @name ||= cli.prompt.text 'Enter task description'
52
+ @name ||= cli.prompt.text("Enter task description")
53
53
  end
54
54
 
55
55
  def notes
56
- @notes ||= cli.prompt.text 'Enter task notes'
56
+ @notes ||= cli.prompt.text("Enter task notes")
57
57
  end
58
58
 
59
59
  def project
60
- @project ||= api.get("projects/#{project_gid}", opt_fields: 'name')
60
+ @project ||= api.get("projects/#{project_gid}", opt_fields: "name")
61
61
  end
62
62
 
63
63
  def section
64
- @section ||= cli.prompt.choice 'Add to section?', sections, ['q', 'Don\'t add to section']
64
+ @section ||= cli.prompt.choice("Add to section?", sections,
65
+ nil_option: ["q", "Don't add to section"])
65
66
  end
66
67
 
67
68
  def sections
68
69
  @sections ||= begin
69
- warn 'Fetching sections...'
70
- api.get_paged("projects/#{project_gid}/sections", opt_fields: 'name')
70
+ warn("Fetching sections...")
71
+ api.get_paged("projects/#{project_gid}/sections", opt_fields: "name")
71
72
  end
72
73
  end
73
74
  end
@@ -6,11 +6,11 @@ module Abt
6
6
  module Commands
7
7
  class BranchName < BaseCommand
8
8
  def self.usage
9
- 'abt branch-name asana[:<project-gid>/<task-gid>]'
9
+ "abt branch-name asana[:<project-gid>/<task-gid>]"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Suggest a git branch name for the current/specified task.'
13
+ "Suggest a git branch name for the current/specified task."
14
14
  end
15
15
 
16
16
  def perform
@@ -23,21 +23,21 @@ module Abt
23
23
  private
24
24
 
25
25
  def name
26
- task['name'].downcase.gsub(/[^\w]+/, '-')
26
+ task["name"].downcase.gsub(/[^\w]+/, "-").gsub(/(^-|-$)/, "")
27
27
  end
28
28
 
29
29
  def ensure_current_is_valid!
30
- abort "Invalid task gid: #{task_gid}" if task.nil?
30
+ abort("Invalid task gid: #{task_gid}") if task.nil?
31
31
 
32
- return if task['memberships'].any? { |m| m.dig('project', 'gid') == project_gid }
32
+ return if task["memberships"].any? { |m| m.dig("project", "gid") == project_gid }
33
33
 
34
- abort "Invalid or unmatching project gid: #{project_gid}"
34
+ abort("Invalid or unmatching project gid: #{project_gid}")
35
35
  end
36
36
 
37
37
  def task
38
38
  @task ||= begin
39
- warn 'Fetching task...'
40
- api.get("tasks/#{task_gid}", opt_fields: 'name,memberships.project')
39
+ warn("Fetching task...")
40
+ api.get("tasks/#{task_gid}", opt_fields: "name,memberships.project")
41
41
  rescue Abt::HttpError::NotFoundError
42
42
  nil
43
43
  end
@@ -6,29 +6,28 @@ module Abt
6
6
  module Commands
7
7
  class Clear < BaseCommand
8
8
  def self.usage
9
- 'abt clear asana'
9
+ "abt clear asana"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Clear asana configuration'
13
+ "Clear asana configuration"
14
14
  end
15
15
 
16
16
  def self.flags
17
17
  [
18
- ['-g', '--global', 'Clear global instead of local asana configuration (credentials etc.)'],
19
- ['-a', '--all', 'Clear all asana configuration']
18
+ ["-g", "--global",
19
+ "Clear global instead of local asana configuration (credentials etc.)"],
20
+ ["-a", "--all", "Clear all asana configuration"]
20
21
  ]
21
22
  end
22
23
 
23
24
  def perform
24
- if flags[:global] && flags[:all]
25
- abort('Flags --global and --all cannot be used at the same time')
26
- end
25
+ abort("Flags --global and --all cannot be used at the same time") if flags[:global] && flags[:all]
27
26
 
28
27
  config.clear_local unless flags[:global]
29
28
  config.clear_global if flags[:global] || flags[:all]
30
29
 
31
- warn 'Configuration cleared'
30
+ warn("Configuration cleared")
32
31
  end
33
32
  end
34
33
  end
@@ -6,22 +6,22 @@ module Abt
6
6
  module Commands
7
7
  class Current < BaseCommand
8
8
  def self.usage
9
- 'abt current asana[:<project-gid>[/<task-gid>]]'
9
+ "abt current asana[:<project-gid>[/<task-gid>]]"
10
10
  end
11
11
 
12
12
  def self.description
13
- 'Get or set project and or task for current git repository'
13
+ "Get or set project and or task for current git repository"
14
14
  end
15
15
 
16
16
  def perform
17
- abort 'Must be run inside a git repository' unless config.local_available?
17
+ abort("Must be run inside a git repository") unless config.local_available?
18
18
 
19
19
  require_project!
20
20
  ensure_valid_configuration!
21
21
 
22
22
  if path != config.path
23
23
  config.path = path
24
- warn 'Configuration updated'
24
+ warn("Configuration updated")
25
25
  end
26
26
 
27
27
  print_configuration
@@ -34,25 +34,25 @@ module Abt
34
34
  end
35
35
 
36
36
  def ensure_valid_configuration!
37
- abort "Invalid project: #{project_gid}" if project.nil?
38
- abort "Invalid task: #{task_gid}" if task_gid && task.nil?
37
+ abort("Invalid project: #{project_gid}") if project.nil?
38
+ abort("Invalid task: #{task_gid}") if task_gid && task.nil?
39
39
  end
40
40
 
41
41
  def project
42
42
  @project ||= begin
43
- warn 'Fetching project...'
44
- api.get("projects/#{project_gid}", opt_fields: 'name,permalink_url')
45
- rescue Abt::HttpError::NotFoundError
46
- nil
43
+ warn("Fetching project...")
44
+ api.get("projects/#{project_gid}", opt_fields: "name,permalink_url")
45
+ rescue Abt::HttpError::NotFoundError
46
+ nil
47
47
  end
48
48
  end
49
49
 
50
50
  def task
51
51
  @task ||= begin
52
- warn 'Fetching task...'
53
- api.get("tasks/#{task_gid}", opt_fields: 'name,permalink_url')
54
- rescue Abt::HttpError::NotFoundError
55
- nil
52
+ warn("Fetching task...")
53
+ api.get("tasks/#{task_gid}", opt_fields: "name,permalink_url")
54
+ rescue Abt::HttpError::NotFoundError
55
+ nil
56
56
  end
57
57
  end
58
58
  end