cardigan 0.0.9 → 0.1.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.
Files changed (64) hide show
  1. data/.gemtest +0 -0
  2. data/Rakefile +6 -0
  3. data/bin/cardigan +2 -0
  4. data/lib/cardigan/cli.rb +18 -20
  5. data/lib/cardigan/command/add_transitions.rb +27 -0
  6. data/lib/cardigan/command/batch_update_cards.rb +15 -14
  7. data/lib/cardigan/command/change_status.rb +18 -11
  8. data/lib/cardigan/command/change_value.rb +11 -10
  9. data/lib/cardigan/command/claim_cards.rb +15 -13
  10. data/lib/cardigan/command/commit_changes.rb +15 -0
  11. data/lib/cardigan/command/count_cards.rb +6 -2
  12. data/lib/cardigan/command/create_card.rb +14 -11
  13. data/lib/cardigan/command/destroy_cards.rb +15 -13
  14. data/lib/cardigan/command/edit_value.rb +12 -11
  15. data/lib/cardigan/command/export_cards.rb +9 -4
  16. data/lib/cardigan/command/filter_cards.rb +6 -0
  17. data/lib/cardigan/command/import_cards.rb +18 -4
  18. data/lib/cardigan/command/list_cards.rb +5 -0
  19. data/lib/cardigan/command/open_card.rb +20 -12
  20. data/lib/cardigan/command/open_workflow.rb +14 -12
  21. data/lib/cardigan/command/remove_transitions.rb +25 -0
  22. data/lib/cardigan/command/show_entry.rb +12 -10
  23. data/lib/cardigan/command/specify_display_columns.rb +6 -0
  24. data/lib/cardigan/command/specify_sort_columns.rb +6 -0
  25. data/lib/cardigan/command/total_cards.rb +6 -2
  26. data/lib/cardigan/command/unclaim_cards.rb +13 -13
  27. data/lib/cardigan/command/unfilter_cards.rb +6 -0
  28. data/lib/cardigan/commands.rb +10 -0
  29. data/lib/cardigan/entry_context.rb +7 -12
  30. data/lib/cardigan/filtered_repository.rb +9 -5
  31. data/lib/cardigan/io.rb +1 -1
  32. data/lib/cardigan/root_context.rb +21 -23
  33. data/lib/cardigan/workflow_context.rb +12 -29
  34. data/lib/cardigan/workflow_repository.rb +18 -10
  35. data/spec/command/add_transitions_spec.rb +35 -0
  36. data/spec/command/batch_update_cards_spec.rb +9 -0
  37. data/spec/command/change_status_spec.rb +9 -0
  38. data/spec/command/change_value_spec.rb +9 -0
  39. data/spec/command/claim_cards_spec.rb +9 -0
  40. data/spec/command/commit_changes_spec.rb +9 -0
  41. data/spec/command/count_cards_spec.rb +68 -0
  42. data/spec/command/create_card_spec.rb +9 -0
  43. data/spec/command/destroy_cards_spec.rb +9 -0
  44. data/spec/command/edit_value_spec.rb +9 -0
  45. data/spec/command/export_cards_spec.rb +9 -0
  46. data/spec/command/filter_cards_spec.rb +9 -0
  47. data/spec/command/import_cards_spec.rb +9 -0
  48. data/spec/command/list_cards_spec.rb +9 -0
  49. data/spec/command/open_card_spec.rb +9 -0
  50. data/spec/command/open_workflow_spec.rb +9 -0
  51. data/spec/command/remove_transitions_spec.rb +25 -0
  52. data/spec/command/show_entry_spec.rb +9 -0
  53. data/spec/command/specify_display_columns_spec.rb +9 -0
  54. data/spec/command/specify_sort_columns_spec.rb +9 -0
  55. data/spec/command/total_cards_spec.rb +82 -0
  56. data/spec/command/unfilter_cards_spec.rb +9 -0
  57. data/spec/spec_helper.rb +25 -0
  58. data/spec/text_report_formatter_spec.rb +47 -0
  59. metadata +100 -35
  60. data/lib/cardigan/command/select_columns.rb +0 -20
  61. data/lib/cardigan/context.rb +0 -60
  62. data/lib/cardigan/directory.rb +0 -34
  63. data/lib/cardigan/repository.rb +0 -54
  64. data/lib/cardigan/symbol_extensions.rb +0 -3
data/.gemtest ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ desc 'execute specifications'
4
+ task :test do
5
+ sh 'bundle exec rspec spec'
6
+ end
data/bin/cardigan CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'rubygems'
4
+
3
5
  $:.unshift File.dirname(__FILE__)+'/../lib'
4
6
 
5
7
  require 'cardigan/cli'
data/lib/cardigan/cli.rb CHANGED
@@ -1,28 +1,26 @@
1
1
  require 'cardigan/io'
2
2
  require 'cardigan/root_context'
3
- require 'cardigan/repository'
3
+ require 'flat_hash/directory'
4
+ require 'flat_hash/serialiser'
5
+ require 'flat_hash/repository'
4
6
  require 'cardigan/workflow_repository'
5
7
 
6
- module Cardigan
7
- class Cli
8
- CONFIG_FILE = '.cardigan'
8
+ class Cardigan::Cli
9
+ CONFIG_FILE = '.cardigan'
9
10
 
10
- def initialize io=Io.new
11
- @io = io
12
- @home = Directory.new('~')
13
- end
11
+ def initialize io=Cardigan::Io.new
12
+ @io = io
13
+ @home = FlatHash::Directory.new(FlatHash::Serialiser.new,File.expand_path('~'))
14
+ end
14
15
 
15
- def execute *args
16
- if @home.has_file?(CONFIG_FILE)
17
- config = @home.load(CONFIG_FILE)
18
- else
19
- config = { :name => @io.ask('Enter your full name'),
20
- :email => @io.ask('Enter your email address')
21
- }
22
- @home.store CONFIG_FILE, config
23
- end
24
- name = "\"#{config[:name]}\" <#{config[:email]}>"
25
- RootContext.new(@io, Repository.new('.cards'), name, WorkflowRepository.new('.')).push
26
- end
16
+ def execute *args
17
+ config = @home.exist?(CONFIG_FILE) ? @home[CONFIG_FILE] : {}
18
+ config['name'] = @io.ask('Enter your full name') unless config['name']
19
+ config['email'] = @io.ask('Enter your email address') unless config['email']
20
+ @home[CONFIG_FILE] = config
21
+ repository = FlatHash::Repository.new(FlatHash::Serialiser.new,'.cards')
22
+ name = "\"#{config['name']}\" <#{config['email']}>"
23
+ workflow_repository = Cardigan::WorkflowRepository.new('.')
24
+ Cardigan::RootContext.new(@io, repository, name, workflow_repository).push
27
25
  end
28
26
  end
@@ -0,0 +1,27 @@
1
+ require 'cardigan/commands'
2
+
3
+ class Cardigan::Command::AddTransitions
4
+ attr_reader :usage, :help
5
+
6
+ def initialize entry, io
7
+ @entry, @io = entry, io
8
+ @usage = '<start status> [<subsequent status>]+'
9
+ @help = 'Creates transitions from a starting status to a number of subsequent statuses'
10
+ end
11
+
12
+ def execute text=nil
13
+ unless text and !text.empty?
14
+ @io.say 'missing required start status'
15
+ return
16
+ end
17
+ name, *states = text.scan(/\w+/)
18
+ if states.empty?
19
+ @io.say 'missing required subsequent status'
20
+ return
21
+ end
22
+ @entry[name] ||= []
23
+ states = states.uniq
24
+ @entry[name] += states
25
+ states.each {|state| @entry[state] ||= [] }
26
+ end
27
+ end
@@ -1,20 +1,21 @@
1
+ require 'cardigan/commands'
1
2
  require 'cardigan/card_editor'
2
3
 
3
- module Cardigan
4
- module Command
5
- class BatchUpdateCards
6
- def initialize repository, io
7
- @repository, @io = repository, io
8
- end
4
+ class Cardigan::Command::BatchUpdateCards
5
+ attr_reader :usage, :help
9
6
 
10
- def execute text
11
- key, *rest = text.scan(/\w+/)
12
- value = @io.ask("Enter the new value for #{key}")
13
- @repository.each_card_from_indices(rest.join(' ')) do |card|
14
- Cardigan::CardEditor.new(card, @io).set key, value
15
- @repository.save card
16
- end
17
- end
7
+ def initialize repository, io
8
+ @repository, @io = repository, io
9
+ @usage = '<field> <number>*'
10
+ @help = 'Sets the specified field to a new value for the specified cards (by index in the list)'
11
+ end
12
+
13
+ def execute text
14
+ key, *rest = text.scan(/\w+/)
15
+ value = @io.ask("Enter the new value for #{key}")
16
+ @repository.each_card_from_indices(rest.join(' ')) do |card|
17
+ Cardigan::CardEditor.new(card, @io).set key, value
18
+ @repository[card.id] = card
18
19
  end
19
20
  end
20
21
  end
@@ -1,13 +1,20 @@
1
- module Cardigan
2
- module Command
3
- class ChangeStatus
4
- def initialize entry
5
- @entry = entry
6
- end
7
-
8
- def execute status
9
- @entry['status'] = status
10
- end
11
- end
1
+ require 'cardigan/commands'
2
+
3
+ class Cardigan::Command::ChangeStatus
4
+ attr_reader :usage, :help
5
+
6
+ def initialize entry, workflow_repository
7
+ @entry, @workflow_repository = entry, workflow_repository
8
+ @usage = '<new status>'
9
+ @help = 'Changes the status of the current entry'
10
+ end
11
+
12
+ def completion text
13
+ status = @entry['status'] || 'none'
14
+ @workflow_repository.load[status].grep(/^#{text}/).sort || []
15
+ end
16
+
17
+ def execute status
18
+ @entry['status'] = status
12
19
  end
13
20
  end
@@ -1,15 +1,16 @@
1
+ require 'cardigan/commands'
1
2
  require 'cardigan/card_editor'
2
3
 
3
- module Cardigan
4
- module Command
5
- class ChangeValue
6
- def initialize entry, io
7
- @entry, @io = entry, io
8
- end
4
+ class Cardigan::Command::ChangeValue
5
+ attr_reader :usage, :help
9
6
 
10
- def execute key
11
- Cardigan::CardEditor.new(@entry, @io).set key, @io.ask("Enter the new value for #{key}")
12
- end
13
- end
7
+ def initialize entry, io
8
+ @entry, @io = entry, io
9
+ @usage = '<key>'
10
+ @help = 'Prompt for a new value to associate with the specified key'
11
+ end
12
+
13
+ def execute key
14
+ Cardigan::CardEditor.new(@entry, @io).set key, @io.ask("Enter the new value for #{key}")
14
15
  end
15
16
  end
@@ -1,17 +1,19 @@
1
- module Cardigan
2
- module Command
3
- class ClaimCards
4
- def initialize repository, io, name
5
- @repository, @io, @name = repository, io, name
6
- end
1
+ require 'cardigan/commands'
7
2
 
8
- def execute numbers
9
- @repository.each_card_from_indices(numbers) do |card|
10
- @io.say "claiming \"#{card['name']}\""
11
- card['owner'] = @name
12
- @repository.save card
13
- end
14
- end
3
+ class Cardigan::Command::ClaimCards
4
+ attr_reader :usage, :help
5
+
6
+ def initialize repository, io, name
7
+ @repository, @io, @name = repository, io, name
8
+ @usage = '<number>*'
9
+ @help = 'Sets you as the owner of the specified cards (by index in the list)'
10
+ end
11
+
12
+ def execute numbers
13
+ @repository.each_card_from_indices(numbers || '') do |card|
14
+ @io.say "claiming \"#{card['name']}\""
15
+ card['owner'] = @name
16
+ @repository[card.id] = card
15
17
  end
16
18
  end
17
19
  end
@@ -0,0 +1,15 @@
1
+ require 'cardigan/commands'
2
+
3
+ class Cardigan::Command::CommitChanges
4
+ attr_reader :usage, :help
5
+
6
+ def initialize repository, io
7
+ @io, @repository = io, repository
8
+ @usage = "<commit message>"
9
+ @help = "Commits _all_ changes (adds, removes and modifications) to the source control system\nWarning: Use with caution. This will not only commit changes to cards - all modifications will be committed."
10
+ end
11
+
12
+ def execute text=nil
13
+ @repository.addremovecommit text
14
+ end
15
+ end
@@ -1,9 +1,13 @@
1
- require 'cardigan/context'
1
+ require 'cardigan/commands'
2
2
  require 'cardigan/text_report_formatter'
3
3
 
4
4
  class Cardigan::Command::CountCards
5
+ attr_reader :usage, :help
6
+
5
7
  def initialize repository, io
6
8
  @repository, @io = repository, io
9
+ @usage = "<grouping field>*"
10
+ @help = "Counts cards aggregated across the specified grouping fields"
7
11
  end
8
12
 
9
13
  def execute text=nil
@@ -12,7 +16,7 @@ class Cardigan::Command::CountCards
12
16
  lengths = Array.new(grouping_fields.size, 0)
13
17
  counts = {}
14
18
  total = 0
15
- @repository.each do |card|
19
+ @repository.cards.each do |card|
16
20
  grouping_fields.each_with_index do |grouping_field,index|
17
21
  lengths[index] = card[grouping_field].size if card[grouping_field] and card[grouping_field].size > lengths[index]
18
22
  end
@@ -1,13 +1,16 @@
1
- module Cardigan
2
- module Command
3
- class CreateCard
4
- def initialize repository
5
- @repository = repository
6
- end
1
+ require 'cardigan/commands'
2
+ require 'uuidtools'
7
3
 
8
- def execute name
9
- @repository.save @repository.find_or_create(name)
10
- end
11
- end
4
+ class Cardigan::Command::CreateCard
5
+ attr_reader :usage, :help
6
+
7
+ def initialize repository
8
+ @repository = repository
9
+ @usage = '<name>'
10
+ @help = 'Creates a new card with the specified name (without opening it for editing)'
11
+ end
12
+
13
+ def execute name
14
+ @repository[UUIDTools::UUID.random_create.to_s] = {'name' => name }
12
15
  end
13
- end
16
+ end
@@ -1,16 +1,18 @@
1
- module Cardigan
2
- module Command
3
- class DestroyCards
4
- def initialize repository, io
5
- @repository, @io = repository, io
6
- end
1
+ require 'cardigan/commands'
7
2
 
8
- def execute numbers
9
- @repository.each_card_from_indices(numbers) do |card|
10
- @io.say "destroying \"#{card['name']}\""
11
- @repository.destroy card
12
- end
13
- end
3
+ class Cardigan::Command::DestroyCards
4
+ attr_reader :usage, :help
5
+
6
+ def initialize repository, io
7
+ @repository, @io = repository, io
8
+ @usage = '<number>*'
9
+ @help = 'Destroys the specified cards (by index in the list)'
10
+ end
11
+
12
+ def execute numbers
13
+ @repository.each_card_from_indices(numbers) do |card|
14
+ @io.say "destroying \"#{card['name']}\""
15
+ @repository.destroy card.id
14
16
  end
15
17
  end
16
- end
18
+ end
@@ -1,17 +1,18 @@
1
+ require 'cardigan/commands'
1
2
  require 'splat'
2
3
  require 'cardigan/card_editor'
3
4
 
4
- module Cardigan
5
- module Command
6
- class EditValue
7
- def initialize entry, io
8
- @entry, @io = entry, io
9
- end
5
+ class Cardigan::Command::EditValue
6
+ attr_reader :usage, :help
10
7
 
11
- def execute key
12
- value = @entry[key] ? @entry[key] : ''
13
- Cardigan::CardEditor.new(@entry, @io).set key, value.to_editor
14
- end
15
- end
8
+ def initialize entry, io
9
+ @entry, @io = entry, io
10
+ @usage = '<key>'
11
+ @help = 'Launch default editor to specify a new value to associate with the specified key'
12
+ end
13
+
14
+ def execute key
15
+ value = @entry[key] ? @entry[key] : ''
16
+ Cardigan::CardEditor.new(@entry, @io).set key, value.to_editor
16
17
  end
17
18
  end
@@ -1,17 +1,22 @@
1
+ require 'cardigan/commands'
1
2
  require 'csv'
2
3
 
3
4
  class Cardigan::Command::ExportCards
5
+ attr_reader :usage, :help
6
+
4
7
  def initialize repository
5
8
  @repository = repository
9
+ @usage = '<filename>'
10
+ @help = 'Exports all cards according to the current filter'
6
11
  end
7
12
 
8
13
  def execute filename
9
14
  filename += ".csv"
10
- columns = @repository.columns
15
+ columns = @repository.columns - ['id']
11
16
  CSV.open(filename, 'w') do |writer|
12
- writer << columns
13
- @repository.each do |card|
14
- writer << columns.map {|column| card[column] ? card[column] : ''}
17
+ writer << (['id'] + columns)
18
+ @repository.cards.each do |card|
19
+ writer << ([card.id] + columns.map {|column| card[column] ? card[column] : ''})
15
20
  end
16
21
  end
17
22
  end
@@ -1,6 +1,12 @@
1
1
  require 'cardigan/command/list_cards'
2
2
 
3
3
  class Cardigan::Command::FilterCards < Cardigan::Command::ListCards
4
+ def initialize repository, io
5
+ super
6
+ @usage = '<ruby expression>'
7
+ @help = "Sets the filter on cards to be displayed\nThis filter is a ruby expression that must return a boolean.\nBound variables are card (a hash) and me (a string)"
8
+ end
9
+
4
10
  def execute filter
5
11
  @repository.filter = filter
6
12
  begin
@@ -1,8 +1,14 @@
1
+ require 'cardigan/commands'
1
2
  require 'csv'
3
+ require 'uuidtools'
2
4
 
3
5
  class Cardigan::Command::ImportCards
6
+ attr_reader :usage, :help
7
+
4
8
  def initialize repository, io
5
9
  @repository, @io = repository, io
10
+ @usage = '<filename>'
11
+ @help = "Imports cards from the specific csv file.\nNote that if the file does not contain an id column, all new cards will be created.\nOtherwise, existing cards with a matching id will be updated."
6
12
  end
7
13
 
8
14
  def execute filename
@@ -14,14 +20,22 @@ class Cardigan::Command::ImportCards
14
20
  header, id_index = nil, nil
15
21
  CSV.open(filename, 'r') do |row|
16
22
  if header
17
- card = @repository.load(row[id_index]) if id_index and row[id_index]
18
- @io.say card ? "updating #{card['id']}" : "creating new card"
19
- card = @repository.create unless card
23
+ if id_index and row[id_index]
24
+ id = row[id_index]
25
+ card = @repository[id] if @repository.exist?(id)
26
+ end
27
+ if card
28
+ puts "updating #{id}"
29
+ else
30
+ id = UUIDTools::UUID.random_create.to_s
31
+ card = {}
32
+ puts "creating card #{id}"
33
+ end
20
34
  editor = Cardigan::CardEditor.new(card, @io)
21
35
  header.each_with_index do |field, index|
22
36
  editor.set field, row[index]
23
37
  end
24
- @repository.save card
38
+ @repository[id] = card
25
39
  else
26
40
  header = row
27
41
  id_index = header.find_index('id')
@@ -1,8 +1,13 @@
1
+ require 'cardigan/commands'
1
2
  require 'cardigan/text_report_formatter'
2
3
 
3
4
  class Cardigan::Command::ListCards
5
+ attr_reader :usage, :help
6
+
4
7
  def initialize repository, io
5
8
  @repository, @io = repository, io
9
+ @usage = ''
10
+ @help = 'Lists all cards that match the current filter'
6
11
  end
7
12
 
8
13
  def execute text
@@ -1,17 +1,25 @@
1
1
  require 'cardigan/entry_context'
2
+ require 'uuidtools'
2
3
 
3
- module Cardigan
4
- module Command
5
- class OpenCard
6
- def initialize repository, workflow_repository, io
7
- @repository, @workflow_repository, @io = repository, workflow_repository, io
8
- end
4
+ class Cardigan::Command::OpenCard
5
+ attr_reader :usage, :help
9
6
 
10
- def execute name
11
- card = @repository.find_or_create(name)
12
- EntryContext.new(@io, @workflow_repository, card).push
13
- @repository.save card
14
- end
15
- end
7
+ def initialize repository, workflow_repository, io
8
+ @repository, @workflow_repository, @io = repository, workflow_repository, io
9
+ @usage = '<card name>'
10
+ @help = 'Opens the specified card for editing'
11
+ end
12
+
13
+ def execute name
14
+ entry = @repository.cards.find { |entry| entry['name'] == name }
15
+ id = entry ? entry.id : UUIDTools::UUID.random_create.to_s
16
+ entry ||= {'name' => name}
17
+ original = entry.dup
18
+ Cardigan::EntryContext.new(@io, @workflow_repository, entry).push
19
+ @repository[id] = entry unless original == entry
20
+ end
21
+
22
+ def completion text
23
+ @repository.cards.map {|card| card['name'] }.grep(/^#{Regexp.escape(text)}/).sort
16
24
  end
17
25
  end
@@ -1,17 +1,19 @@
1
+ require 'cardigan/commands'
1
2
  require 'cardigan/workflow_context'
2
3
 
3
- module Cardigan
4
- module Command
5
- class OpenWorkflow
6
- def initialize workflow_repository, io
7
- @workflow_repository, @io = workflow_repository, io
8
- end
4
+ class Cardigan::Command::OpenWorkflow
5
+ attr_reader :usage, :help
9
6
 
10
- def execute name
11
- workflow = @workflow_repository.load
12
- WorkflowContext.new(@io, workflow).push
13
- @workflow_repository.save workflow
14
- end
15
- end
7
+ def initialize workflow_repository, io
8
+ @workflow_repository, @io = workflow_repository, io
9
+ @usage = ''
10
+ @help = 'Opens the current workflow for editing'
11
+ end
12
+
13
+ def execute name
14
+ workflow = @workflow_repository.load
15
+ original = workflow.dup
16
+ Cardigan::WorkflowContext.new(@io, workflow).push
17
+ @workflow_repository.save workflow unless workflow == original
16
18
  end
17
19
  end
@@ -0,0 +1,25 @@
1
+ require 'cardigan/commands'
2
+
3
+ class Cardigan::Command::RemoveTransitions
4
+ attr_reader :usage, :help
5
+
6
+ def initialize entry, io
7
+ @entry, @io = entry, io
8
+ @usage = '<start status> [<subsequent status>]+'
9
+ @help = 'Removes transitions from a starting status to a number of subsequent statuses'
10
+ end
11
+
12
+ def execute text=nil
13
+ unless text and !text.empty?
14
+ @io.say 'missing required start status'
15
+ return
16
+ end
17
+ name, *states = text.scan(/\w+/)
18
+ if states.empty?
19
+ @io.say 'missing required subsequent status'
20
+ return
21
+ end
22
+ name, *states = text.scan(/\w+/)
23
+ @entry[name] -= states
24
+ end
25
+ end
@@ -1,13 +1,15 @@
1
- module Cardigan
2
- module Command
3
- class ShowEntry
4
- def initialize entry, io
5
- @entry, @io = entry, io
6
- end
1
+ require 'cardigan/commands'
7
2
 
8
- def execute ignored=nil
9
- @entry.keys.sort.each { |key| @io.say "#{key}: #{@entry[key].inspect}" }
10
- end
11
- end
3
+ class Cardigan::Command::ShowEntry
4
+ attr_reader :usage, :help
5
+
6
+ def initialize entry, io
7
+ @entry, @io = entry, io
8
+ @usage = ''
9
+ @help = 'Shows the entire content of the entry'
10
+ end
11
+
12
+ def execute ignored=nil
13
+ @entry.keys.sort.each { |key| @io.say "#{key}: #{@entry[key].inspect}" }
12
14
  end
13
15
  end
@@ -1,6 +1,12 @@
1
1
  require 'cardigan/command/list_cards'
2
2
 
3
3
  class Cardigan::Command::SpecifyDisplayColumns < Cardigan::Command::ListCards
4
+ def initialize repository, io
5
+ super
6
+ @usage = '<column>*'
7
+ @help = 'Specify the list of columns to display'
8
+ end
9
+
4
10
  def execute text
5
11
  if text
6
12
  @repository.display_columns = text.scan(/\w+/)
@@ -1,6 +1,12 @@
1
1
  require 'cardigan/command/list_cards'
2
2
 
3
3
  class Cardigan::Command::SpecifySortColumns < Cardigan::Command::ListCards
4
+ def initialize repository, io
5
+ super
6
+ @usage = '<column>*'
7
+ @help = 'Specify the list of columns to sort by'
8
+ end
9
+
4
10
  def execute text
5
11
  if text
6
12
  @repository.sort_columns = text.scan(/\w+/)
@@ -1,9 +1,13 @@
1
- require 'cardigan/context'
1
+ require 'cardigan/commands'
2
2
  require 'cardigan/text_report_formatter'
3
3
 
4
4
  class Cardigan::Command::TotalCards
5
+ attr_reader :usage, :help
6
+
5
7
  def initialize repository, io
6
8
  @repository, @io = repository, io
9
+ @usage = '<numeric field> <grouping field>*'
10
+ @help = 'Calculates totals for the specified numeric field aggregated across the specified grouping fields'
7
11
  end
8
12
 
9
13
  def execute text=nil
@@ -13,7 +17,7 @@ class Cardigan::Command::TotalCards
13
17
  return
14
18
  end
15
19
  counts = {}
16
- @repository.each do |card|
20
+ @repository.cards.each do |card|
17
21
  key = grouping_fields.map {|grouping_field| card[grouping_field] ? card[grouping_field] : ''}
18
22
  value = card[count_field].to_i
19
23
  counts[key] = counts[key] ? counts[key] + value : value