diff options
Diffstat (limited to 'railties/lib/rails/generators')
10 files changed, 284 insertions, 230 deletions
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 25baa470d7..de14186a09 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -1,7 +1,7 @@ require 'digest/md5' require 'securerandom' require 'active_support/core_ext/string/strip' -require 'rails/version' unless defined?(Rails.version) +require 'rails/version' unless defined?(Rails::VERSION) require 'rbconfig' require 'open-uri' require 'uri' @@ -142,7 +142,7 @@ module Rails else <<-GEMFILE.strip_heredoc # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' - gem 'rails', '#{Rails.version}' + gem 'rails', '#{Rails::VERSION::STRING}' GEMFILE end end @@ -179,16 +179,22 @@ module Rails gemfile = if options.dev? || options.edge? <<-GEMFILE.gsub(/^ {12}/, '') - # Gems used for assets + # Use edge version of sprockets-rails gem 'sprockets-rails', github: 'rails/sprockets-rails' + + # Use SCSS for stylesheets gem 'sass-rails', github: 'rails/sass-rails' - gem 'uglifier', '>= 1.0.3' + + # To use Uglifier as compressor for JavaScript assets + gem 'uglifier', '>= 1.3.0' GEMFILE else <<-GEMFILE.gsub(/^ {12}/, '') - # Gems used for assets + # Use SCSS for stylesheets gem 'sass-rails', '~> 4.0.0.beta1' - gem 'uglifier', '>= 1.0.3' + + # To use Uglifier as compressor for JavaScript assets + gem 'uglifier', '>= 1.3.0' GEMFILE end @@ -203,23 +209,28 @@ module Rails end def coffee_gemfile_entry - if options.dev? || options.edge? - "gem 'coffee-rails', github: 'rails/coffee-rails'" + gemfile = if options.dev? || options.edge? + <<-GEMFILE.gsub(/^ {12}/, '') + # Use CoffeeScript for .js.coffee assets and views + gem 'coffee-rails', github: 'rails/coffee-rails' + GEMFILE else - "gem 'coffee-rails', '~> 4.0.0.beta1'" + <<-GEMFILE.gsub(/^ {12}/, '') + # Use CoffeeScript for .js.coffee assets and views + gem 'coffee-rails', '~> 4.0.0.beta1' + GEMFILE end + + gemfile.strip_heredoc.gsub(/^[ \t]*$/, '') end def javascript_gemfile_entry - args = {'jquery' => ", github: 'rails/jquery-rails'"} - unless options[:skip_javascript] <<-GEMFILE.gsub(/^ {12}/, '').strip_heredoc - #{javascript_runtime_gemfile_entry} - # Use CoffeeScript for .js.coffee assets and views #{coffee_gemfile_entry} + #{javascript_runtime_gemfile_entry} - gem '#{options[:javascript]}-rails'#{args[options[:javascript]]} + gem '#{options[:javascript]}-rails' # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks gem 'turbolinks' diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index f6bd107eba..07cf31dd83 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -9,6 +9,11 @@ source 'https://rubygems.org' <%= assets_gemfile_entry %> <%= javascript_gemfile_entry -%> +group :doc do + # bundle exec rake doc:rails generates the API under doc/api. + gem 'sdoc', require: false +end + # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 1.0.1' diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index daf399a538..ceb2bdf371 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -11,8 +11,9 @@ require "action_mailer/railtie" <%= comment_if :skip_test_unit %>require "rails/test_unit/railtie" <% end -%> -# Assets should be precompiled for production (so we don't need the gems loaded then) -Bundler.require(*Rails.groups(assets: %w(development test))) +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(:default, Rails.env) module <%= app_const_base %> class Application < Rails::Application diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt index df07de9922..4a099a4ce2 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt @@ -1,3 +1,3 @@ # Be sure to restart your server when you modify this file. -<%= app_const %>.config.session_store :encrypted_cookie_store, key: <%= "'_#{app_name}_session'" %> +<%= app_const %>.config.session_store :cookie_store, key: <%= "'_#{app_name}_session'" %> diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec b/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec index 6373ca711e..f7c12e67dd 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec +++ b/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.test_files = Dir["test/**/*"] <% end -%> - <%= '# ' if options.dev? || options.edge? -%>s.add_dependency "rails", "~> <%= Rails.version %>" + <%= '# ' if options.dev? || options.edge? -%>s.add_dependency "rails", "~> <%= Rails::VERSION::STRING %>" <% unless options[:skip_active_record] -%> s.add_development_dependency "<%= gem_for_database %>" diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile index de00ab057d..3f2b78f2fd 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile @@ -1,7 +1,7 @@ source "https://rubygems.org" <% if options[:skip_gemspec] -%> -<%= '# ' if options.dev? || options.edge? -%>gem "rails", "~> <%= Rails.version %>" +<%= '# ' if options.dev? || options.edge? -%>gem "rails", "~> <%= Rails::VERSION::STRING %>" <% else -%> # Declare your gem's dependencies in <%= name %>.gemspec. # Bundler will treat runtime dependencies like base dependencies, and diff --git a/railties/lib/rails/generators/test_case.rb b/railties/lib/rails/generators/test_case.rb index 85a8914ccc..58592b4f8e 100644 --- a/railties/lib/rails/generators/test_case.rb +++ b/railties/lib/rails/generators/test_case.rb @@ -1,8 +1,7 @@ -require 'active_support/core_ext/class/attribute' -require 'active_support/core_ext/module/delegation' -require 'active_support/core_ext/hash/reverse_merge' -require 'active_support/core_ext/kernel/reporting' require 'rails/generators' +require 'rails/generators/testing/behaviour' +require 'rails/generators/testing/setup_and_teardown' +require 'rails/generators/testing/assertions' require 'fileutils' module Rails @@ -27,215 +26,11 @@ module Rails # setup :prepare_destination # end class TestCase < ActiveSupport::TestCase + include Rails::Generators::Testing::Behaviour + include Rails::Generators::Testing::SetupAndTeardown + include Rails::Generators::Testing::Assertions include FileUtils - class_attribute :destination_root, :current_path, :generator_class, :default_arguments - - # Generators frequently change the current path using +FileUtils.cd+. - # So we need to store the path at file load and revert back to it after each test. - self.current_path = File.expand_path(Dir.pwd) - self.default_arguments = [] - - def setup # :nodoc: - destination_root_is_set? - ensure_current_path - super - end - - def teardown # :nodoc: - ensure_current_path - super - end - - # Sets which generator should be tested: - # - # tests AppGenerator - def self.tests(klass) - self.generator_class = klass - end - - # Sets default arguments on generator invocation. This can be overwritten when - # invoking it. - # - # arguments %w(app_name --skip-active-record) - def self.arguments(array) - self.default_arguments = array - end - - # Sets the destination of generator files: - # - # destination File.expand_path("../tmp", File.dirname(__FILE__)) - def self.destination(path) - self.destination_root = path - end - - # Asserts a given file exists. You need to supply an absolute path or a path relative - # to the configured destination: - # - # assert_file "config/environment.rb" - # - # You can also give extra arguments. If the argument is a regexp, it will check if the - # regular expression matches the given file content. If it's a string, it compares the - # file with the given string: - # - # assert_file "config/environment.rb", /initialize/ - # - # Finally, when a block is given, it yields the file content: - # - # assert_file "app/controllers/products_controller.rb" do |controller| - # assert_instance_method :index, controller do |index| - # assert_match(/Product\.all/, index) - # end - # end - def assert_file(relative, *contents) - absolute = File.expand_path(relative, destination_root) - assert File.exists?(absolute), "Expected file #{relative.inspect} to exist, but does not" - - read = File.read(absolute) if block_given? || !contents.empty? - yield read if block_given? - - contents.each do |content| - case content - when String - assert_equal content, read - when Regexp - assert_match content, read - end - end - end - alias :assert_directory :assert_file - - # Asserts a given file does not exist. You need to supply an absolute path or a - # path relative to the configured destination: - # - # assert_no_file "config/random.rb" - def assert_no_file(relative) - absolute = File.expand_path(relative, destination_root) - assert !File.exists?(absolute), "Expected file #{relative.inspect} to not exist, but does" - end - alias :assert_no_directory :assert_no_file - - # Asserts a given migration exists. You need to supply an absolute path or a - # path relative to the configured destination: - # - # assert_migration "db/migrate/create_products.rb" - # - # This method manipulates the given path and tries to find any migration which - # matches the migration name. For example, the call above is converted to: - # - # assert_file "db/migrate/003_create_products.rb" - # - # Consequently, assert_migration accepts the same arguments has assert_file. - def assert_migration(relative, *contents, &block) - file_name = migration_file_name(relative) - assert file_name, "Expected migration #{relative} to exist, but was not found" - assert_file file_name, *contents, &block - end - - # Asserts a given migration does not exist. You need to supply an absolute path or a - # path relative to the configured destination: - # - # assert_no_migration "db/migrate/create_products.rb" - def assert_no_migration(relative) - file_name = migration_file_name(relative) - assert_nil file_name, "Expected migration #{relative} to not exist, but found #{file_name}" - end - - # Asserts the given class method exists in the given content. This method does not detect - # class methods inside (class << self), only class methods which starts with "self.". - # When a block is given, it yields the content of the method. - # - # assert_migration "db/migrate/create_products.rb" do |migration| - # assert_class_method :up, migration do |up| - # assert_match(/create_table/, up) - # end - # end - def assert_class_method(method, content, &block) - assert_instance_method "self.#{method}", content, &block - end - - # Asserts the given method exists in the given content. When a block is given, - # it yields the content of the method. - # - # assert_file "app/controllers/products_controller.rb" do |controller| - # assert_instance_method :index, controller do |index| - # assert_match(/Product\.all/, index) - # end - # end - def assert_instance_method(method, content) - assert content =~ /(\s+)def #{method}(\(.+\))?(.*?)\n\1end/m, "Expected to have method #{method}" - yield $3.strip if block_given? - end - alias :assert_method :assert_instance_method - - # Asserts the given attribute type gets translated to a field type - # properly: - # - # assert_field_type :date, :date_select - def assert_field_type(attribute_type, field_type) - assert_equal(field_type, create_generated_attribute(attribute_type).field_type) - end - - # Asserts the given attribute type gets a proper default value: - # - # assert_field_default_value :string, "MyString" - def assert_field_default_value(attribute_type, value) - assert_equal(value, create_generated_attribute(attribute_type).default) - end - - # Runs the generator configured for this class. The first argument is an array like - # command line arguments: - # - # class AppGeneratorTest < Rails::Generators::TestCase - # tests AppGenerator - # destination File.expand_path("../tmp", File.dirname(__FILE__)) - # teardown :cleanup_destination_root - # - # test "database.yml is not created when skipping Active Record" do - # run_generator %w(myapp --skip-active-record) - # assert_no_file "config/database.yml" - # end - # end - # - # You can provide a configuration hash as second argument. This method returns the output - # printed by the generator. - def run_generator(args=self.default_arguments, config={}) - capture(:stdout) { self.generator_class.start(args, config.reverse_merge(destination_root: destination_root)) } - end - - # Instantiate the generator. - def generator(args=self.default_arguments, options={}, config={}) - @generator ||= self.generator_class.new(args, options, config.reverse_merge(destination_root: destination_root)) - end - - # Create a Rails::Generators::GeneratedAttribute by supplying the - # attribute type and, optionally, the attribute name: - # - # create_generated_attribute(:string, 'name') - def create_generated_attribute(attribute_type, name = 'test', index = nil) - Rails::Generators::GeneratedAttribute.parse([name, attribute_type, index].compact.join(':')) - end - - protected - - def destination_root_is_set? # :nodoc: - raise "You need to configure your Rails::Generators::TestCase destination root." unless destination_root - end - - def ensure_current_path # :nodoc: - cd current_path - end - - def prepare_destination # :nodoc: - rm_rf(destination_root) - mkdir_p(destination_root) - end - - def migration_file_name(relative) # :nodoc: - absolute = File.expand_path(relative, destination_root) - dirname, file_name = File.dirname(absolute), File.basename(absolute).sub(/\.rb$/, '') - Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first - end end end end diff --git a/railties/lib/rails/generators/testing/assertions.rb b/railties/lib/rails/generators/testing/assertions.rb new file mode 100644 index 0000000000..6267b2f2ee --- /dev/null +++ b/railties/lib/rails/generators/testing/assertions.rb @@ -0,0 +1,121 @@ +module Rails + module Generators + module Testing + module Assertions + # Asserts a given file exists. You need to supply an absolute path or a path relative + # to the configured destination: + # + # assert_file "config/environment.rb" + # + # You can also give extra arguments. If the argument is a regexp, it will check if the + # regular expression matches the given file content. If it's a string, it compares the + # file with the given string: + # + # assert_file "config/environment.rb", /initialize/ + # + # Finally, when a block is given, it yields the file content: + # + # assert_file "app/controllers/products_controller.rb" do |controller| + # assert_instance_method :index, controller do |index| + # assert_match(/Product\.all/, index) + # end + # end + def assert_file(relative, *contents) + absolute = File.expand_path(relative, destination_root) + assert File.exists?(absolute), "Expected file #{relative.inspect} to exist, but does not" + + read = File.read(absolute) if block_given? || !contents.empty? + yield read if block_given? + + contents.each do |content| + case content + when String + assert_equal content, read + when Regexp + assert_match content, read + end + end + end + alias :assert_directory :assert_file + + # Asserts a given file does not exist. You need to supply an absolute path or a + # path relative to the configured destination: + # + # assert_no_file "config/random.rb" + def assert_no_file(relative) + absolute = File.expand_path(relative, destination_root) + assert !File.exists?(absolute), "Expected file #{relative.inspect} to not exist, but does" + end + alias :assert_no_directory :assert_no_file + + # Asserts a given migration exists. You need to supply an absolute path or a + # path relative to the configured destination: + # + # assert_migration "db/migrate/create_products.rb" + # + # This method manipulates the given path and tries to find any migration which + # matches the migration name. For example, the call above is converted to: + # + # assert_file "db/migrate/003_create_products.rb" + # + # Consequently, assert_migration accepts the same arguments has assert_file. + def assert_migration(relative, *contents, &block) + file_name = migration_file_name(relative) + assert file_name, "Expected migration #{relative} to exist, but was not found" + assert_file file_name, *contents, &block + end + + # Asserts a given migration does not exist. You need to supply an absolute path or a + # path relative to the configured destination: + # + # assert_no_migration "db/migrate/create_products.rb" + def assert_no_migration(relative) + file_name = migration_file_name(relative) + assert_nil file_name, "Expected migration #{relative} to not exist, but found #{file_name}" + end + + # Asserts the given class method exists in the given content. This method does not detect + # class methods inside (class << self), only class methods which starts with "self.". + # When a block is given, it yields the content of the method. + # + # assert_migration "db/migrate/create_products.rb" do |migration| + # assert_class_method :up, migration do |up| + # assert_match(/create_table/, up) + # end + # end + def assert_class_method(method, content, &block) + assert_instance_method "self.#{method}", content, &block + end + + # Asserts the given method exists in the given content. When a block is given, + # it yields the content of the method. + # + # assert_file "app/controllers/products_controller.rb" do |controller| + # assert_instance_method :index, controller do |index| + # assert_match(/Product\.all/, index) + # end + # end + def assert_instance_method(method, content) + assert content =~ /(\s+)def #{method}(\(.+\))?(.*?)\n\1end/m, "Expected to have method #{method}" + yield $3.strip if block_given? + end + alias :assert_method :assert_instance_method + + # Asserts the given attribute type gets translated to a field type + # properly: + # + # assert_field_type :date, :date_select + def assert_field_type(attribute_type, field_type) + assert_equal(field_type, create_generated_attribute(attribute_type).field_type) + end + + # Asserts the given attribute type gets a proper default value: + # + # assert_field_default_value :string, "MyString" + def assert_field_default_value(attribute_type, value) + assert_equal(value, create_generated_attribute(attribute_type).default) + end + end + end + end +end diff --git a/railties/lib/rails/generators/testing/behaviour.rb b/railties/lib/rails/generators/testing/behaviour.rb new file mode 100644 index 0000000000..caad810de8 --- /dev/null +++ b/railties/lib/rails/generators/testing/behaviour.rb @@ -0,0 +1,103 @@ +require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/module/delegation' +require 'active_support/core_ext/hash/reverse_merge' +require 'active_support/core_ext/kernel/reporting' +require 'active_support/concern' +require 'rails/generators' + +module Rails + module Generators + module Testing + module Behaviour + extend ActiveSupport::Concern + + included do + class_attribute :destination_root, :current_path, :generator_class, :default_arguments + + # Generators frequently change the current path using +FileUtils.cd+. + # So we need to store the path at file load and revert back to it after each test. + self.current_path = File.expand_path(Dir.pwd) + self.default_arguments = [] + end + + module ClassMethods + # Sets which generator should be tested: + # + # tests AppGenerator + def tests(klass) + self.generator_class = klass + end + + # Sets default arguments on generator invocation. This can be overwritten when + # invoking it. + # + # arguments %w(app_name --skip-active-record) + def arguments(array) + self.default_arguments = array + end + + # Sets the destination of generator files: + # + # destination File.expand_path("../tmp", File.dirname(__FILE__)) + def destination(path) + self.destination_root = path + end + end + + # Runs the generator configured for this class. The first argument is an array like + # command line arguments: + # + # class AppGeneratorTest < Rails::Generators::TestCase + # tests AppGenerator + # destination File.expand_path("../tmp", File.dirname(__FILE__)) + # teardown :cleanup_destination_root + # + # test "database.yml is not created when skipping Active Record" do + # run_generator %w(myapp --skip-active-record) + # assert_no_file "config/database.yml" + # end + # end + # + # You can provide a configuration hash as second argument. This method returns the output + # printed by the generator. + def run_generator(args=self.default_arguments, config={}) + capture(:stdout) { self.generator_class.start(args, config.reverse_merge(destination_root: destination_root)) } + end + + # Instantiate the generator. + def generator(args=self.default_arguments, options={}, config={}) + @generator ||= self.generator_class.new(args, options, config.reverse_merge(destination_root: destination_root)) + end + + # Create a Rails::Generators::GeneratedAttribute by supplying the + # attribute type and, optionally, the attribute name: + # + # create_generated_attribute(:string, 'name') + def create_generated_attribute(attribute_type, name = 'test', index = nil) + Rails::Generators::GeneratedAttribute.parse([name, attribute_type, index].compact.join(':')) + end + + protected + + def destination_root_is_set? # :nodoc: + raise "You need to configure your Rails::Generators::TestCase destination root." unless destination_root + end + + def ensure_current_path # :nodoc: + cd current_path + end + + def prepare_destination # :nodoc: + rm_rf(destination_root) + mkdir_p(destination_root) + end + + def migration_file_name(relative) # :nodoc: + absolute = File.expand_path(relative, destination_root) + dirname, file_name = File.dirname(absolute), File.basename(absolute).sub(/\.rb$/, '') + Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first + end + end + end + end +end diff --git a/railties/lib/rails/generators/testing/setup_and_teardown.rb b/railties/lib/rails/generators/testing/setup_and_teardown.rb new file mode 100644 index 0000000000..73102a283f --- /dev/null +++ b/railties/lib/rails/generators/testing/setup_and_teardown.rb @@ -0,0 +1,18 @@ +module Rails + module Generators + module Testing + module SetupAndTeardown + def setup # :nodoc: + destination_root_is_set? + ensure_current_path + super + end + + def teardown # :nodoc: + ensure_current_path + super + end + end + end + end +end |