hanami 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/FEATURES.md +13 -0
  4. data/README.md +28 -1
  5. data/hanami.gemspec +20 -17
  6. data/lib/hanami.rb +106 -7
  7. data/lib/hanami/action/routing_helpers.rb +2 -2
  8. data/lib/hanami/app.rb +72 -0
  9. data/lib/hanami/application.rb +144 -183
  10. data/lib/hanami/application_configuration.rb +1541 -0
  11. data/lib/hanami/application_name.rb +2 -2
  12. data/lib/hanami/application_namespace.rb +12 -0
  13. data/lib/hanami/assets/asset.rb +3 -1
  14. data/lib/hanami/assets/static.rb +3 -9
  15. data/lib/hanami/cli.rb +10 -7
  16. data/lib/hanami/cli_sub_commands/assets.rb +1 -9
  17. data/lib/hanami/cli_sub_commands/generate.rb +16 -0
  18. data/lib/hanami/commands/apps.rb +4 -0
  19. data/lib/hanami/commands/assets/precompile.rb +6 -19
  20. data/lib/hanami/commands/command.rb +64 -0
  21. data/lib/hanami/commands/console.rb +37 -26
  22. data/lib/hanami/commands/db/apply.rb +4 -2
  23. data/lib/hanami/commands/db/console.rb +11 -27
  24. data/lib/hanami/commands/db/create.rb +4 -2
  25. data/lib/hanami/commands/db/drop.rb +4 -2
  26. data/lib/hanami/commands/db/migrate.rb +11 -5
  27. data/lib/hanami/commands/db/prepare.rb +4 -2
  28. data/lib/hanami/commands/db/version.rb +4 -2
  29. data/lib/hanami/commands/generate/abstract.rb +5 -7
  30. data/lib/hanami/commands/generate/action.rb +18 -6
  31. data/lib/hanami/commands/generate/app.rb +15 -2
  32. data/lib/hanami/commands/generate/migration.rb +3 -2
  33. data/lib/hanami/commands/generate/model.rb +4 -3
  34. data/lib/hanami/commands/generate/secret_token.rb +31 -0
  35. data/lib/hanami/commands/new/abstract.rb +14 -5
  36. data/lib/hanami/commands/new/container.rb +1 -0
  37. data/lib/hanami/commands/routes.rb +5 -22
  38. data/lib/hanami/commands/server.rb +14 -142
  39. data/lib/hanami/components.rb +107 -0
  40. data/lib/hanami/components/app/assets.rb +55 -0
  41. data/lib/hanami/components/app/controller.rb +69 -0
  42. data/lib/hanami/components/app/logger.rb +30 -0
  43. data/lib/hanami/components/app/routes.rb +51 -0
  44. data/lib/hanami/components/app/view.rb +40 -0
  45. data/lib/hanami/components/component.rb +166 -0
  46. data/lib/hanami/components/components.rb +366 -0
  47. data/lib/hanami/components/routes_inspector.rb +70 -0
  48. data/lib/hanami/config/load_paths.rb +7 -6
  49. data/lib/hanami/config/mapper.rb +1 -1
  50. data/lib/hanami/config/security.rb +0 -8
  51. data/lib/hanami/configuration.rb +27 -1697
  52. data/lib/hanami/env.rb +67 -0
  53. data/lib/hanami/environment.rb +31 -21
  54. data/lib/hanami/environment_application_configurations.rb +30 -0
  55. data/lib/hanami/frameworks.rb +1 -0
  56. data/lib/hanami/generators/app/application.rb.tt +2 -2
  57. data/lib/hanami/generators/application/app/Gemfile.tt +3 -1
  58. data/lib/hanami/generators/application/app/config/application.rb.tt +2 -2
  59. data/lib/hanami/generators/application/app/gitignore_with_sqlite.tt +3 -0
  60. data/lib/hanami/generators/application/app/lib/app_name.rb.tt +4 -25
  61. data/lib/hanami/generators/application/app/spec_helper.rb.minitest.tt +1 -1
  62. data/lib/hanami/generators/application/app/spec_helper.rb.rspec.tt +1 -1
  63. data/lib/hanami/generators/application/container/Gemfile.tt +3 -1
  64. data/lib/hanami/generators/application/container/capybara.rb.rspec.tt +1 -1
  65. data/lib/hanami/generators/application/container/config.ru.tt +1 -1
  66. data/lib/hanami/generators/application/container/config/environment.rb.tt +35 -1
  67. data/lib/hanami/generators/application/container/features_helper.rb.minitest.tt +1 -1
  68. data/lib/hanami/generators/application/container/gitignore_with_sqlite.tt +3 -0
  69. data/lib/hanami/generators/application/container/lib/project.rb.tt +1 -57
  70. data/lib/hanami/generators/application/container/spec_helper.rb.minitest.tt +1 -1
  71. data/lib/hanami/generators/application/container/spec_helper.rb.rspec.tt +2 -3
  72. data/lib/hanami/generators/database_config.rb +8 -11
  73. data/lib/hanami/generators/model/entity.rb.tt +1 -2
  74. data/lib/hanami/generators/model/repository.rb.tt +1 -2
  75. data/lib/hanami/generators/template_engine.rb +8 -3
  76. data/lib/hanami/generators/test_framework.rb +4 -3
  77. data/lib/hanami/middleware.rb +41 -21
  78. data/lib/hanami/rake_helper.rb +6 -8
  79. data/lib/hanami/server.rb +43 -33
  80. data/lib/hanami/static.rb +2 -2
  81. data/lib/hanami/version.rb +35 -1
  82. data/lib/hanami/welcome.rb +4 -5
  83. metadata +68 -42
  84. data/lib/hanami/commands/db/abstract.rb +0 -19
  85. data/lib/hanami/config/configure.rb +0 -17
  86. data/lib/hanami/config/mapping.rb +0 -12
  87. data/lib/hanami/container.rb +0 -71
  88. data/lib/hanami/generators/application/container/gitignore_with_db.tt +0 -4
  89. data/lib/hanami/loader.rb +0 -257
  90. data/lib/hanami/repositories/car_repository.rb +0 -3
  91. data/lib/hanami/repositories/name_repository.rb +0 -3
@@ -1,9 +1,11 @@
1
- require 'hanami/commands/db/abstract'
1
+ require 'hanami/commands/command'
2
2
 
3
3
  module Hanami
4
4
  module Commands
5
5
  class DB
6
- class Create < Abstract
6
+ class Create < Command
7
+ requires 'model.configuration'
8
+
7
9
  def start
8
10
  require 'hanami/model/migrator'
9
11
  Hanami::Model::Migrator.create
@@ -1,9 +1,11 @@
1
- require 'hanami/commands/db/abstract'
1
+ require 'hanami/commands/command'
2
2
 
3
3
  module Hanami
4
4
  module Commands
5
5
  class DB
6
- class Drop < Abstract
6
+ class Drop < Command
7
+ requires 'model.configuration'
8
+
7
9
  def start
8
10
  require 'hanami/model/migrator'
9
11
  Hanami::Model::Migrator.drop
@@ -1,18 +1,24 @@
1
- require 'hanami/commands/db/abstract'
1
+ require 'hanami/commands/command'
2
2
 
3
3
  module Hanami
4
4
  module Commands
5
5
  class DB
6
- class Migrate < Abstract
7
- def initialize(environment, version)
8
- super(environment)
6
+ class Migrate < Command
7
+ requires 'model.sql'
8
+
9
+ def initialize(options, version)
10
+ super(options)
9
11
  @version = version
10
12
  end
11
13
 
12
14
  def start
13
15
  require 'hanami/model/migrator'
14
- Hanami::Model::Migrator.migrate(version: @version)
16
+ Hanami::Model::Migrator.migrate(version: version)
15
17
  end
18
+
19
+ private
20
+
21
+ attr_reader :version
16
22
  end
17
23
  end
18
24
  end
@@ -1,9 +1,11 @@
1
- require 'hanami/commands/db/abstract'
1
+ require 'hanami/commands/command'
2
2
 
3
3
  module Hanami
4
4
  module Commands
5
5
  class DB
6
- class Prepare < Abstract
6
+ class Prepare < Command
7
+ requires 'model.sql'
8
+
7
9
  def start
8
10
  require 'hanami/model/migrator'
9
11
  Hanami::Model::Migrator.prepare
@@ -1,9 +1,11 @@
1
- require 'hanami/commands/db/abstract'
1
+ require 'hanami/commands/command'
2
2
 
3
3
  module Hanami
4
4
  module Commands
5
5
  class DB
6
- class Version < Abstract
6
+ class Version < Command
7
+ requires 'model.configuration'
8
+
7
9
  def start
8
10
  require 'hanami/model/migrator'
9
11
  puts Hanami::Model::Migrator.version
@@ -1,4 +1,5 @@
1
1
  require 'hanami/environment'
2
+ require 'hanami/commands/command'
2
3
  require 'hanami/generators/generatable'
3
4
  require 'hanami/generators/test_framework'
4
5
  require 'hanami/generators/template_engine'
@@ -8,17 +9,19 @@ require 'hanami/utils/string'
8
9
  module Hanami
9
10
  module Commands
10
11
  class Generate
11
- class Abstract
12
+ class Abstract < Commands::Command
12
13
 
13
14
  include Hanami::Generators::Generatable
14
15
 
15
16
  attr_reader :options, :target_path
16
17
 
17
18
  def initialize(options)
19
+ super
20
+
18
21
  @options = Hanami::Utils::Hash.new(options).symbolize!
19
22
  assert_options!
20
23
 
21
- @target_path = Pathname.pwd
24
+ @target_path = Hanami.root
22
25
  end
23
26
 
24
27
  def template_source_path
@@ -40,11 +43,6 @@ module Hanami
40
43
  @hanamirc ||= Hanamirc.new(target_path)
41
44
  end
42
45
 
43
- def environment
44
- @environment ||= Hanami::Environment.new(options)
45
- end
46
-
47
-
48
46
  def template_engine
49
47
  @template_engine ||= Hanami::Generators::TemplateEngine.new(hanamirc, options[:template])
50
48
  end
@@ -1,5 +1,6 @@
1
1
  require 'hanami/commands/generate/abstract'
2
2
  require 'hanami/routing/route'
3
+ require 'hanami/utils/blank'
3
4
 
4
5
  module Hanami
5
6
  module Commands
@@ -81,6 +82,7 @@ module Hanami
81
82
  assert_application_name!
82
83
  assert_controller_class_name!
83
84
  assert_action_name!
85
+ assert_url!
84
86
  assert_http_method!
85
87
  end
86
88
 
@@ -167,8 +169,8 @@ module Hanami
167
169
  # @since 0.5.0
168
170
  # @api private
169
171
  def known_application_names
170
- Dir.glob(applications_path.join('/*')).map do |name|
171
- File.basename(name)
172
+ applications_path.children.map do |app|
173
+ ::File.basename(app)
172
174
  end
173
175
  end
174
176
 
@@ -193,8 +195,18 @@ module Hanami
193
195
  def assert_application_name!
194
196
  return unless environment.container?
195
197
  if argument_blank?(@application_name) || !application_path.exist?
196
- existing_apps = known_application_names.join('/')
197
- raise ArgumentError.new("Unknown app: `#{ @application_name.downcase }'. Please specify one of (#{ existing_apps }) as application name")
198
+ existing_apps = known_application_names.map { |name| "`#{name}'" }.join(' ')
199
+ warn "`#{@application_name.downcase}' is not a valid APPLICATION_NAME. Please specify one of: #{existing_apps}"
200
+ exit(1)
201
+ end
202
+ end
203
+
204
+ # @since 0.9.0
205
+ # @api private
206
+ def assert_url!
207
+ if options.key?(:url) && Hanami::Utils::Blank.blank?(options[:url])
208
+ warn "`#{options[:url]}' is not a valid URL"
209
+ exit(1)
198
210
  end
199
211
  end
200
212
 
@@ -202,8 +214,8 @@ module Hanami
202
214
  # @api private
203
215
  def assert_http_method!
204
216
  if !Hanami::Routing::Route::VALID_HTTP_VERBS.include?(http_method.upcase)
205
- existing_http_methods = Hanami::Routing::Route::VALID_HTTP_VERBS
206
- raise ArgumentError.new("Unknown HTTP method '#{http_method}', please use one of #{ existing_http_methods.join('/') }.")
217
+ warn "`#{http_method.upcase}' is not a valid HTTP method. Please use one of: #{Hanami::Routing::Route::VALID_HTTP_VERBS.map { |verb| "`#{verb}'" }.join(" ")}"
218
+ exit(1)
207
219
  end
208
220
  end
209
221
 
@@ -1,5 +1,6 @@
1
1
  require 'hanami/commands/generate/abstract'
2
2
  require 'hanami/application_name'
3
+ require 'hanami/utils/blank'
3
4
  require 'securerandom'
4
5
 
5
6
  module Hanami
@@ -10,9 +11,14 @@ module Hanami
10
11
  attr_reader :base_path
11
12
 
12
13
  def initialize(options, application_name)
13
- super(options)
14
+ @environment = Hanami::Environment.new(options)
15
+ @options = Hanami::Utils::Hash.new(options).symbolize!
16
+ assert_options!
17
+
18
+ @target_path = Hanami.root
14
19
  assert_application_name!(application_name)
15
20
  assert_architecture!
21
+ assert_application_base_url!
16
22
 
17
23
  @application_name = ApplicationName.new(application_name)
18
24
  @base_path = Pathname.pwd
@@ -65,7 +71,7 @@ module Hanami
65
71
  end
66
72
 
67
73
  def add_mount_app
68
- generator.inject_into_file base_path.join('config/environment.rb'), after: /Hanami::Container.configure do/ do |match|
74
+ generator.inject_into_file base_path.join('config/environment.rb'), after: /Hanami.configure do/ do |match|
69
75
  "\n mount #{ classified_app_name }::Application, at: '#{ application_base_url }'"
70
76
  end
71
77
  end
@@ -114,6 +120,13 @@ module Hanami
114
120
  raise ArgumentError.new('App generator is only available for container architecture.')
115
121
  end
116
122
  end
123
+
124
+ def assert_application_base_url!
125
+ if options.key?(:application_base_url) && Utils::Blank.blank?(options[:application_base_url])
126
+ warn "`' is not a valid URL"
127
+ exit(1)
128
+ end
129
+ end
117
130
  end
118
131
  end
119
132
  end
@@ -1,4 +1,5 @@
1
1
  require 'hanami/commands/generate/abstract'
2
+ require 'hanami/utils/file_list'
2
3
 
3
4
  module Hanami
4
5
  module Commands
@@ -27,7 +28,7 @@ module Hanami
27
28
  @name = name
28
29
  @underscored_name = Utils::String.new(@name).underscore
29
30
 
30
- environment.require_application_environment
31
+ Components.resolve('model.configuration')
31
32
  assert_migration_name!
32
33
  end
33
34
 
@@ -42,7 +43,7 @@ module Hanami
42
43
  end
43
44
 
44
45
  def existing_migration_path
45
- Dir.glob("#{Hanami::Model.configuration.migrations}/[0-9]*_#{underscored_name}.rb").first
46
+ Utils::FileList["#{Hanami::Model.configuration.migrations}/[0-9]*_#{underscored_name}.rb"].first
46
47
  end
47
48
 
48
49
  def new_migration_path
@@ -5,11 +5,12 @@ module Hanami
5
5
  class Generate
6
6
  class Model < Abstract
7
7
 
8
- attr_reader :model_name
8
+ attr_reader :input, :model_name
9
9
 
10
10
  def initialize(options, model_name)
11
11
  super(options)
12
- @model_name = Utils::String.new(model_name).classify
12
+ @input = Utils::String.new(model_name).underscore
13
+ @model_name = Utils::String.new(@input).classify
13
14
 
14
15
  assert_model_name!
15
16
  end
@@ -88,7 +89,7 @@ module Hanami
88
89
  # @since 0.5.0
89
90
  # @api private
90
91
  def model_name_underscored
91
- Utils::String.new(model_name).underscore
92
+ input
92
93
  end
93
94
 
94
95
  # @since 0.8.0
@@ -0,0 +1,31 @@
1
+ require 'hanami/commands/generate/abstract'
2
+ require 'hanami/application_name'
3
+ require 'securerandom'
4
+
5
+ module Hanami
6
+ module Commands
7
+ class Generate
8
+ class SecretToken
9
+
10
+ def initialize(application_name)
11
+ @application_name = application_name
12
+ end
13
+
14
+ def start
15
+ if Hanami::Utils::Blank.blank?(@application_name)
16
+ puts SecureRandom.hex(32)
17
+ else
18
+ puts "Set the following environment variable to provide the secret token:"
19
+ puts %(#{ upcase_app_name }_SESSIONS_SECRET="#{ SecureRandom.hex(32) }")
20
+ end
21
+ end
22
+
23
+ private
24
+ def upcase_app_name
25
+ @application_name.upcase
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,6 +4,7 @@ require 'hanami/generators/database_config'
4
4
  require 'hanami/generators/generatable'
5
5
  require 'hanami/generators/test_framework'
6
6
  require 'hanami/generators/template_engine'
7
+ require 'hanami/utils'
7
8
  require 'hanami/utils/hash'
8
9
 
9
10
  module Hanami
@@ -28,15 +29,15 @@ module Hanami
28
29
  assert_name!
29
30
  assert_architecture!
30
31
 
31
- @hanami_model_version = '~> 0.6'
32
+ @hanami_model_version = '~> 0.7'
32
33
  @database_config = Hanami::Generators::DatabaseConfig.new(options[:database], project_name)
33
34
  @test_framework = Hanami::Generators::TestFramework.new(hanamirc, @options[:test])
34
35
  @template_engine = Hanami::Generators::TemplateEngine.new(hanamirc, @options[:template])
35
36
  end
36
37
 
37
38
  def start
38
- FileUtils.mkdir_p(project_name)
39
- Dir.chdir(project_name) do
39
+ FileUtils.mkdir_p(project_directory)
40
+ Dir.chdir(project_directory) do
40
41
  @target_path = Pathname.pwd
41
42
 
42
43
  super
@@ -62,7 +63,7 @@ module Hanami
62
63
  def add_git_templates
63
64
  return if git_dir_present?
64
65
 
65
- source = database_config.filesystem? ? 'gitignore_with_db.tt' : 'gitignore.tt'
66
+ source = database_config.sqlite? ? 'gitignore_with_sqlite.tt' : 'gitignore.tt'
66
67
  target = '.gitignore'
67
68
  add_mapping(source, target)
68
69
  end
@@ -75,6 +76,10 @@ module Hanami
75
76
  ApplicationName.new(real_project_name)
76
77
  end
77
78
 
79
+ def project_directory
80
+ @name == '.' ? '.' : project_name
81
+ end
82
+
78
83
  def target
79
84
  Pathname.new('.')
80
85
  end
@@ -90,13 +95,17 @@ module Hanami
90
95
  end
91
96
 
92
97
  def hanami_version
93
- "~> #{Hanami::VERSION.scan(/\A\d{1,2}\.\d{1,2}/).first}"
98
+ Hanami::Version.gem_requirement
94
99
  end
95
100
 
96
101
  def hanami_head?
97
102
  options.fetch(:hanami_head, false)
98
103
  end
99
104
 
105
+ def code_reloading?
106
+ !Hanami::Utils.jruby?
107
+ end
108
+
100
109
  def architecture
101
110
  options.fetch(:architecture, DEFAULT_ARCHITECTURE)
102
111
  end
@@ -20,6 +20,7 @@ module Hanami
20
20
  {
21
21
  project_name: project_name,
22
22
  hanami_head: hanami_head?,
23
+ code_reloading: code_reloading?,
23
24
  test: test_framework.framework,
24
25
  database: database_config.type,
25
26
  database_config: database_config.to_hash,
@@ -1,3 +1,5 @@
1
+ require 'hanami/commands/command'
2
+
1
3
  module Hanami
2
4
  module Commands
3
5
  # Display application/container routes.
@@ -8,33 +10,14 @@ module Hanami
8
10
  #
9
11
  # @since 0.1.0
10
12
  # @api private
11
- class Routes
12
- # @param options [Hash] Environment's options
13
- #
14
- # @since 0.1.0
15
- # @see Hanami::Environment#initialize
16
- def initialize(options)
17
- @environment = Hanami::Environment.new(options)
18
- @environment.require_application_environment
19
- end
13
+ class Routes < Command
14
+ requires 'routes.inspector'
20
15
 
21
16
  # Display to STDOUT application routes
22
17
  #
23
18
  # @since 0.1.0
24
19
  def start
25
- puts app.routes.inspector.to_s
26
- end
27
-
28
- private
29
-
30
- # @since 0.1.0
31
- # @api private
32
- def app
33
- if @environment.container?
34
- Hanami::Container.new
35
- else
36
- Hanami::Application.applications.first.new
37
- end
20
+ puts requirements['routes.inspector'].inspect
38
21
  end
39
22
  end
40
23
  end
@@ -1,156 +1,28 @@
1
- require 'rack'
2
- require 'hanami/server'
1
+ require 'hanami/commands/command'
3
2
 
4
3
  module Hanami
5
4
  module Commands
6
- class Server
7
-
8
- # Message text when Shotgun enabled but interpreter does not support `fork`
9
- #
10
- # @since 0.8.0
11
- # @api private
12
- WARNING_MESSAGE = 'Your platform doesn\'t support code reloading.'.freeze
13
-
14
- ENTR_EXECUTE_COMMAND = "find %{paths} -type f | entr -r bundle exec hanami rackserver %{args}".freeze
15
-
16
- attr_reader :server
5
+ # Server command (`hanami server`)
6
+ #
7
+ # @since 0.1.0
8
+ # @api private
9
+ class Server < Command
10
+ requires 'code_reloading'
17
11
 
18
12
  def initialize(options)
19
- @options = options
20
- detect_strategy!
21
- prepare_server!
22
- end
23
-
24
- def start
25
- preload_applications!
26
-
27
- case @strategy
28
- when :entr
29
- exec ENTR_EXECUTE_COMMAND % {paths: project_paths, args: server_options}
30
- when :shotgun
31
- Shotgun.enable_copy_on_write
32
- Shotgun.preload
33
- @server.start
34
- when :rackup
35
- @server.start
36
- end
37
- end
38
-
39
- private
40
-
41
- def server_options
42
- _options = @options.dup
43
- _options.delete(:code_reloading)
44
- _options.inject([]) {|res, (k, v)| res << "--#{k}=#{v}" ; res}.join(" ")
45
- end
46
-
47
- def project_paths
48
- applications = Hanami::Environment.new.container? ? 'apps' : 'app'
49
- "#{ applications } config db lib"
50
- end
51
-
52
- def prepare_server!
53
- case @strategy
54
- when :rackup
55
- @server = Hanami::Server.new(@options)
56
- when :shotgun
57
- @server = Hanami::Server.new(@options)
58
- @server.app = Shotgun::Loader.new(@server.rackup_config)
59
- end
60
- end
61
-
62
- # Determine server strategy
63
- #
64
- # In order to decide the value, it looks up the following sources:
65
- #
66
- # * CLI option `code_reloading`
67
- #
68
- # If those are missing it falls back to the following defaults:
69
- #
70
- # * :shotgun for development and if Shotgun enabled and `fork supported
71
- # * :entr for development and Shotgun disabled but `entr` installed
72
- # * :rackup for all other cases
73
- #
74
- # @return [:shotgun,:entr, :rackup] the result of the check
75
- #
76
- # @since 0.8.0
77
- #
78
- # @see Hanami::Environment::CODE_RELOADING
79
- def detect_strategy!
80
- @strategy = :rackup
81
- if Hanami::Environment.new(@options).code_reloading?
82
- if shotgun_enabled?
83
- if fork_supported?
84
- @strategy = :shotgun
85
- else
86
- puts WARNING_MESSAGE
87
- end
88
- elsif entr_enabled?
89
- @strategy = :entr
90
- end
91
- end
13
+ super(options)
92
14
 
93
- @strategy
15
+ require 'hanami/server'
16
+ @server = Hanami::Server.new
94
17
  end
95
18
 
96
- def preload_applications!
97
- Hanami::Environment.new(@options).require_application_environment
98
- Hanami::Application.preload!
99
- end
100
-
101
- # Check if entr(1) is installed
102
- #
103
- # @return [Boolean]
104
- #
105
- # @since 0.8.0
106
- # @api private
107
- def entr_enabled?
108
- !!which('entr')
109
- end
110
-
111
-
112
- # Check if Shotgun is enabled
113
- #
114
- # @return [Boolean]
115
- #
116
- # @since 0.8.0
117
- # @api private
118
- def shotgun_enabled?
119
- begin
120
- require 'shotgun'
121
- true
122
- rescue LoadError
123
- false
124
- end
19
+ def start
20
+ server.start
125
21
  end
126
22
 
127
- # Check if ruby interpreter supports `fork`
128
- #
129
- # @return [Boolean]
130
- #
131
- # @since 0.8.0
132
- # @api private
133
- def fork_supported?
134
- Kernel.respond_to?(:fork)
135
- end
23
+ protected
136
24
 
137
- # Cross-platform way of finding an executable in the $PATH.
138
- #
139
- # Usage:
140
- # which('ruby') #=> /usr/bin/ruby
141
- #
142
- # @since 0.8.0
143
- # @api private
144
- def which(cmd)
145
- exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
146
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
147
- exts.each { |ext|
148
- exe = File.join(path, "#{cmd}#{ext}")
149
- return exe if File.executable?(exe) && !File.directory?(exe)
150
- }
151
- end
152
- return nil
153
- end
25
+ attr_reader :server
154
26
  end
155
27
  end
156
28
  end