Class: Everywhere::Framework
- Inherits:
-
Object
- Object
- Everywhere::Framework
- Defined in:
- lib/everywhere/framework.rb
Overview
Framework adapters keep both the CLI (dev/build) and the packaged runtime (boot) framework-agnostic. Each adapter owns two sides of one framework:
CLI side — dev_command / precompile_* / cleanup_command (build.rb, dev.rb)
runtime side — prepare_runtime_env / boot! (boot.rb, inside the binary)
Rails keeps its own boot path (Rails::Command server, multi-db prepare_all). Sinatra and Hanami are plain Rack apps and share RackFramework's boot: load config.ru, prepare the database, serve it under Puma bound to localhost.
Defined Under Namespace
Classes: Hanami, RackFramework, Rails, Sinatra
Instance Attribute Summary collapse
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Class Method Summary collapse
- .detect(root = Dir.pwd) ⇒ Object
- .gemfile_mentions?(root, gem_name) ⇒ Boolean
- .hanami?(root) ⇒ Boolean
- .rails?(root) ⇒ Boolean
- .sinatra?(root) ⇒ Boolean
Instance Method Summary collapse
-
#boot!(port:) ⇒ Object
Load the app, prepare its database, and start the server bound to 127.0.0.1:port.
-
#boot_stub ⇒ Object
The native_boot.rb entry point
every installwrites. -
#env_exports ⇒ Object
Env each framework needs set before the app loads, beyond NATIVE_PACKAGED.
-
#initialize(root) ⇒ Framework
constructor
A new instance of Framework.
-
#load_rack_app ⇒ Object
Build the Rack app from config.ru.
-
#prepare_runtime_env ⇒ Object
Set framework-specific env before the app loads.
- #render_boot_stub(env, setup_line) ⇒ Object
-
#serve_rack(app, port:) ⇒ Object
Serve a Rack app under Puma on localhost.
Constructor Details
Instance Attribute Details
#root ⇒ Object (readonly)
Returns the value of attribute root.
40 41 42 |
# File 'lib/everywhere/framework.rb', line 40 def root @root end |
Class Method Details
.detect(root = Dir.pwd) ⇒ Object
14 15 16 17 18 19 20 |
# File 'lib/everywhere/framework.rb', line 14 def self.detect(root = Dir.pwd) return Rails.new(root) if rails?(root) return Hanami.new(root) if hanami?(root) return Sinatra.new(root) if sinatra?(root) raise Error, "No supported framework detected in #{root} (looked for Rails, Hanami, Sinatra)" end |
.gemfile_mentions?(root, gem_name) ⇒ Boolean
35 36 37 38 |
# File 'lib/everywhere/framework.rb', line 35 def self.gemfile_mentions?(root, gem_name) gemfile = File.join(root, "Gemfile") File.exist?(gemfile) && File.read(gemfile).match?(/gem ["']#{Regexp.escape(gem_name)}/) end |
.hanami?(root) ⇒ Boolean
27 28 29 |
# File 'lib/everywhere/framework.rb', line 27 def self.hanami?(root) File.exist?(File.join(root, "config", "app.rb")) && gemfile_mentions?(root, "hanami") end |
Instance Method Details
#boot!(port:) ⇒ Object
Load the app, prepare its database, and start the server bound to 127.0.0.1:port. Blocks. Implemented per framework.
53 54 55 |
# File 'lib/everywhere/framework.rb', line 53 def boot!(port:) raise NotImplementedError, "#{name} has no packaged boot path yet" end |
#boot_stub ⇒ Object
The native_boot.rb entry point every install writes. Frameworks differ
in which env they set and how the bundle is loaded before the gem.
69 70 71 |
# File 'lib/everywhere/framework.rb', line 69 def boot_stub render_boot_stub(env_exports, "require \"bundler/setup\"") end |
#env_exports ⇒ Object
Env each framework needs set before the app loads, beyond NATIVE_PACKAGED.
74 |
# File 'lib/everywhere/framework.rb', line 74 def env_exports = {} |
#load_rack_app ⇒ Object
Build the Rack app from config.ru. Rack 3 returns the app; Rack 2 returned [app, options].
59 60 61 62 63 |
# File 'lib/everywhere/framework.rb', line 59 def load_rack_app require "rack" built = ::Rack::Builder.parse_file(File.join(root, "config.ru")) built.is_a?(Array) ? built.first : built end |
#prepare_runtime_env ⇒ Object
Set framework-specific env before the app loads. Called by Boot.
49 |
# File 'lib/everywhere/framework.rb', line 49 def prepare_runtime_env; end |
#render_boot_stub(env, setup_line) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/everywhere/framework.rb', line 76 def render_boot_stub(env, setup_line) exports = ({ "NATIVE_PACKAGED" => "1" }.merge(env)) .map { |k, v| "ENV[#{k.inspect}] ||= #{v.inspect}" }.join("\n") <<~RUBY #!/usr/bin/env ruby # frozen_string_literal: true # RubyEverywhere packaged-app entry point (generated by `every install`). # Keep this thin: the real boot lives in the ruby_everywhere gem. #{exports} #{setup_line} require "ruby_everywhere" Everywhere.boot!(root: __dir__) RUBY end |
#serve_rack(app, port:) ⇒ Object
Serve a Rack app under Puma on localhost. Keep-alives are disabled: WebKit (the webview) reuses connections Puma has already closed, which shows up as intermittent "network connection was lost" asset failures.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/everywhere/framework.rb', line 97 def serve_rack(app, port:) require "puma" require "puma/configuration" require "puma/launcher" configuration = ::Puma::Configuration.new do |c| c.bind "tcp://127.0.0.1:#{port}" c.app app c.environment ENV.fetch("RACK_ENV", "production") c.workers 0 c.threads 1, 5 c.enable_keep_alives false if c.respond_to?(:enable_keep_alives) end ::Puma::Launcher.new(configuration).run end |