vmc 0.4.7 → 0.5.0.beta.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 (73) hide show
  1. data/lib/vmc.rb +1 -2
  2. data/lib/vmc/cli.rb +33 -31
  3. data/lib/vmc/cli/app/app.rb +2 -2
  4. data/lib/vmc/cli/app/apps.rb +4 -5
  5. data/lib/vmc/cli/app/crashes.rb +2 -3
  6. data/lib/vmc/cli/app/delete.rb +28 -25
  7. data/lib/vmc/cli/app/env.rb +11 -19
  8. data/lib/vmc/cli/app/files.rb +11 -15
  9. data/lib/vmc/cli/app/health.rb +2 -3
  10. data/lib/vmc/cli/app/instances.rb +3 -3
  11. data/lib/vmc/cli/app/logs.rb +7 -10
  12. data/lib/vmc/cli/app/push.rb +17 -89
  13. data/lib/vmc/cli/app/push/create.rb +2 -0
  14. data/lib/vmc/cli/app/rename.rb +17 -13
  15. data/lib/vmc/cli/app/restart.rb +4 -7
  16. data/lib/vmc/cli/app/routes.rb +14 -11
  17. data/lib/vmc/cli/app/scale.rb +17 -15
  18. data/lib/vmc/cli/app/start.rb +4 -7
  19. data/lib/vmc/cli/app/stats.rb +2 -3
  20. data/lib/vmc/cli/app/stop.rb +3 -5
  21. data/lib/vmc/cli/domain/add_domain.rb +3 -5
  22. data/lib/vmc/cli/domain/create_domain.rb +5 -8
  23. data/lib/vmc/cli/domain/delete_domain.rb +23 -18
  24. data/lib/vmc/cli/domain/domains.rb +4 -7
  25. data/lib/vmc/cli/domain/remove_domain.rb +12 -10
  26. data/lib/vmc/cli/organization/org.rb +6 -7
  27. data/lib/vmc/cli/organization/orgs.rb +19 -19
  28. data/lib/vmc/cli/organization/rename.rb +18 -14
  29. data/lib/vmc/cli/route/create_route.rb +20 -13
  30. data/lib/vmc/cli/route/{delete_route.rb → delete.rb} +22 -17
  31. data/lib/vmc/cli/service/bind.rb +2 -2
  32. data/lib/vmc/cli/service/create.rb +57 -53
  33. data/lib/vmc/cli/service/delete.rb +33 -31
  34. data/lib/vmc/cli/service/rename.rb +17 -14
  35. data/lib/vmc/cli/service/service.rb +5 -8
  36. data/lib/vmc/cli/service/services.rb +14 -18
  37. data/lib/vmc/cli/service/unbind.rb +4 -4
  38. data/lib/vmc/cli/space/create.rb +16 -17
  39. data/lib/vmc/cli/space/delete.rb +34 -31
  40. data/lib/vmc/cli/space/rename.rb +20 -17
  41. data/lib/vmc/cli/space/space.rb +11 -14
  42. data/lib/vmc/cli/space/spaces.rb +14 -16
  43. data/lib/vmc/cli/space/take.rb +1 -3
  44. data/lib/vmc/cli/start/base.rb +2 -0
  45. data/lib/vmc/cli/start/colors.rb +0 -1
  46. data/lib/vmc/cli/start/info.rb +8 -10
  47. data/lib/vmc/cli/start/login.rb +11 -40
  48. data/lib/vmc/cli/start/logout.rb +0 -1
  49. data/lib/vmc/cli/start/register.rb +18 -12
  50. data/lib/vmc/cli/start/target.rb +7 -36
  51. data/lib/vmc/cli/start/target_interactions.rb +3 -1
  52. data/lib/vmc/cli/start/targets.rb +0 -1
  53. data/lib/vmc/cli/user/create.rb +4 -2
  54. data/lib/vmc/version.rb +1 -1
  55. data/spec/factories/organization_factory.rb +5 -0
  56. data/spec/factories/space_factory.rb +15 -0
  57. data/spec/spec_helper.rb +16 -0
  58. data/spec/vmc/cli/app/push/create_spec.rb +2 -1
  59. data/spec/vmc/cli/app/push_spec.rb +1 -1
  60. data/spec/vmc/cli/organization/orgs_spec.rb +119 -0
  61. data/spec/vmc/cli/route/delete_route_spec.rb +3 -3
  62. data/spec/vmc/cli/service/bind_spec.rb +34 -0
  63. data/spec/vmc/cli/service/delete_spec.rb +32 -0
  64. data/spec/vmc/cli/service/service_spec.rb +32 -0
  65. data/spec/vmc/cli/service/unbind_spec.rb +34 -0
  66. data/spec/vmc/cli/space/spaces_spec.rb +120 -0
  67. data/spec/vmc/cli/start/info_spec.rb +38 -0
  68. data/spec/vmc/cli/start/login_spec.rb +40 -0
  69. metadata +127 -113
  70. data/lib/vmc/cli/organization/create_org.rb +0 -28
  71. data/lib/vmc/cli/organization/delete_org.rb +0 -65
  72. data/lib/vmc/cli/service/binding.rb +0 -66
  73. data/lib/vmc/cli/user.rb +0 -118
data/lib/vmc.rb CHANGED
@@ -1,9 +1,8 @@
1
1
  require "vmc/version"
2
2
 
3
3
  require "vmc/cli"
4
- require "vmc/cli/user"
5
4
 
6
- command_files = "../vmc/cli/{app,route,domain,organization,space,service,start}/*.rb"
5
+ command_files = "../vmc/cli/{app,route,domain,organization,space,service,start,user}/*.rb"
7
6
  Dir[File.expand_path(command_files, __FILE__)].each do |file|
8
7
  require file unless File.basename(file) == 'base.rb'
9
8
  end
data/lib/vmc/cli.rb CHANGED
@@ -23,36 +23,32 @@ module VMC
23
23
  include VMC::Interactive
24
24
  include VMC::Spacing
25
25
 
26
- option :help, :alias => "-h", :type => :boolean,
27
- :desc => "Show command usage & instructions"
26
+ option :help, :desc => "Show command usage", :alias => "-h",
27
+ :default => false
28
28
 
29
- option :proxy, :alias => "-u", :value => :email,
30
- :desc => "Act as another user (admin only)"
29
+ option :proxy, :desc => "Act as another user (admin)", :alias => "-u",
30
+ :value => :email
31
31
 
32
- option :version, :alias => "-v", :type => :boolean,
33
- :desc => "Print version number"
32
+ option :version, :desc => "Print version number", :alias => "-v",
33
+ :default => false
34
34
 
35
- option :verbose, :alias => "-V", :type => :boolean,
36
- :desc => "Print extra information"
35
+ option :verbose, :desc => "Print extra information", :alias => "-V",
36
+ :default => false
37
37
 
38
- option :force, :alias => "-f", :type => :boolean,
39
- :default => proc { input[:script] },
40
- :desc => "Skip interaction when possible"
38
+ option :force, :desc => "Skip interaction when possible", :alias => "-f",
39
+ :type => :boolean, :default => proc { input[:script] }
41
40
 
42
- option :quiet, :alias => "-q", :type => :boolean,
43
- :default => proc { input[:script] },
44
- :desc => "Simplify output format"
41
+ option :quiet, :desc => "Simplify output format", :alias => "-q",
42
+ :type => :boolean, :default => proc { input[:script] }
45
43
 
46
- option :script, :type => :boolean,
47
- :default => proc { !$stdout.tty? },
48
- :desc => "Shortcut for --quiet and --force"
44
+ option :script, :desc => "Shortcut for --quiet and --force",
45
+ :type => :boolean, :default => proc { !$stdout.tty? }
49
46
 
50
- option :color, :type => :boolean,
51
- :default => proc { !input[:quiet] },
52
- :desc => "Use colorful output"
47
+ option :color, :desc => "Use colorful output",
48
+ :type => :boolean, :default => proc { !input[:quiet] }
53
49
 
54
- option :trace, :alias => "-t", :type => :boolean,
55
- :desc => "Show API requests and responses"
50
+ option :trace, :desc => "Show API traffic", :alias => "-t",
51
+ :default => false
56
52
 
57
53
 
58
54
  def default_action
@@ -394,24 +390,30 @@ module VMC
394
390
 
395
391
  private
396
392
 
397
- def find_by_name(what)
398
- proc { |name, choices, *_|
393
+ def find_by_name(display, &blk)
394
+ proc { |name, *args|
395
+ choices, _ = args
396
+ choices ||= instance_exec(&blk) if block_given?
397
+
399
398
  choices.find { |c| c.name == name } ||
400
- fail("Unknown #{what} '#{name}'.")
399
+ fail("Unknown #{display} '#{name}'.")
401
400
  }
402
401
  end
403
402
 
404
- def by_name(what, obj = what)
403
+ def by_name(what, display = what)
405
404
  proc { |name, *_|
406
- client.send(:"#{obj}_by_name", name) ||
407
- fail("Unknown #{what} '#{name}'.")
405
+ client.send(:"#{what}_by_name", name) ||
406
+ fail("Unknown #{display} '#{name}'.")
408
407
  }
409
408
  end
410
409
 
411
- def find_by_name_insensitive(what)
412
- proc { |name, choices|
410
+ def find_by_name_insensitive(display, &blk)
411
+ proc { |name, *args|
412
+ choices, _ = args
413
+ choices ||= instance_exec(&blk) if block_given?
414
+
413
415
  choices.find { |c| c.name.upcase == name.upcase } ||
414
- fail("Unknown #{what} '#{name}'.")
416
+ fail("Unknown #{display} '#{name}'.")
415
417
  }
416
418
  end
417
419
  end
@@ -6,8 +6,8 @@ module VMC::App
6
6
 
7
7
  desc "Show app information"
8
8
  group :apps
9
- input :app, :argument => :required, :from_given => by_name("app"),
10
- :desc => "App to show"
9
+ input :app, :desc => "App to show", :argument => :required,
10
+ :from_given => by_name(:app)
11
11
  def app
12
12
  app = input[:app]
13
13
 
@@ -4,15 +4,14 @@ module VMC::App
4
4
  class Apps < Base
5
5
  desc "List your applications"
6
6
  group :apps
7
- input :space, :from_given => by_name("space"),
8
- :default => proc { client.current_space },
9
- :desc => "Show apps in given space"
7
+ input :space, :desc => "Show apps in given space",
8
+ :default => proc { client.current_space },
9
+ :from_given => by_name(:space)
10
10
  input :name, :desc => "Filter by name regexp"
11
11
  input :runtime, :desc => "Filter by runtime regexp"
12
12
  input :framework, :desc => "Filter by framework regexp"
13
13
  input :url, :desc => "Filter by url regexp"
14
- input :full, :type => :boolean, :default => false,
15
- :desc => "Verbose output format"
14
+ input :full, :desc => "Verbose output format", :default => false
16
15
  def apps
17
16
  if space = input[:space]
18
17
  begin
@@ -4,9 +4,8 @@ module VMC::App
4
4
  class Crashes < Base
5
5
  desc "List an app's crashed instances"
6
6
  group :apps, :info, :hidden => true
7
- input :apps, :argument => :splat, :singular => :app,
8
- :desc => "Applications whose crashed instances to list",
9
- :from_given => by_name("app")
7
+ input :apps, :desc => "Applications whose crashed instances to list",
8
+ :argument => :splat, :singular => :app, :from_given => by_name(:app)
10
9
  def crashes
11
10
  apps = input[:apps]
12
11
  fail "No applications given." if apps.empty?
@@ -6,25 +6,14 @@ module VMC::App
6
6
  class Delete < Base
7
7
  desc "Delete an application"
8
8
  group :apps, :manage
9
- input(:apps, :argument => :splat, :singular => :app,
10
- :desc => "Applications to delete",
11
- :from_given => by_name("app")) {
12
- apps = client.apps
13
- fail "No applications." if apps.empty?
14
-
15
- [ask("Delete which application?", :choices => apps.sort_by(&:name),
16
- :display => proc(&:name))]
17
- }
18
- input(:really, :type => :boolean, :forget => true,
19
- :default => proc { force? || interact }) { |name, color|
20
- ask("Really delete #{c(name, color)}?", :default => false)
21
- }
22
- input :routes, :type => :boolean, :default => false,
23
- :desc => "Delete associated routes"
24
- input :orphaned, :aliases => "-o", :type => :boolean,
25
- :desc => "Delete orphaned instances"
26
- input :all, :type => :boolean, :default => false,
27
- :desc => "Delete all applications"
9
+ input :apps, :desc => "Applications to delete", :argument => :splat,
10
+ :singular => :app, :from_given => by_name(:app)
11
+ input :routes, :desc => "Delete associated routes", :default => false
12
+ input :orphaned, :desc => "Delete orphaned services", :aliases => "-o",
13
+ :default => false
14
+ input :all, :desc => "Delete all applications", :default => false
15
+ input :really, :type => :boolean, :forget => true, :hidden => true,
16
+ :default => proc { force? || interact }
28
17
  def delete
29
18
  apps = client.apps
30
19
 
@@ -72,19 +61,33 @@ module VMC::App
72
61
  orphaned.each(&:invalidate!)
73
62
  end
74
63
 
75
- def delete_orphaned_services(instances, orphaned)
76
- return if instances.empty?
64
+ def delete_orphaned_services(service, orphaned)
65
+ return if service.empty?
77
66
 
78
67
  line unless quiet? || force?
79
68
 
80
- instances.select { |i|
69
+ service.select { |i|
81
70
  orphaned ||
82
- ask("Delete orphaned service instance #{c(i.name, :name)}?",
71
+ ask("Delete orphaned service #{c(i.name, :name)}?",
83
72
  :default => false)
84
- }.each do |instance|
73
+ }.each do |service|
85
74
  # TODO: splat
86
- invoke :delete_service, :instance => instance, :really => true
75
+ invoke :delete_service, :service => service, :really => true
87
76
  end
88
77
  end
78
+
79
+ private
80
+
81
+ def ask_app
82
+ apps = client.apps
83
+ fail "No applications." if apps.empty?
84
+
85
+ [ask("Delete which application?", :choices => apps.sort_by(&:name),
86
+ :display => proc(&:name))]
87
+ end
88
+
89
+ def ask_really(name, color)
90
+ ask("Really delete #{c(name, color)}?", :default => false)
91
+ end
89
92
  end
90
93
  end
@@ -6,9 +6,8 @@ module VMC::App
6
6
 
7
7
  desc "Show all environment variables set for an app"
8
8
  group :apps, :info, :hidden => true
9
- input :app, :argument => true,
10
- :desc => "Application to inspect the environment of",
11
- :from_given => by_name("app")
9
+ input :app, :desc => "Application to inspect the environment of",
10
+ :argument => true, :from_given => by_name(:app)
12
11
  def env
13
12
  app = input[:app]
14
13
 
@@ -26,15 +25,11 @@ module VMC::App
26
25
 
27
26
  desc "Set an environment variable"
28
27
  group :apps, :info, :hidden => true
29
- input :app, :argument => true,
30
- :desc => "Application to set the variable for",
31
- :from_given => by_name("app")
32
- input :name, :argument => true,
33
- :desc => "Environment variable name"
34
- input :value, :argument => :optional,
35
- :desc => "Environment variable value"
36
- input :restart, :type => :boolean, :default => true,
37
- :desc => "Restart app after updating?"
28
+ input :app, :desc => "Application to set the variable for",
29
+ :argument => true, :from_given => by_name(:app)
30
+ input :name, :desc => "Variable name", :argument => true
31
+ input :value, :desc => "Variable value", :argument => :optional
32
+ input :restart, :desc => "Restart app after updating?", :default => true
38
33
  def set_env
39
34
  app = input[:app]
40
35
  name = input[:name]
@@ -62,13 +57,10 @@ module VMC::App
62
57
 
63
58
  desc "Remove an environment variable"
64
59
  group :apps, :info, :hidden => true
65
- input :app, :argument => true,
66
- :desc => "Application to set the variable for",
67
- :from_given => by_name("app")
68
- input :name, :argument => true,
69
- :desc => "Environment variable name"
70
- input :restart, :type => :boolean, :default => true,
71
- :desc => "Restart app after updating?"
60
+ input :app, :desc => "Application to set the variable for",
61
+ :argument => true, :from_given => by_name(:app)
62
+ input :name, :desc => "Variable name", :argument => true
63
+ input :restart, :desc => "Restart app after updating?", :default => true
72
64
  def unset_env
73
65
  app = input[:app]
74
66
  name = input[:name]
@@ -5,11 +5,10 @@ module VMC::App
5
5
  class Files < Base
6
6
  desc "Print out an app's file contents"
7
7
  group :apps, :info, :hidden => true
8
- input :app, :argument => true,
9
- :desc => "Application to inspect the files of",
10
- :from_given => by_name("app")
11
- input :path, :argument => true, :default => "/",
12
- :desc => "Path of file to read"
8
+ input :app, :desc => "Application to inspect the files of",
9
+ :argument => true, :from_given => by_name(:app)
10
+ input :path, :desc => "Path of file to read", :argument => :optional,
11
+ :default => "/"
13
12
  def file
14
13
  app = input[:app]
15
14
  path = input[:path]
@@ -36,11 +35,10 @@ module VMC::App
36
35
 
37
36
  desc "Examine an app's files"
38
37
  group :apps, :info, :hidden => true
39
- input :app, :argument => true,
40
- :desc => "Application to inspect the files of",
41
- :from_given => by_name("app")
42
- input :path, :argument => :optional, :default => "/",
43
- :desc => "Path of directory to list"
38
+ input :app, :desc => "Application to inspect the files of",
39
+ :argument => true, :from_given => by_name(:app)
40
+ input :path, :desc => "Path of directory to list", :argument => :optional,
41
+ :default => "/"
44
42
  def files
45
43
  app = input[:app]
46
44
  path = input[:path]
@@ -65,11 +63,9 @@ module VMC::App
65
63
 
66
64
  desc "Stream an app's file contents"
67
65
  group :apps, :info, :hidden => true
68
- input :app, :argument => true,
69
- :desc => "Application to inspect the file of",
70
- :from_given => by_name("app")
71
- input :path, :argument => :optional, :default => nil,
72
- :desc => "Path of file to stream (default: all)"
66
+ input :app, :desc => "Application to inspect the files of",
67
+ :argument => true, :from_given => by_name(:app)
68
+ input :path, :desc => "Path of file to stream", :argument => :optional
73
69
  def tail
74
70
  app = input[:app]
75
71
 
@@ -4,9 +4,8 @@ module VMC::App
4
4
  class Health < Base
5
5
  desc "Get application health"
6
6
  group :apps, :info, :hidden => true
7
- input :apps, :argument => :splat, :singular => :app,
8
- :desc => "Applications to start",
9
- :from_given => by_name("app")
7
+ input :apps, :desc => "Applications to start", :argument => :splat,
8
+ :singular => :app, :from_given => by_name(:app)
10
9
  def health
11
10
  apps = input[:apps]
12
11
  fail "No applications given." if apps.empty?
@@ -4,9 +4,9 @@ module VMC::App
4
4
  class Instances < Base
5
5
  desc "List an app's instances"
6
6
  group :apps, :info, :hidden => true
7
- input :apps, :argument => :splat, :singular => :app,
8
- :desc => "Applications whose instances to list",
9
- :from_given => by_name("app")
7
+ input :apps, :desc => "Applications whose instances to list",
8
+ :argument => :splat, :singular => :app,
9
+ :from_given => by_name(:app)
10
10
  def instances
11
11
  apps = input[:apps]
12
12
  fail "No applications given." if apps.empty?
@@ -4,13 +4,11 @@ module VMC::App
4
4
  class Logs < Base
5
5
  desc "Print out an app's logs"
6
6
  group :apps, :info, :hidden => true
7
- input :app, :argument => true,
8
- :desc => "Application to get the logs of",
9
- :from_given => by_name("app")
10
- input :instance, :default => "0",
11
- :desc => "Instance of application to get the logs of"
12
- input :all, :type => :boolean, :default => false,
13
- :desc => "Get logs for every instance"
7
+ input :app, :desc => "Application to get the logs of", :argument => true,
8
+ :from_given => by_name(:app)
9
+ input :instance, :desc => "Instance of application to get the logs of",
10
+ :default => "0"
11
+ input :all, :desc => "Get logs for every instance", :default => false
14
12
  def logs
15
13
  app = input[:app]
16
14
 
@@ -36,9 +34,8 @@ module VMC::App
36
34
 
37
35
  desc "Print out the logs for an app's crashed instances"
38
36
  group :apps, :info, :hidden => true
39
- input :app, :argument => true,
40
- :desc => "Application to get the logs of",
41
- :from_given => by_name("app")
37
+ input :app, :desc => "Application to get the logs of", :argument => true,
38
+ :from_given => by_name(:app)
42
39
  def crashlogs
43
40
  app = input[:app]
44
41
 
@@ -1,7 +1,7 @@
1
- require "vmc/detect"
2
1
  require "vmc/cli/app/base"
3
2
  require "vmc/cli/app/push/sync"
4
3
  require "vmc/cli/app/push/create"
4
+ require "vmc/cli/app/push/interactions"
5
5
 
6
6
  module VMC::App
7
7
  class Push < Base
@@ -10,67 +10,22 @@ module VMC::App
10
10
 
11
11
  desc "Push an application, syncing changes if it exists"
12
12
  group :apps, :manage
13
- input(:name, :argument => true, :desc => "Application name") {
14
- ask("Name")
15
- }
16
- input :path, :default => ".",
17
- :desc => "Path containing the application"
18
- input(:url, :desc => "URL bound to app") { |name|
19
- choices = url_choices(name)
20
-
21
- options = {
22
- :choices => choices + ["none"],
23
- :allow_other => true
24
- }
25
-
26
- options[:default] = choices.first if choices.size == 1
27
-
28
- url = ask "URL", options
29
-
30
- unless url == "none"
31
- url
32
- end
33
- }
34
- input(:memory, :desc => "Memory limit") { |default|
35
- ask("Memory Limit",
36
- :choices => memory_choices,
37
- :allow_other => true,
38
- :default => default || "64M")
39
- }
40
- input(:instances, :type => :integer,
41
- :desc => "Number of instances to run") {
42
- ask("Instances", :default => 1)
43
- }
44
- input(:framework, :from_given => by_name("framework"),
45
- :desc => "Framework to use") { |choices, default, other|
46
- ask_with_other("Framework", client.frameworks, choices, default, other)
47
- }
48
- input(:runtime, :from_given => by_name("runtime"),
49
- :desc => "Runtime to use") { |choices, default, other|
50
- ask_with_other("Runtime", client.runtimes, choices, default, other)
51
- }
52
- input(:command, :desc => "Startup command for standalone app") {
53
- ask("Startup command")
54
- }
55
- input :plan, :default => "D100",
56
- :desc => "Application plan (e.g. D100, P200)"
57
- input :start, :type => :boolean, :default => true,
58
- :desc => "Start app after pushing?"
59
- input :restart, :type => :boolean, :default => true,
60
- :desc => "Restart app after updating?"
61
- input(:create_services, :type => :boolean,
62
- :default => proc { force? ? false : interact },
63
- :desc => "Interactively create services?") {
64
- line unless quiet?
65
- ask "Create services for application?", :default => false
66
- }
67
- input(:bind_services, :type => :boolean,
68
- :default => proc { force? ? false : interact },
69
- :desc => "Interactively bind services?") {
70
- unless all_instances.empty?
71
- ask "Bind other services to application?", :default => false
72
- end
73
- }
13
+ input :name, :desc => "Application name", :argument => :optional
14
+ input :path, :desc => "Path containing the bits", :default => "."
15
+ input :url, :desc => "URL to bind to app"
16
+ input :memory, :desc => "Memory limit"
17
+ input :instances, :desc => "Number of instances to run"
18
+ input :framework, :desc => "Framework to use", :from_given => by_name(:framework)
19
+ input :runtime, :desc => "Runtime to use", :from_given => by_name(:runtime)
20
+ input :command, :desc => "Startup command for standalone app"
21
+ input :plan, :desc => "Application plan", :default => "D100"
22
+ input :start, :desc => "Start app after pushing?", :default => true
23
+ input :restart, :desc => "Restart app after updating?", :default => true
24
+ input :create_services, :desc => "Interactively create services?",
25
+ :type => :boolean, :default => proc { force? ? false : interact }
26
+ input :bind_services, :desc => "Interactively bind services?",
27
+ :type => :boolean, :default => proc { force? ? false : interact }
28
+ interactions PushInteractions
74
29
  def push
75
30
  name = input[:name]
76
31
  path = File.expand_path(input[:path])
@@ -122,32 +77,5 @@ module VMC::App
122
77
  err "Upload failed. Try again with 'vmc push'."
123
78
  raise
124
79
  end
125
-
126
- def ask_with_other(message, all, choices, default, other)
127
- choices = choices.sort_by(&:name)
128
- choices << other if other
129
-
130
- opts = {
131
- :choices => choices,
132
- :display => proc { |x|
133
- if other && x == other
134
- "other"
135
- else
136
- x.name
137
- end
138
- }
139
- }
140
-
141
- opts[:default] = default if default
142
-
143
- res = ask(message, opts)
144
-
145
- if other && res == other
146
- opts[:choices] = all
147
- res = ask(message, opts)
148
- end
149
-
150
- res
151
- end
152
80
  end
153
81
  end