brat 0.1.1

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 (101) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +24 -0
  6. data/README.md +103 -0
  7. data/Rakefile +9 -0
  8. data/bin/brat +7 -0
  9. data/brat.gemspec +26 -0
  10. data/lib/brat.rb +37 -0
  11. data/lib/brat/api.rb +17 -0
  12. data/lib/brat/cli.rb +47 -0
  13. data/lib/brat/cli_helpers.rb +175 -0
  14. data/lib/brat/client.rb +18 -0
  15. data/lib/brat/client/branches.rb +79 -0
  16. data/lib/brat/client/groups.rb +88 -0
  17. data/lib/brat/client/issues.rb +92 -0
  18. data/lib/brat/client/merge_requests.rb +107 -0
  19. data/lib/brat/client/milestones.rb +57 -0
  20. data/lib/brat/client/notes.rb +106 -0
  21. data/lib/brat/client/projects.rb +298 -0
  22. data/lib/brat/client/repositories.rb +78 -0
  23. data/lib/brat/client/snippets.rb +86 -0
  24. data/lib/brat/client/system_hooks.rb +58 -0
  25. data/lib/brat/client/users.rb +123 -0
  26. data/lib/brat/configuration.rb +40 -0
  27. data/lib/brat/error.rb +42 -0
  28. data/lib/brat/help.rb +44 -0
  29. data/lib/brat/objectified_hash.rb +24 -0
  30. data/lib/brat/request.rb +101 -0
  31. data/lib/brat/shell.rb +49 -0
  32. data/lib/brat/version.rb +3 -0
  33. data/spec/brat/cli_spec.rb +80 -0
  34. data/spec/brat/client/branches_spec.rb +103 -0
  35. data/spec/brat/client/groups_spec.rb +111 -0
  36. data/spec/brat/client/issues_spec.rb +122 -0
  37. data/spec/brat/client/merge_requests_spec.rb +124 -0
  38. data/spec/brat/client/milestones_spec.rb +66 -0
  39. data/spec/brat/client/notes_spec.rb +156 -0
  40. data/spec/brat/client/projects_spec.rb +357 -0
  41. data/spec/brat/client/repositories_spec.rb +92 -0
  42. data/spec/brat/client/snippets_spec.rb +85 -0
  43. data/spec/brat/client/system_hooks_spec.rb +69 -0
  44. data/spec/brat/client/users_spec.rb +192 -0
  45. data/spec/brat/objectified_hash_spec.rb +23 -0
  46. data/spec/brat/request_spec.rb +48 -0
  47. data/spec/brat_spec.rb +65 -0
  48. data/spec/fixtures/branch.json +1 -0
  49. data/spec/fixtures/branches.json +1 -0
  50. data/spec/fixtures/comment_merge_request.json +1 -0
  51. data/spec/fixtures/create_branch.json +1 -0
  52. data/spec/fixtures/create_merge_request.json +1 -0
  53. data/spec/fixtures/error_already_exists.json +1 -0
  54. data/spec/fixtures/group.json +60 -0
  55. data/spec/fixtures/group_create.json +1 -0
  56. data/spec/fixtures/group_member.json +1 -0
  57. data/spec/fixtures/group_member_delete.json +1 -0
  58. data/spec/fixtures/group_members.json +1 -0
  59. data/spec/fixtures/groups.json +2 -0
  60. data/spec/fixtures/issue.json +1 -0
  61. data/spec/fixtures/issues.json +1 -0
  62. data/spec/fixtures/key.json +1 -0
  63. data/spec/fixtures/keys.json +1 -0
  64. data/spec/fixtures/merge_request.json +1 -0
  65. data/spec/fixtures/merge_request_comments.json +1 -0
  66. data/spec/fixtures/merge_requests.json +1 -0
  67. data/spec/fixtures/milestone.json +1 -0
  68. data/spec/fixtures/milestones.json +1 -0
  69. data/spec/fixtures/note.json +1 -0
  70. data/spec/fixtures/notes.json +1 -0
  71. data/spec/fixtures/project.json +1 -0
  72. data/spec/fixtures/project_commit.json +13 -0
  73. data/spec/fixtures/project_commit_diff.json +10 -0
  74. data/spec/fixtures/project_commits.json +1 -0
  75. data/spec/fixtures/project_delete_key.json +8 -0
  76. data/spec/fixtures/project_events.json +1 -0
  77. data/spec/fixtures/project_for_user.json +1 -0
  78. data/spec/fixtures/project_fork_link.json +1 -0
  79. data/spec/fixtures/project_hook.json +1 -0
  80. data/spec/fixtures/project_hooks.json +1 -0
  81. data/spec/fixtures/project_issues.json +1 -0
  82. data/spec/fixtures/project_key.json +6 -0
  83. data/spec/fixtures/project_keys.json +6 -0
  84. data/spec/fixtures/project_tags.json +1 -0
  85. data/spec/fixtures/projects.json +1 -0
  86. data/spec/fixtures/protect_branch.json +1 -0
  87. data/spec/fixtures/session.json +1 -0
  88. data/spec/fixtures/snippet.json +1 -0
  89. data/spec/fixtures/snippets.json +1 -0
  90. data/spec/fixtures/system_hook.json +1 -0
  91. data/spec/fixtures/system_hook_test.json +1 -0
  92. data/spec/fixtures/system_hooks.json +1 -0
  93. data/spec/fixtures/tag.json +1 -0
  94. data/spec/fixtures/team_member.json +1 -0
  95. data/spec/fixtures/team_members.json +1 -0
  96. data/spec/fixtures/unprotect_branch.json +1 -0
  97. data/spec/fixtures/update_merge_request.json +1 -0
  98. data/spec/fixtures/user.json +1 -0
  99. data/spec/fixtures/users.json +1 -0
  100. data/spec/spec_helper.rb +74 -0
  101. metadata +281 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 057d5021e30f18c5dc02e68e144aac17b41d1cc9
4
+ data.tar.gz: 32c68c61399d306e309e36b2720a433fb9113a52
5
+ SHA512:
6
+ metadata.gz: b6a52cc17f8bece0515273aa515315bb96563997734772fa844a34b1d1e89f72b2f7354f78f52bdca0f2c7f91cd70818087650d056ed62e9047e46557bd46ee4
7
+ data.tar.gz: fcf7496ccd8efde5c835f1e03c49e0a6473ee851bd00843a3e3274adc5f90f80a9ce9a84f8d1b1cf355de606727f3d2b0065b6b1ffc0d122134cf32639b9d9b3
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea
19
+ .ruby-version
20
+ .ruby-gemset
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in brat.gemspec
4
+ gemspec
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2012-2014 Nihad Abbasov <mail@narkoz.me>
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
+ POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,103 @@
1
+ # Brat
2
+
3
+ [website](http://brat.io/brat-io/brat)
4
+ [![build status](http://ci.brat.io/projects/7/status.png?ref=master)](http://ci.brat.io/projects/7?ref=master)
5
+
6
+ Brat is a wrapper and CLI for (Brat.io)[http://brat.io/brat-io/brat]. We are currently in pre-release.
7
+
8
+ ## Installation
9
+
10
+ Install it from rubygems:
11
+
12
+ ```sh
13
+ gem install brat
14
+ ```
15
+
16
+ Or add to a Gemfile:
17
+
18
+ ```ruby
19
+ gem 'brat'
20
+ # gem 'brat', :git => 'git://brat.io/brat-io/brat.git'
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ Rails Configuration example:
26
+
27
+ ```ruby
28
+ Brat.configure do |config|
29
+ config.private_token = 'qEsq1pt6HJPaNciie3MG' # user's private token, default: ENV['BRAT_API_PRIVATE_TOKEN']
30
+ # Optional
31
+ # config.endpoint = 'http://brat.io/api/v3' # API endpoint URL, default: 'http://brat.io/api/v3'
32
+ # config.user_agent = 'Custom User Agent' # user agent, default: 'Brat Ruby Gem [version]'
33
+ # config.sudo = 'user' # username for sudo mode, default: nil
34
+ end
35
+ ```
36
+
37
+ Usage examples:
38
+
39
+ ```ruby
40
+ # set a user private token
41
+ Brat.private_token = 'qEsq1pt6HJPaNciie3MG'
42
+ # => "qEsq1pt6HJPaNciie3MG"
43
+
44
+ # list projects
45
+ Brat.projects(:per_page => 5)
46
+ # => [#<Brat::ObjectifiedHash:0x000000023326e0 @data={"id"=>1, "code"=>"brute", "name"=>"Brute", "description"=>nil, "path"=>"brute", "default_branch"=>nil, "owner"=>#<Brat::ObjectifiedHash:0x00000002331600 @data={"id"=>1, "email"=>"john@example.com", "name"=>"John Smith", "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>, "private"=>true, "issues_enabled"=>true, "merge_requests_enabled"=>true, "wall_enabled"=>true, "wiki_enabled"=>true, "created_at"=>"2012-09-17T09:41:56Z"}>, #<Brat::ObjectifiedHash:0x000000023450d8 @data={"id"=>2, "code"=>"mozart", "name"=>"Mozart", "description"=>nil, "path"=>"mozart", "default_branch"=>nil, "owner"=>#<Brat::ObjectifiedHash:0x00000002344ca0 @data={"id"=>1, "email"=>"john@example.com", "name"=>"John Smith", "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>, "private"=>true, "issues_enabled"=>true, "merge_requests_enabled"=>true, "wall_enabled"=>true, "wiki_enabled"=>true, "created_at"=>"2012-09-17T09:41:57Z"}>, #<Brat::ObjectifiedHash:0x00000002344958 @data={"id"=>3, "code"=>"brat", "name"=>"Brat", "description"=>nil, "path"=>"brat", "default_branch"=>nil, "owner"=>#<Brat::ObjectifiedHash:0x000000023447a0 @data={"id"=>1, "email"=>"john@example.com", "name"=>"John Smith", "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>, "private"=>true, "issues_enabled"=>true, "merge_requests_enabled"=>true, "wall_enabled"=>true, "wiki_enabled"=>true, "created_at"=>"2012-09-17T09:41:58Z"}>]
47
+
48
+ # initialize a new client
49
+ g = Brat.client(:endpoint => 'https://brat.io/api/v3', private_token: 'qEsq1pt6HJPaNciie3MG')
50
+ # => #<Brat::Client:0x00000001e62408 @endpoint="https://api.example.com", @private_token="qEsq1pt6HJPaNciie3MG", @user_agent="Brat Ruby Gem 0.1.1">
51
+
52
+ # get a user
53
+ user = g.user
54
+ # => #<Brat::ObjectifiedHash:0x00000002217990 @data={"id"=>1, "email"=>"john@example.com", "name"=>"John Smith", "bio"=>nil, "skype"=>"", "linkedin"=>"", "twitter"=>"john", "dark_scheme"=>false, "theme_id"=>1, "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>
55
+
56
+ # get a user's email
57
+ user.email
58
+ # => "john@example.com"
59
+
60
+ ```
61
+
62
+ ## CLI
63
+
64
+ Usage examples:
65
+
66
+ ```sh
67
+ # set your private_token
68
+ # list users
69
+ brat users
70
+
71
+ # get current user
72
+ brat user
73
+
74
+ # get a user
75
+ brat user 2
76
+
77
+ # filter output
78
+ brat user --only=id,username
79
+
80
+ brat user --except=email,bio
81
+ ```
82
+
83
+ ## CLI Shell
84
+
85
+ Usage examples:
86
+
87
+ ```sh
88
+ # start shell session
89
+ brat shell
90
+
91
+ # list available commands
92
+ brat> help
93
+
94
+ # list groups
95
+ brat> groups
96
+
97
+ # protect a branch
98
+ brat> protect_branch 1 master
99
+ ```
100
+
101
+ ## License
102
+
103
+ Released under the BSD 2-clause license. See LICENSE.txt for details.
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec) do |spec|
5
+ spec.pattern = FileList['spec/**/*_spec.rb']
6
+ spec.rspec_opts = ['--color', '--format d']
7
+ end
8
+
9
+ task :default => :spec
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path('../../lib', __FILE__)
4
+
5
+ require 'brat/cli'
6
+
7
+ Brat::CLI.start(ARGV)
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'brat/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "brat"
8
+ gem.version = Brat::VERSION
9
+ gem.authors = ["John-Henry Liberty"]
10
+ gem.email = ["johnhenry.liberty@gmail.com"]
11
+ gem.description = %q{Ruby client and CLI for Brat.io}
12
+ gem.summary = %q{A Ruby wrapper and CLI for the Brat.io API}
13
+ gem.homepage = "https://github.com/jhliberty/brat-cli"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_runtime_dependency 'httparty'
21
+ gem.add_runtime_dependency 'terminal-table'
22
+
23
+ gem.add_development_dependency 'rake'
24
+ gem.add_development_dependency 'rspec'
25
+ gem.add_development_dependency 'webmock'
26
+ end
@@ -0,0 +1,37 @@
1
+ require 'brat/version'
2
+ require 'brat/objectified_hash'
3
+ require 'brat/configuration'
4
+ require 'brat/error'
5
+ require 'brat/request'
6
+ require 'brat/api'
7
+ require 'brat/client'
8
+
9
+ module Brat
10
+ extend Configuration
11
+
12
+ # Alias for Brat::Client.new
13
+ #
14
+ # @return [Brat::Client]
15
+ def self.client(options={})
16
+ Brat::Client.new(options)
17
+ end
18
+
19
+ # Delegate to Brat::Client
20
+ def self.method_missing(method, *args, &block)
21
+ return super unless client.respond_to?(method)
22
+ client.send(method, *args, &block)
23
+ end
24
+
25
+ # Delegate to Brat::Client
26
+ def self.respond_to?(method)
27
+ return client.respond_to?(method) || super
28
+ end
29
+
30
+ # Returns an unsorted array of available client methods.
31
+ #
32
+ # @return [Array<Symbol>]
33
+ def self.actions
34
+ hidden = /endpoint|private_token|user_agent|sudo|get|post|put|\Adelete\z|validate|set_request_defaults/
35
+ (Brat::Client.instance_methods - Object.methods).reject {|e| e[hidden]}
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ module Brat
2
+ # @private
3
+ class API < Request
4
+ # @private
5
+ attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
6
+
7
+ # Creates a new API.
8
+ # @raise [Error:MissingCredentials]
9
+ def initialize(options={})
10
+ options = Brat.options.merge(options)
11
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
12
+ send("#{key}=", options[key])
13
+ end
14
+ set_request_defaults @endpoint, @private_token, @sudo
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,47 @@
1
+ require 'brat'
2
+ require 'terminal-table/import'
3
+ require_relative 'cli_helpers'
4
+ require_relative 'shell'
5
+
6
+ class Brat::CLI
7
+ extend Helpers
8
+
9
+ def self.start(args)
10
+ command = args.shift.strip rescue 'help'
11
+ run(command, args)
12
+ end
13
+
14
+ def self.run(cmd, args=[])
15
+ case cmd
16
+ when 'help'
17
+ puts actions_table
18
+ when 'info'
19
+ endpoint = Brat.endpoint ? Brat.endpoint : 'not set'
20
+ private_token = Brat.private_token ? Brat.private_token : 'not set'
21
+ puts "Brat endpoint is #{endpoint}"
22
+ puts "Brat private token is #{private_token}"
23
+ puts "Ruby Version is #{RUBY_VERSION}"
24
+ puts "Brat Ruby Gem #{Brat::VERSION}"
25
+ when '-v', '--version'
26
+ puts "Brat Ruby Gem #{Brat::VERSION}"
27
+ when 'shell'
28
+ Brat::Shell.start
29
+ else
30
+ unless valid_command?(cmd)
31
+ puts "Unknown command. Run `brat help` for a list of available commands."
32
+ exit(1)
33
+ end
34
+
35
+ if args.any? && (args.last.start_with?('--only=') || args.last.start_with?('--except='))
36
+ command_args = args[0..-2]
37
+ else
38
+ command_args = args
39
+ end
40
+
41
+ confirm_command(cmd)
42
+
43
+ data = brat_helper(cmd, command_args) { exit(1) }
44
+ output_table(cmd, args, data)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,175 @@
1
+ class Brat::CLI
2
+ # Defines methods related to CLI output and formatting.
3
+ module Helpers
4
+ extend self
5
+
6
+ # Returns filtered required fields.
7
+ #
8
+ # @return [Array]
9
+ def required_fields(args)
10
+ if args.any? && args.last.start_with?('--only=')
11
+ args.last.gsub('--only=', '').split(',')
12
+ else
13
+ []
14
+ end
15
+ end
16
+
17
+ # Returns filtered excluded fields.
18
+ #
19
+ # @return [Array]
20
+ def excluded_fields(args)
21
+ if args.any? && args.last.start_with?('--except=')
22
+ args.last.gsub('--except=', '').split(',')
23
+ else
24
+ []
25
+ end
26
+ end
27
+
28
+ # Confirms command is valid.
29
+ #
30
+ # @return [Boolean]
31
+ def valid_command?(cmd)
32
+ command = cmd.is_a?(Symbol) ? cmd : cmd.to_sym
33
+ Brat.actions.include?(command)
34
+ end
35
+
36
+ # Confirms command with a desctructive action.
37
+ #
38
+ # @return [String]
39
+ def confirm_command(cmd)
40
+ if cmd.start_with?('remove_') || cmd.start_with?('delete_')
41
+ puts "Are you sure? (y/n)"
42
+ if %w(y yes).include?($stdin.gets.to_s.strip.downcase)
43
+ puts 'Proceeding..'
44
+ else
45
+ puts 'Command aborted.'
46
+ exit(1)
47
+ end
48
+ end
49
+ end
50
+
51
+ # Table with available commands.
52
+ #
53
+ # @return [String]
54
+ def actions_table
55
+ client = Brat::Client.new(endpoint: '')
56
+ actions = Brat.actions
57
+ methods = []
58
+
59
+ actions.each do |action|
60
+ methods << {
61
+ name: action,
62
+ owner: client.method(action).owner.to_s.gsub('Brat::Client::', '')
63
+ }
64
+ end
65
+
66
+ owners = methods.map {|m| m[:owner]}.uniq.sort
67
+ methods_c = methods.group_by {|m| m[:owner]}
68
+ methods_c = methods_c.map {|_, v| [_, v.sort_by {|hv| hv[:name]}] }
69
+ methods_c = Hash[methods_c.sort_by(&:first).map {|k, v| [k, v]}]
70
+ max_column_length = methods_c.values.max_by(&:size).size
71
+
72
+ rows = max_column_length.times.map do |i|
73
+ methods_c.keys.map do |key|
74
+ methods_c[key][i] ? methods_c[key][i][:name] : ''
75
+ end
76
+ end
77
+
78
+ table do |t|
79
+ t.title = "Available commands (#{actions.size} total)"
80
+ t.headings = owners
81
+
82
+ rows.each do |row|
83
+ t.add_row row
84
+ end
85
+ end
86
+ end
87
+
88
+ # Decides which table to use.
89
+ #
90
+ # @return [String]
91
+ def output_table(cmd, args, data)
92
+ case data
93
+ when Brat::ObjectifiedHash
94
+ puts single_record_table(data, cmd, args)
95
+ when Array
96
+ puts multiple_record_table(data, cmd, args)
97
+ else
98
+ puts data.inspect
99
+ end
100
+ end
101
+
102
+ # Table for a single record.
103
+ #
104
+ # @return [String]
105
+ def single_record_table(data, cmd, args)
106
+ hash = data.to_h
107
+ keys = hash.keys.sort {|x, y| x.to_s <=> y.to_s }
108
+ keys = keys & required_fields(args) if required_fields(args).any?
109
+ keys = keys - excluded_fields(args)
110
+
111
+ table do |t|
112
+ t.title = "Brat.#{cmd} #{args.join(', ')}"
113
+
114
+ keys.each_with_index do |key, index|
115
+ case value = hash[key]
116
+ when Hash
117
+ value = 'Hash'
118
+ when nil
119
+ value = 'null'
120
+ end
121
+
122
+ t.add_row [key, value]
123
+ t.add_separator unless keys.size - 1 == index
124
+ end
125
+ end
126
+ end
127
+
128
+ # Table for multiple records.
129
+ #
130
+ # @return [String]
131
+ def multiple_record_table(data, cmd, args)
132
+ return 'No data' if data.empty?
133
+
134
+ arr = data.map(&:to_h)
135
+ keys = arr.first.keys.sort {|x, y| x.to_s <=> y.to_s }
136
+ keys = keys & required_fields(args) if required_fields(args).any?
137
+ keys = keys - excluded_fields(args)
138
+
139
+ table do |t|
140
+ t.title = "Brat.#{cmd} #{args.join(', ')}"
141
+ t.headings = keys
142
+
143
+ arr.each_with_index do |hash, index|
144
+ values = []
145
+
146
+ keys.each do |key|
147
+ case value = hash[key]
148
+ when Hash
149
+ value = 'Hash'
150
+ when nil
151
+ value = 'null'
152
+ end
153
+
154
+ values << value
155
+ end
156
+
157
+ t.add_row values
158
+ t.add_separator unless arr.size - 1 == index
159
+ end
160
+ end
161
+ end
162
+
163
+ # Helper function to call Brat commands with args.
164
+ def brat_helper(cmd, args=[])
165
+ begin
166
+ data = args.any? ? Brat.send(cmd, *args) : Brat.send(cmd)
167
+ rescue => e
168
+ puts e.message
169
+ yield if block_given?
170
+ end
171
+
172
+ data
173
+ end
174
+ end
175
+ end