diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 573b1f8f69c0971aeb9b4ecbae403e9e13ca7c87..30449aa67043f508c7786208386ee312eb24d0ae 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,8 @@ +* Add a `--api` option in order to generate plugins that can be added + inside an API application. + + *Robin Dupret* + * Fix `NoMethodError` when generating a scaffold inside a full engine. *Yuji Yaginuma* diff --git a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index 66111004aa48247949394e66b42ca302c09cea94..0e1326ce4fb50074ae9fbd495590846bc76e27a9 100644 --- a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -17,15 +17,22 @@ def rakefile def app if mountable? - directory 'app' - empty_directory_with_keep_file "app/assets/images/#{namespaced_name}" + if api? + directory 'app', exclude_pattern: %r{app/(views|helpers)} + else + directory 'app' + empty_directory_with_keep_file "app/assets/images/#{namespaced_name}" + end elsif full? empty_directory_with_keep_file 'app/models' empty_directory_with_keep_file 'app/controllers' - empty_directory_with_keep_file 'app/views' - empty_directory_with_keep_file 'app/helpers' empty_directory_with_keep_file 'app/mailers' - empty_directory_with_keep_file "app/assets/images/#{namespaced_name}" + + unless api? + empty_directory_with_keep_file "app/assets/images/#{namespaced_name}" + empty_directory_with_keep_file 'app/helpers' + empty_directory_with_keep_file 'app/views' + end end end @@ -82,6 +89,7 @@ def generate_test_dummy(force = false) opts = (options || {}).slice(*PASSTHROUGH_OPTIONS) opts[:force] = force opts[:skip_bundle] = true + opts[:api] = options.api? invoke Rails::Generators::AppGenerator, [ File.expand_path(dummy_path, destination_root) ], opts @@ -176,6 +184,9 @@ class PluginGenerator < AppBase # :nodoc: desc: "If creating plugin in application's directory " + "skip adding entry to Gemfile" + class_option :api, type: :boolean, default: false, + desc: "Generate a smaller stack for API application plugins" + def initialize(*args) @dummy_path = nil super @@ -210,15 +221,15 @@ def create_lib_files end def create_public_stylesheets_files - build(:stylesheets) + build(:stylesheets) unless api? end def create_javascript_files - build(:javascripts) + build(:javascripts) unless api? end def create_images_directory - build(:images) + build(:images) unless api? end def create_bin_files @@ -305,6 +316,10 @@ def with_dummy_app? options[:skip_test].blank? || options[:dummy_path] != 'test/dummy' end + def api? + options[:api] + end + def self.banner "rails plugin new #{self.arguments.map(&:usage).join(' ')} [options]" end diff --git a/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt index 7157e48c42240ed8d0ac7bb475fbd537158ead27..7fe4e5034de9ccdced41aff0fa9557f26f92bbb7 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt @@ -1,5 +1,5 @@ <%= wrap_in_modules <<-rb.strip_heredoc - class ApplicationController < ActionController::Base + class ApplicationController < ActionController::#{api? ? "API" : "Base"} end rb %> diff --git a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb index 17afd5217715f636d11c5187e460a923722552a0..8938770fc47c4c4d1637f0c05c6194dc36d18850 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb @@ -1,6 +1,7 @@ <%= wrap_in_modules <<-rb.strip_heredoc class Engine < ::Rails::Engine #{mountable? ? ' isolate_namespace ' + camelized_modules : ' '} + #{api? ? " config.generators.api_only = true" : ' '} end rb %> diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 73e68863f4dc93cef9c874522d9720102f0dc6bd..6f5a8151734367f36373509f28f9b4d50ca66e51 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -544,6 +544,60 @@ def test_no_details_from_git_when_skip_git end end + def test_skipping_useless_folders_generation_for_api_engines + ['--full', '--mountable'].each do |option| + run_generator [destination_root, option, '--api'] + + assert_no_directory "app/assets" + assert_no_directory "app/helpers" + assert_no_directory "app/views" + + FileUtils.rm_rf destination_root + end + end + + def test_application_controller_parent_for_mountable_api_plugins + run_generator [destination_root, '--mountable', '--api'] + + assert_file "app/controllers/bukkits/application_controller.rb" do |content| + assert_match "ApplicationController < ActionController::API", content + end + end + + def test_dummy_api_application_for_api_plugins + run_generator [destination_root, '--api'] + + assert_file "test/dummy/config/application.rb" do |content| + assert_match "config.api_only = true", content + end + end + + + def test_api_generators_configuration_for_api_engines + run_generator [destination_root, '--full', '--api'] + + assert_file "lib/bukkits/engine.rb" do |content| + assert_match "config.generators.api_only = true", content + end + end + + def test_scaffold_generator_for_mountable_api_plugins + run_generator [destination_root, '--mountable', '--api'] + + capture(:stdout) do + `#{destination_root}/bin/rails g scaffold article` + end + + assert_file "app/models/bukkits/article.rb" + assert_file "app/controllers/bukkits/articles_controller.rb" do |content| + assert_match "only: [:show, :update, :destroy]", content + end + + assert_no_directory "app/assets" + assert_no_directory "app/helpers" + assert_no_directory "app/views" + end + protected def action(*args, &block) silence(:stdout){ generator.send(*args, &block) }