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

Extract an administrate:manifest generator #362

Merged
merged 1 commit into from
Jan 8, 2016
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@

* [#269] [FEATURE] Add a generator for copying default layout files
* [#328] [FEATURE] Add a generator for copying default sidebar partial
* [#362] [FEATURE] Add a generator for only the dashboard manifest.
Customizing this manifest before running the `administrate:install` generator
will change which dashboards get generated.
* [#295] [FEATURE] Add dashboard detection for ActiveRecord::Enum fields.
* [#364] [FEATURE] Improve dashboard generator by explicitly listing out the
generated `SHOW_PAGE_ATTRIBUTES` array elements.
Expand Down
10 changes: 7 additions & 3 deletions lib/generators/administrate/dashboard/dashboard_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@ class DashboardGenerator < Rails::Generators::NamedBase
source_root File.expand_path("../templates", __FILE__)

def create_dashboard_definition
template "dashboard.rb.erb", "app/dashboards/#{file_name}_dashboard.rb"
template(
"dashboard.rb.erb",
Rails.root.join("app/dashboards/#{file_name}_dashboard.rb"),
)
end

def create_resource_controller
template(
"controller.rb.erb",
destination = Rails.root.join(
"app/controllers/admin/#{file_name.pluralize}_controller.rb",
)

template("controller.rb.erb", destination)
end

private
Expand Down
56 changes: 7 additions & 49 deletions lib/generators/administrate/install/install_generator.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
Rails.application.eager_load!
require "rails/generators/base"

module Administrate
Expand All @@ -13,13 +12,6 @@ def create_dashboard_controller
)
end

def create_dashboard_manifest
template(
"dashboard_manifest.rb.erb",
"app/dashboards/dashboard_manifest.rb"
)
end

def insert_dashboard_routes
unless File.read(rails_routes_file_path).include?(dashboard_routes)
route(dashboard_routes)
Expand All @@ -32,56 +24,22 @@ def run_dashboard_generators
end
end

def warn_about_invalid_models
namespaced_models.each do |invalid_model|
puts "WARNING: Unable to generate a dashboard for #{invalid_model}."
puts " Administrate does not yet support namespaced models."
end

models_without_tables.each do |invalid_model|
puts "WARNING: Unable to generate a dashboard for #{invalid_model}."
puts " It is not connected to a database table."
end

unnamed_constants.each do |invalid_model|
puts "NOTICE: Skipping dynamically generated model #{invalid_model}."
end
end

private

def singular_dashboard_resources
dashboard_resources.map(&:singularize)
dashboard_resources.map(&:to_s).map(&:singularize)
end

def dashboard_resources
valid_dashboard_models.map do |model|
model.to_s.pluralize.underscore
end
manifest::DASHBOARDS
end

def valid_dashboard_models
database_models - invalid_database_models
end

def database_models
ActiveRecord::Base.descendants
end

def invalid_database_models
models_without_tables + namespaced_models + unnamed_constants
end

def models_without_tables
database_models.reject(&:table_exists?)
end

def namespaced_models
database_models.select { |model| model.to_s.include?("::") }
end
def manifest
unless defined?(DashboardManifest)
Rails::Generators.invoke("administrate:manifest")
end

def unnamed_constants
ActiveRecord::Base.descendants.reject { |d| d.name == d.to_s }
DashboardManifest
end

def dashboard_routes
Expand Down
65 changes: 65 additions & 0 deletions lib/generators/administrate/manifest/manifest_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
Rails.application.eager_load!
require "rails/generators/base"

module Administrate
module Generators
class ManifestGenerator < Rails::Generators::Base
source_root File.expand_path("../templates", __FILE__)

def create_dashboard_manifest
template(
"dashboard_manifest.rb.erb",
Rails.root.join("app/dashboards/dashboard_manifest.rb"),
)
end

def warn_about_invalid_models
namespaced_models.each do |invalid_model|
puts "WARNING: Unable to generate a dashboard for #{invalid_model}."
puts " Administrate does not yet support namespaced models."
end

models_without_tables.each do |invalid_model|
puts "WARNING: Unable to generate a dashboard for #{invalid_model}."
puts " It is not connected to a database table."
end

unnamed_constants.each do |invalid_model|
puts "NOTICE: Skipping dynamically generated model #{invalid_model}."
end
end

private

def dashboard_resources
valid_dashboard_models.map do |model|
model.to_s.pluralize.underscore
end
end

def valid_dashboard_models
database_models - invalid_database_models
end

def database_models
ActiveRecord::Base.descendants
end

def invalid_database_models
models_without_tables + namespaced_models + unnamed_constants
end

def models_without_tables
database_models.reject(&:table_exists?)
end

def namespaced_models
database_models.select { |model| model.to_s.include?("::") }
end

def unnamed_constants
ActiveRecord::Base.descendants.reject { |d| d.name == d.to_s }
end
end
end
end
59 changes: 8 additions & 51 deletions spec/generators/install_generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,68 +20,26 @@ class ApplicationController < Administrate::ApplicationController
end
end

describe "dashboard_manifest" do
it "is copied to the dashboards folder" do
stub_generator_dependencies
manifest = file("app/dashboards/dashboard_manifest.rb")

run_generator

expect(manifest).to exist
expect(manifest).to have_correct_syntax
expect(manifest).to contain("class DashboardManifest")
expect(manifest).to contain("DASHBOARDS = [")
expect(manifest).to contain("ROOT_DASHBOARD = DASHBOARDS.first")
end

it "populates default dashboards based on current ActiveRecord models" do
stub_generator_dependencies
manifest = file("app/dashboards/dashboard_manifest.rb")

run_generator

[:customers, :line_items, :orders, :products].each do |model|
expect(manifest).to contain(":#{model}")
end
expect(manifest).not_to contain("Delayed::Backend::ActiveRecord::Job")
end

it "skips namespaced models with a warning" do
stub_generator_dependencies
manifest = file("app/dashboards/dashboard_manifest.rb")

run_generator

expect(manifest).not_to contain("delayed/backend/active_record/jobs")
end

it "skips models that aren't backed by the database" do
describe "manifest generator" do
it "invokes the Manifest generator if the manifest does not yet exist" do
begin
class ModelWithoutDBTable < ActiveRecord::Base; end
remove_constants :DashboardManifest
stub_generator_dependencies
manifest = file("app/dashboards/dashboard_manifest.rb")

run_generator
expect { run_generator }.to raise_error
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error is only raised in the test suite.

When a user runs this generator without DashboardManifest defined, the generator will invoke the manifest generator to fill in the missing piece.

In the test suite, we stub out the invocation of the manifest generator. The generator does not run, and DashboardManifest remains undefined. When the install generator tries to use DashboardManifest as the basis for the installation, it comes up empty and raises an error.


expect(manifest).not_to contain("model_without_db_table")
expect(Rails::Generators).to invoke_generator("administrate:manifest")
ensure
remove_constants :ModelWithoutDBTable
load "spec/example_app/app/dashboards/dashboard_manifest.rb"
end
end

it "skips models that don't have a named constant" do
it "does not invoke the manifest generator if a manifest already exists" do
stub_generator_dependencies
ActiveRecord::Schema.define { create_table(:foos) }
_unnamed_model = Class.new(ActiveRecord::Base) do
def self.table_name
:foos
end
end

run_generator

manifest = file("app/dashboards/dashboard_manifest.rb")
expect(manifest).to have_correct_syntax
expect(Rails::Generators).not_to invoke_generator("administrate:manifest")
end
end

Expand Down Expand Up @@ -140,7 +98,6 @@ def self.table_name
def stub_generator_dependencies
provide_existing_routes_file
allow(Rails::Generators).to receive(:invoke)
allow(Rails).to receive(:root).and_return(Pathname.new(file(".")))
end

def insert_generated_routes
Expand Down
75 changes: 75 additions & 0 deletions spec/generators/manifest_generator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
require "rails_helper"
require "generators/administrate/manifest/manifest_generator"
require "support/generator_spec_helpers"
require "support/constant_helpers"

describe Administrate::Generators::ManifestGenerator, :generator do
describe "dashboard_manifest" do
it "is copied to the dashboards folder" do
stub_generator_dependencies
manifest = file("app/dashboards/dashboard_manifest.rb")

run_generator

expect(manifest).to exist
expect(manifest).to have_correct_syntax
expect(manifest).to contain("class DashboardManifest")
expect(manifest).to contain("DASHBOARDS = [")
expect(manifest).to contain("ROOT_DASHBOARD = DASHBOARDS.first")
end

it "populates default dashboards based on current ActiveRecord models" do
stub_generator_dependencies
manifest = file("app/dashboards/dashboard_manifest.rb")

run_generator

[:customers, :line_items, :orders, :products].each do |model|
expect(manifest).to contain(":#{model}")
end
expect(manifest).not_to contain("Delayed::Backend::ActiveRecord::Job")
end

it "skips namespaced models with a warning" do
stub_generator_dependencies
manifest = file("app/dashboards/dashboard_manifest.rb")

run_generator

expect(manifest).not_to contain("delayed/backend/active_record/jobs")
end

it "skips models that aren't backed by the database" do
begin
class ModelWithoutDBTable < ActiveRecord::Base; end
stub_generator_dependencies
manifest = file("app/dashboards/dashboard_manifest.rb")

run_generator

expect(manifest).not_to contain("model_without_db_table")
ensure
remove_constants :ModelWithoutDBTable
end
end

it "skips models that don't have a named constant" do
stub_generator_dependencies
ActiveRecord::Schema.define { create_table(:foos) }
_unnamed_model = Class.new(ActiveRecord::Base) do
def self.table_name
:foos
end
end

run_generator

manifest = file("app/dashboards/dashboard_manifest.rb")
expect(manifest).to have_correct_syntax
end
end

def stub_generator_dependencies
allow(Rails::Generators).to receive(:invoke)
end
end
4 changes: 4 additions & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ module Features
config.infer_base_class_for_anonymous_controllers = false
config.infer_spec_type_from_file_location!
config.use_transactional_fixtures = false

config.before(:each, type: :generator) do
allow(Rails).to receive(:root).and_return(Pathname.new(file(".")))
end
end

ActiveRecord::Migration.maintain_test_schema!
Expand Down