Skip to content

Commit

Permalink
Convert GoodJob into a single mountable engine (instead of a plugin p…
Browse files Browse the repository at this point in the history
…lus optional engine)
  • Loading branch information
bensheldon committed Apr 5, 2022
1 parent af4aa5b commit cf51d76
Show file tree
Hide file tree
Showing 64 changed files with 131 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
release: bin/test_app_rake heroku:release
release: bin/test_app heroku:release
web: bin/test_app server
15 changes: 1 addition & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,19 +323,6 @@ _🚧 GoodJob's dashboard is a work in progress. Please contribute ideas and cod
GoodJob includes a Dashboard as a mountable `Rails::Engine`.
1. Explicitly require the Engine code at the top of your `config/application.rb` file, immediately after Rails is required and before Bundler requires the Rails' groups. This is necessary because the mountable engine is an optional feature of GoodJob.
```ruby
# config/application.rb
require_relative 'boot'
require 'rails/all'
require 'good_job/engine' # <= Add this line
# ...
```
Note: If you find the dashboard fails to reload due to a routing error and uninitialized constant `GoodJob::ExecutionsController`, this is likely because you are not requiring the engine early enough.
1. Mount the engine in your `config/routes.rb` file. The following will mount it at `http://example.com/good_job`.
```ruby
Expand All @@ -344,7 +331,7 @@ GoodJob includes a Dashboard as a mountable `Rails::Engine`.
mount GoodJob::Engine => 'good_job'
```
Because jobs can potentially contain sensitive information, you should authorize access. For example, using Devise's `authenticate` helper, that might look like:
1. Configure authentication. Because jobs can potentially contain sensitive information, you should authorize access. For example, using Devise's `authenticate` helper, that might look like:
```ruby
# config/routes.rb
Expand Down
2 changes: 1 addition & 1 deletion app.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@
}
],
"scripts": {
"postdeploy": "bin/test_app_rake heroku:postdeploy"
"postdeploy": "bin/test_app heroku:postdeploy"
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ActiveJobJob < BaseRecord
DiscardJobError = Class.new(StandardError)

class << self
delegate :table_name, to: Execution
delegate :table_name, to: ::GoodJob::Execution

def table_name=(_value)
raise NotImplementedError, 'Assign GoodJob::Execution.table_name directly'
Expand All @@ -26,7 +26,7 @@ def table_name=(_value)
self.primary_key = 'active_job_id'
self.advisory_lockable_column = 'active_job_id'

has_many :executions, -> { order(created_at: :asc) }, class_name: 'GoodJob::Execution', foreign_key: 'active_job_id', inverse_of: :job
has_many :executions, -> { order(created_at: :asc) }, class_name: 'GoodJob::Execution', foreign_key: 'active_job_id', inverse_of: :job # rubocop:disable Rails/HasManyOrHasOneDependent

# Only the most-recent unretried execution represents a "Job"
default_scope { where(retried_good_job_id: nil) }
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
96 changes: 96 additions & 0 deletions app/views/layouts/good_job/base.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Good Job Dashboard</title>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%# Assets must use *_url route helpers to avoid being overriden by config.asset_host %>
<%= stylesheet_link_tag bootstrap_url(format: :css, v: GoodJob::VERSION), skip_pipeline: true %>
<%= stylesheet_link_tag style_url(format: :css, v: GoodJob::VERSION) %>
<%= javascript_include_tag bootstrap_url(format: :js, v: GoodJob::VERSION), nonce: true %>
<%= javascript_include_tag chartjs_url(format: :js, v: GoodJob::VERSION), nonce: true %>
<%= javascript_include_tag scripts_url(format: :js, v: GoodJob::VERSION), nonce: true %>
<%= javascript_include_tag rails_ujs_url(format: :js, v: GoodJob::VERSION), nonce: true %>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<%= link_to "GoodJob 👍", root_path, class: 'navbar-brand mb-0 h1' %>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>

<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<%= link_to "All Executions", root_path, class: ["nav-link", ("active" if current_page?(root_path))] %>
</li>
<li class="nav-item">
<%= link_to "All Jobs", jobs_path, class: ["nav-link", ("active" if current_page?(jobs_path))] %>
</li>
<li class="nav-item">
<%= link_to "Cron Schedules", cron_entries_path, class: ["nav-link", ("active" if current_page?(cron_entries_path))] %>
</li>
<li class="nav-item">
<%= link_to "Processes", processes_path, class: ["nav-link", ("active" if current_page?(processes_path))] %>
</li>
<li class="nav-item">
<div class="nav-link">
<span class="badge bg-secondary">More views coming soon</span>
</div>
</li>
</ul>
<div>
<input type="checkbox" id="toggle-poll" name="toggle-poll" data-gj-action='change#togglePoll' <%= 'checked' if params[:poll].present? %>>
<label for="toggle-poll">Live Poll</label>
</div>
</div>
</div>
</nav>

<div class="container-fluid">
<div class="card border-warning text-dark my-3">
<div class="card-body">
<p class="card-text">🚧 GoodJob's dashboard is a work in progress. Please contribute ideas and code on <a href="https://github.com/bensheldon/good_job/issues" target="_blank" rel="nofollow noopener noreferrer">Github</a>.</p>
</div>
</div>

<% if notice %>
<div class="alert alert-success alert-dismissible fade show d-flex align-items-center offset-md-3 col-6" role="alert">
<%= render "good_job/shared/icons/check", class: "flex-shrink-0 me-2" %>
<div><%= notice %></div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<% elsif alert %>
<div class="alert alert-warning alert-dismissible fade show d-flex align-items-center offset-md-3 col-6" role="alert">
<%= render "good_job/shared/icons/exclamation", class: "flex-shrink-0 me-2" %>
<div><%= alert %></div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<% end %>
<%= yield %>
</div>

<footer class="footer mt-auto py-3 bg-light fixed-bottom" id="footer" data-gj-poll-replace>
<div class="container-fluid">
<div class="row">
<div class="col-6">
<span class="text-muted">
Last updated: <time id="page-updated-at" datetime="<%= Time.current.utc.iso8601 %>"><%= Time.current %></time>
</span>
</div>

<div class="col-6 text-end">
Remember, you're doing a Good Job too!
</div>
</div>
</div>
</footer>
</body>
</html>
6 changes: 3 additions & 3 deletions bin/lint
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ FileUtils.chdir GEM_ROOT do

puts "\n== ERB Lint =="
if options[:nofix]
system!("bundle exec erblint engine/app/views")
system!("bundle exec erblint app/views")
else
# Must run twice to run all linters
# https://github.com/Shopify/erb-lint/issues/145
puts "Running ERB Lint with autocorrectable linters"
system!("bundle exec erblint --autocorrect engine/app/views")
system!("bundle exec erblint --autocorrect app/views")

puts "\nRunning ERB Lint with all linters"
system!("bundle exec erblint engine/app/views")
system!("bundle exec erblint app/views")
end

puts "\n== Markdown Lint =="
Expand Down
17 changes: 14 additions & 3 deletions bin/test_app
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../spec/test_app/config/application', __dir__)
require_relative '../spec/test_app/config/boot'
require 'rails/commands'
#
# Note: this command cannot be named "rails" because it will break generator specs with the message:
# "Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first."

ENGINE_ROOT = File.expand_path("..", __dir__)
ENGINE_PATH = File.expand_path("../lib/good_job/engine", __dir__)
APP_PATH = File.expand_path("../spec/test_app/config/application", __dir__)

# Set up gems listed in the Gemfile.
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])

require "rails/all"
require "rails/engine/commands"
5 changes: 0 additions & 5 deletions bin/test_app_rake

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 0 additions & 6 deletions engine/lib/good_job/engine.rb

This file was deleted.

3 changes: 2 additions & 1 deletion good_job.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ Gem::Specification.new do |spec|
}

spec.files = Dir[
"engine/**/*",
"app/**/*",
"config/**/*",
"lib/**/*",
"README.md",
"CHANGELOG.md",
Expand Down
File renamed without changes.
6 changes: 2 additions & 4 deletions lib/good_job.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# frozen_string_literal: true
require "rails"
require "active_job"
require "active_job/queue_adapters"

require "zeitwerk"
Zeitwerk::Loader.for_gem.tap do |loader|
Expand All @@ -12,7 +9,8 @@
loader.setup
end

require "good_job/railtie"
require "good_job/version"
require "good_job/engine"

# GoodJob is a multithreaded, Postgres-based, ActiveJob backend for Ruby on Rails.
#
Expand Down
9 changes: 8 additions & 1 deletion lib/good_job/railtie.rb → lib/good_job/engine.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# frozen_string_literal: true

require "rails"
require "active_job"
require "active_job/queue_adapters"

module GoodJob
# Ruby on Rails integration.
class Railtie < ::Rails::Railtie
class Engine < ::Rails::Engine
isolate_namespace GoodJob

config.good_job = ActiveSupport::OrderedOptions.new
config.good_job.cron = {}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'rails_helper'

RSpec.describe GoodJob::Railtie do
RSpec.describe GoodJob::Engine do
it 'copies over the Rails logger by default' do
expect(GoodJob.logger).to eq Rails.logger
end
Expand Down
1 change: 0 additions & 1 deletion spec/test_app/config/application.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
require_relative 'boot'

require 'rails/all'
require "good_job/engine"

Bundler.require(*Rails.groups)
require "good_job"
Expand Down

0 comments on commit cf51d76

Please sign in to comment.