Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Install Generator to Properly Install Engine in Host Apps #19

Merged
merged 4 commits into from
Oct 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/maintenance_tasks/runs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module MaintenanceTasks
class RunsController < ApplicationController
# Renders the /maintenance_tasks page, displaying available tasks to users.
def index
@available_tasks = Task.descendants
@available_tasks = Task.available_tasks
end

# POST /maintenance_tasks/runs
Expand Down
19 changes: 16 additions & 3 deletions app/jobs/maintenance_tasks/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ class Task < ActiveJob::Base
extend ActiveSupport::DescendantsTracker

class << self
# Controls the value of abstract_class, which indicates whether the class
# is abstract or not. Abstract classes are excluded from the list of
# available_tasks.
#
# @return [Boolean] the value of abstract_class
attr_accessor :abstract_class

# @return [Boolean] whether or not the class is abstract
def abstract_class?
defined?(@abstract_class) && @abstract_class == true
end

# Given the name of a Task, returns the Task subclass. Returns nil if
# there's no task with that name.
def named(name)
Expand All @@ -16,12 +28,13 @@ def named(name)
nil
end

# Returns a list of classes that inherit from the Task superclass.
# Returns a list of concrete classes that inherit from
# the Task superclass.
#
# @return [Array<Class>] the list of classes.
def descendants
def available_tasks
load_constants
super
descendants.reject(&:abstract_class?)
end

private
Expand Down
36 changes: 36 additions & 0 deletions lib/generators/maintenance_tasks/install_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true
module MaintenanceTasks
# Generator used to set up the engine in the host application.
# It handles mounting the engine, installing migrations
# and creating some required files.
class InstallGenerator < Rails::Generators::Base
source_root File.expand_path('templates', __dir__)

# Mounts the engine in the host application's config/routes.rb
def mount_engine
route("mount MaintenanceTasks::Engine => '/maintenance_tasks'")
end

# Copies engine migrations to host application and migrates the database
def install_migrations
rake('maintenance_tasks:install:migrations')
rake('db:migrate')
end

# Creates an initializer file for the engine in the host application
def create_initializer
template(
'maintenance_tasks.rb',
'config/initializers/maintenance_tasks.rb'
)
end

# Creates ApplicationTask class for task classes to subclass
def create_application_task
template(
'application_task.rb',
'app/jobs/maintenance/application_task.rb'
)
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true
module Maintenance
class ApplicationTask < MaintenanceTasks::Task
self.abstract_class = true
end
end
15 changes: 15 additions & 0 deletions lib/generators/maintenance_tasks/templates/maintenance_tasks.rb.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

# Custom configuration for the tasks namespace can be defined here, ie.
# MaintenanceTasks.tasks_module = 'Maintenance'
<% unless Rails.autoloaders.zeitwerk_enabled? -%>
adrianna-chang-shopify marked this conversation as resolved.
Show resolved Hide resolved

# Your application does not use Zeitwerk, so task dependencies must be
# manually required. This block can be removed if zeitwerk mode is enabled.
# For more information on Zeitwerk, see https://guides.rubyonrails.org/autoloading_and_reloading_constants.html
Rails.application.config.to_prepare do
adrianna-chang-shopify marked this conversation as resolved.
Show resolved Hide resolved
Dir["#{Rails.root}/app/jobs/maintenance/*.rb"].each do |file|
require_dependency(file)
end
end
<% end -%>
6 changes: 6 additions & 0 deletions test/dummy/app/jobs/maintenance/application_task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true
module Maintenance
class ApplicationTask < MaintenanceTasks::Task
self.abstract_class = true
end
end
7 changes: 0 additions & 7 deletions test/dummy/config/initializers/maintenance_tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,3 @@

# Custom configuration for the tasks namespace can be defined here, ie.
# MaintenanceTasks.tasks_module = 'Maintenance'

# If autoloader is not Zeitwerk, tasks must be manually required
# Rails.application.config.to_prepare do
# Dir["#{Rails.root}/app/jobs/maintenance/*.rb"].each do |file|
# require_dependency(file)
# end
# end
1 change: 0 additions & 1 deletion test/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,4 @@
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end

end
6 changes: 3 additions & 3 deletions test/jobs/maintenance_tasks/task_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

module MaintenanceTasks
class TaskTest < ActiveJob::TestCase
test '.descendants returns list of tasks that inherit from the Task superclass' do
expected_tasks = [Maintenance::UpdatePostsTask]
assert_equal expected_tasks, MaintenanceTasks::Task.descendants
test '.available_tasks returns list of tasks that inherit from the Task superclass' do
expected = ['Maintenance::UpdatePostsTask']
assert_equal expected, MaintenanceTasks::Task.available_tasks.map(&:name)
end

test '.named returns the task based on its name' do
Expand Down
55 changes: 55 additions & 0 deletions test/lib/generators/maintenance_tasks/install_generator_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true
require 'test_helper'
require 'generators/maintenance_tasks/install_generator'

module MaintenanceTasks
class InstallGeneratorTest < Rails::Generators::TestCase
tests InstallGenerator
SAMPLE_APP_PATH = Engine.root.join('tmp/sample_app')
destination SAMPLE_APP_PATH
setup :prepare_destination

def setup
super
setup_sample_app
end

def teardown
FileUtils.rm_rf(SAMPLE_APP_PATH)
end

test 'generator mounts engine, runs migrations, and creates required files' do
Dir.chdir(SAMPLE_APP_PATH) do
run_generator

assert_file('config/routes.rb') do |contents|
assert_match(
%r{mount MaintenanceTasks::Engine => '/maintenance_tasks'},
contents
)
end

mig = 'db/migrate/create_maintenance_tasks_runs.maintenance_tasks.rb'
assert_migration(mig)
assert_file('db/schema.rb') do |contents|
assert_match(/create_table "maintenance_tasks_runs"/, contents)
end

assert_file('app/jobs/maintenance/application_task.rb')
assert_file('config/initializers/maintenance_tasks.rb')
end
end

private

def setup_sample_app
FileUtils.copy_entry(Rails.root, SAMPLE_APP_PATH)
etiennebarrie marked this conversation as resolved.
Show resolved Hide resolved

Dir.chdir(SAMPLE_APP_PATH) do
FileUtils.rm_r('db')
FileUtils.rm('config/initializers/maintenance_tasks.rb')
FileUtils.rm('app/jobs/maintenance/application_task.rb')
end
end
end
end