diff options
Diffstat (limited to 'railties/lib')
41 files changed, 783 insertions, 434 deletions
diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb index 6c9c53fc69..19c2226619 100644 --- a/railties/lib/rails/all.rb +++ b/railties/lib/rails/all.rb @@ -1,5 +1,9 @@ require "rails" +if defined?(Rake) && Rake.application.top_level_tasks.grep(/^test(?::|$)/).any? + ENV['RAILS_ENV'] ||= 'test' +end + %w( active_record action_controller diff --git a/railties/lib/rails/api/task.rb b/railties/lib/rails/api/task.rb new file mode 100644 index 0000000000..c829873da4 --- /dev/null +++ b/railties/lib/rails/api/task.rb @@ -0,0 +1,158 @@ +require 'rdoc/task' + +module Rails + module API + class Task < RDoc::Task + RDOC_FILES = { + 'activesupport' => { + :include => %w( + README.rdoc + CHANGELOG.md + lib/active_support/**/*.rb + ), + :exclude => 'lib/active_support/vendor/*' + }, + + 'activerecord' => { + :include => %w( + README.rdoc + CHANGELOG.md + lib/active_record/**/*.rb + ), + :exclude => 'lib/active_record/vendor/*' + }, + + 'activemodel' => { + :include => %w( + README.rdoc + CHANGELOG.md + lib/active_model/**/*.rb + ) + }, + + 'actionpack' => { + :include => %w( + README.rdoc + CHANGELOG.md + lib/abstract_controller/**/*.rb + lib/action_controller/**/*.rb + lib/action_dispatch/**/*.rb + lib/action_view/**/*.rb + ), + :exclude => 'lib/action_controller/vendor/*' + }, + + 'actionmailer' => { + :include => %w( + README.rdoc + CHANGELOG.md + lib/action_mailer/**/*.rb + ), + :exclude => 'lib/action_mailer/vendor/*' + }, + + 'railties' => { + :include => %w( + README.rdoc + CHANGELOG.md + MIT-LICENSE + lib/**/*.rb + ), + :exclude => 'lib/rails/generators/rails/**/templates/**/*.rb' + } + } + + def initialize(name) + super + + # Every time rake runs this task is instantiated as all the rest. + # Be lazy computing stuff to have as light impact as possible to + # the rest of tasks. + before_running_rdoc do + load_and_configure_sdoc + configure_rdoc_files + setup_horo_variables + end + end + + # Hack, ignore the desc calls performed by the original initializer. + def desc(description) + # no-op + end + + def load_and_configure_sdoc + require 'sdoc' + + self.title = 'Ruby on Rails API' + self.rdoc_dir = api_dir + + options << '-m' << api_main + options << '-e' << 'UTF-8' + + options << '-f' << 'sdoc' + options << '-T' << 'rails' + rescue LoadError + $stderr.puts %(Unable to load SDoc, please add\n\n gem 'sdoc', require: false\n\nto the Gemfile.) + exit 1 + end + + def configure_rdoc_files + rdoc_files.include(api_main) + + RDOC_FILES.each do |component, cfg| + cdr = component_root_dir(component) + + Array(cfg[:include]).each do |pattern| + rdoc_files.include("#{cdr}/#{pattern}") + end + + Array(cfg[:exclude]).each do |pattern| + rdoc_files.exclude("#{cdr}/#{pattern}") + end + end + end + + def setup_horo_variables + ENV['HORO_PROJECT_NAME'] = 'Ruby on Rails' + ENV['HORO_PROJECT_VERSION'] = rails_version + end + + def api_main + component_root_dir('railties') + '/RDOC_MAIN.rdoc' + end + end + + class RepoTask < Task + def load_and_configure_sdoc + super + options << '-g' # link to GitHub, SDoc flag + end + + def component_root_dir(component) + component + end + + def api_dir + 'doc/rdoc' + end + + def rails_version + "master@#{`git rev-parse HEAD`[0, 7]}" + end + end + + class AppTask < Task + def component_root_dir(gem_name) + $:.grep(%r{#{gem_name}[\w.-]*/lib\z}).first[0..-5] + end + + def api_dir + 'doc/api' + end + + def rails_version + Rails::VERSION::STRING + end + end + end +end diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 25cc36ff5d..2d5aa9d952 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,5 +1,5 @@ require 'fileutils' -# FIXME remove DummyKeyGenerator and this require in 4.1 +require 'active_support/core_ext/object/blank' require 'active_support/key_generator' require 'rails/engine' @@ -46,10 +46,10 @@ module Rails # 6) Run config.before_initialize callbacks # 7) Run Railtie#initializer defined by railties, engines and application. # One by one, each engine sets up its load paths, routes and runs its config/initializers/* files. - # 9) Custom Railtie#initializers added by railties, engines and applications are executed - # 10) Build the middleware stack and run to_prepare callbacks - # 11) Run config.before_eager_load and eager_load! if eager_load is true - # 12) Run config.after_initialize callbacks + # 8) Custom Railtie#initializers added by railties, engines and applications are executed + # 9) Build the middleware stack and run to_prepare callbacks + # 10) Run config.before_eager_load and eager_load! if eager_load is true + # 11) Run config.after_initialize callbacks # class Application < Engine autoload :Bootstrap, 'rails/application/bootstrap' @@ -79,7 +79,7 @@ module Rails @initialized = false @reloaders = [] @routes_reloader = nil - @env_config = nil + @app_env_config = nil @ordered_railties = nil @railties = nil end @@ -111,7 +111,7 @@ module Rails key_generator = ActiveSupport::KeyGenerator.new(config.secret_key_base, iterations: 1000) ActiveSupport::CachingKeyGenerator.new(key_generator) else - ActiveSupport::DummyKeyGenerator.new(config.secret_token) + ActiveSupport::LegacyKeyGenerator.new(config.secret_token) end end end @@ -122,7 +122,8 @@ module Rails # # * "action_dispatch.parameter_filter" => config.filter_parameters # * "action_dispatch.redirect_filter" => config.filter_redirect - # * "action_dispatch.secret_token" => config.secret_token, + # * "action_dispatch.secret_token" => config.secret_token + # * "action_dispatch.secret_key_base" => config.secret_key_base # * "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions # * "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local # * "action_dispatch.logger" => Rails.logger @@ -134,14 +135,13 @@ module Rails # * "action_dispatch.encrypted_signed_cookie_salt" => config.action_dispatch.encrypted_signed_cookie_salt # def env_config - @env_config ||= begin - if config.secret_key_base.nil? - ActiveSupport::Deprecation.warn "You didn't set config.secret_key_base in config/initializers/secret_token.rb file. " + - "This should be used instead of the old deprecated config.secret_token in order to use the new EncryptedCookieStore. " + - "To convert safely to the encrypted store (without losing existing cookies and sessions), see http://guides.rubyonrails.org/upgrading_ruby_on_rails.html#action-pack" + @app_env_config ||= begin + if config.secret_key_base.blank? + ActiveSupport::Deprecation.warn "You didn't set config.secret_key_base. " + + "Read the upgrade documentation to learn more about this new config option." if config.secret_token.blank? - raise "You must set config.secret_key_base in your app's config" + raise "You must set config.secret_key_base in your app's config." end end @@ -149,6 +149,7 @@ module Rails "action_dispatch.parameter_filter" => config.filter_parameters, "action_dispatch.redirect_filter" => config.filter_redirect, "action_dispatch.secret_token" => config.secret_token, + "action_dispatch.secret_key_base" => config.secret_key_base, "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions, "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local, "action_dispatch.logger" => Rails.logger, diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index aacde52cfc..41d3722c18 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -5,6 +5,7 @@ aliases = { "d" => "destroy", "c" => "console", "s" => "server", + "t" => "test", "db" => "dbconsole", "r" => "runner" } @@ -16,6 +17,7 @@ The most common rails commands are: generate Generate new code (short-cut alias: "g") console Start the Rails console (short-cut alias: "c") server Start the Rails server (short-cut alias: "s") + test Running the test file (short-cut alias: "t") dbconsole Start a console for the database specified in config/database.yml (short-cut alias: "db") new Create a new Rails application. "rails new my_app" creates a @@ -78,6 +80,15 @@ when 'server' server.start end +when 'test' + $LOAD_PATH.unshift("./test") + require 'rails/commands/test_runner' + options = Rails::TestRunner.parse_arguments(ARGV) + ENV['RAILS_ENV'] ||= options[:environment] || 'test' + + require APP_PATH + Rails::TestRunner.start(ARGV, options) + when 'dbconsole' require 'rails/commands/dbconsole' Rails::DBConsole.start diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index 86ab1aabbf..96229bb4f6 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -46,7 +46,10 @@ module Rails def initialize(app, options={}) @app = app @options = options + + app.sandbox = sandbox? app.load_console + @console = app.config.console || IRB end @@ -71,7 +74,6 @@ module Rails end def start - app.sandbox = sandbox? require_debugger if debugger? set_environment! if environment? diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index cdb29a8156..e3119ecf22 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -42,8 +42,12 @@ module Rails set_environment end + # TODO: this is no longer required but we keep it for the moment to support older config.ru files. def app - @app ||= super.respond_to?(:to_app) ? super.to_app : super + @app ||= begin + app = super + app.respond_to?(:to_app) ? app.to_app : app + end end def opt_parser @@ -58,7 +62,7 @@ module Rails url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}" puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}" - puts "=> Call with -d to detach" unless options[:daemonize] + puts "=> Run `rails server -h` for more startup options" trap(:INT) { exit } puts "=> Ctrl-C to shutdown server" unless options[:daemonize] diff --git a/railties/lib/rails/commands/test_runner.rb b/railties/lib/rails/commands/test_runner.rb new file mode 100644 index 0000000000..d8857bd183 --- /dev/null +++ b/railties/lib/rails/commands/test_runner.rb @@ -0,0 +1,146 @@ +require 'optparse' +require 'minitest/unit' + +module Rails + # Handles all logic behind +rails test+ command. + class TestRunner + class << self + # Creates a new +TestRunner+ object with an array of test files to run + # based on the arguments. When no arguments are provided, it runs all test + # files. When a suite argument is provided, it runs only the test files in + # that suite. Otherwise, it runs the specified test file(s). + def start(files, options = {}) + original_fixtures_options = options.delete(:fixtures) + options[:fixtures] = true + + case files.first + when nil + new(Dir['test/**/*_test.rb'], options).run + when 'models' + new(Dir['test/models/**/*_test.rb'], options).run + when 'helpers' + new(Dir['test/helpers/**/*_test.rb'], options).run + when 'units' + new(Dir['test/{models,helpers,unit}/**/*_test.rb'], options).run + when 'controllers' + new(Dir['test/controllers/**/*_test.rb'], options).run + when 'mailers' + new(Dir['test/mailers/**/*_test.rb'], options).run + when 'functionals' + new(Dir['test/{controllers,mailers,functional}/**/*_test.rb'], options).run + when 'integration' + new(Dir['test/integration/**/*_test.rb'], options).run + else + options[:fixtures] = original_fixtures_options + new(files, options).run + end + end + + # Parses arguments and sets them as option flags + def parse_arguments(arguments) + options = {} + orig_arguments = arguments.dup + + OptionParser.new do |opts| + opts.banner = "Usage: rails test [path to test file(s) or test suite]" + + opts.separator "" + opts.separator "Run a specific test file(s) or a test suite, under Rails'" + opts.separator "environment. If the file name(s) or suit name is omitted," + opts.separator "Rails will run all tests." + opts.separator "" + opts.separator "Specific options:" + + opts.on '-h', '--help', 'Display this help.' do + puts opts + exit + end + + opts.on '-e', '--environment NAME', String, 'Specifies the environment to run this test under' do |e| + options[:environment] = e + end + + opts.on '-f', '--fixtures', 'Load fixtures in test/fixtures/ before running the tests' do + options[:fixtures] = true + end + + opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m| + options[:seed] = m.to_i + end + + opts.on '-v', '--verbose', "Verbose. Show progress processing files." do + options[:verbose] = true + end + + opts.on '-n', '--name PATTERN', "Filter test names on pattern (e.g. /foo/)" do |n| + options[:filter] = n + end + + opts.separator "" + opts.separator "Support types of test suites:" + opts.separator "-------------------------------------------------------------" + opts.separator "* models (test/models/**/*)" + opts.separator "* helpers (test/helpers/**/*)" + opts.separator "* units (test/{models,helpers,unit}/**/*" + opts.separator "* controllers (test/controllers/**/*)" + opts.separator "* mailers (test/mailers/**/*)" + opts.separator "* functionals (test/{controllers,mailers,functional}/**/*)" + opts.separator "* integration (test/integration/**/*)" + opts.separator "-------------------------------------------------------------" + + opts.parse! arguments + orig_arguments -= arguments + end + options + end + end + + # Creates a new +TestRunner+ object with a list of test file paths. + def initialize(files, options) + @files = files + + Rails.application.load_tasks + Rake::Task['db:test:load'].invoke + + if options.delete(:fixtures) + if defined?(ActiveRecord::Base) + ActiveSupport::TestCase.send :include, ActiveRecord::TestFixtures + ActiveSupport::TestCase.fixture_path = "#{Rails.root}/test/fixtures/" + ActiveSupport::TestCase.fixtures :all + end + end + + MiniTest::Unit.runner.options = options + MiniTest::Unit.output = SilentUntilSyncStream.new(MiniTest::Unit.output) + end + + # Runs test files by evaluating each of them. + def run + @files.each { |filename| load(filename) } + end + + # A null stream object which ignores everything until +sync+ has been set + # to true. This is only used to silence unnecessary output from MiniTest, + # as MiniTest calls +output.sync = true+ right before it outputs the first + # test result. + class SilentUntilSyncStream < File + # Creates a +SilentUntilSyncStream+ object by giving it a target stream + # object that will be assigned to +MiniTest::Unit.output+ after +sync+ is + # set to true. + def initialize(target_stream) + @target_stream = target_stream + super(File::NULL, 'w') + end + + # Swaps +MiniTest::Unit.output+ to another stream when +sync+ is true. + def sync=(sync) + if sync + @target_stream.sync = true + MiniTest::Unit.output = @target_stream + end + + super + end + end + end +end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 579af8c6a5..93504b3b35 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -107,7 +107,7 @@ module Rails # # The <tt>Application</tt> class adds a couple more paths to this set. And as in your # <tt>Application</tt>, all folders under +app+ are automatically added to the load path. - # If you have an <tt>app/services/tt> folder for example, it will be added by default. + # If you have an <tt>app/services</tt> folder for example, it will be added by default. # # == Endpoint # diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 4e703151ba..de14186a09 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -178,31 +178,46 @@ module Rails return if options[:skip_sprockets] gemfile = if options.dev? || options.edge? - <<-GEMFILE - # Gems used only for assets and not required - # in production environments by default. - group :assets do - gem 'sprockets-rails', github: 'rails/sprockets-rails' - gem 'sass-rails', github: 'rails/sass-rails' - gem 'coffee-rails', github: 'rails/coffee-rails' - - # See https://github.com/sstephenson/execjs#readme for more supported runtimes - #{javascript_runtime_gemfile_entry} - gem 'uglifier', '>= 1.0.3' - end + <<-GEMFILE.gsub(/^ {12}/, '') + # Use edge version of sprockets-rails + gem 'sprockets-rails', github: 'rails/sprockets-rails' + + # Use SCSS for stylesheets + gem 'sass-rails', github: 'rails/sass-rails' + + # To use Uglifier as compressor for JavaScript assets + gem 'uglifier', '>= 1.3.0' + GEMFILE + else + <<-GEMFILE.gsub(/^ {12}/, '') + # Use SCSS for stylesheets + gem 'sass-rails', '~> 4.0.0.beta1' + + # To use Uglifier as compressor for JavaScript assets + gem 'uglifier', '>= 1.3.0' + GEMFILE + end + + if options[:skip_javascript] + gemfile += <<-GEMFILE.gsub(/^ {12}/, '') + #{coffee_gemfile_entry} + #{javascript_runtime_gemfile_entry} + GEMFILE + end + + gemfile.strip_heredoc.gsub(/^[ \t]*$/, '') + end + + def coffee_gemfile_entry + 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 - <<-GEMFILE - # Gems used only for assets and not required - # in production environments by default. - group :assets do - gem 'sass-rails', '~> 4.0.0.beta1' - gem 'coffee-rails', '~> 4.0.0.beta1' - - # See https://github.com/sstephenson/execjs#readme for more supported runtimes - #{javascript_runtime_gemfile_entry} - gem 'uglifier', '>= 1.0.3' - end + <<-GEMFILE.gsub(/^ {12}/, '') + # Use CoffeeScript for .js.coffee assets and views + gem 'coffee-rails', '~> 4.0.0.beta1' GEMFILE end @@ -211,7 +226,10 @@ module Rails def javascript_gemfile_entry unless options[:skip_javascript] - <<-GEMFILE.strip_heredoc + <<-GEMFILE.gsub(/^ {12}/, '').strip_heredoc + #{coffee_gemfile_entry} + #{javascript_runtime_gemfile_entry} + gem '#{options[:javascript]}-rails' # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks @@ -221,11 +239,15 @@ module Rails end def javascript_runtime_gemfile_entry - if defined?(JRUBY_VERSION) - "gem 'therubyrhino'\n" + runtime = if defined?(JRUBY_VERSION) + "gem 'therubyrhino'" else - "# gem 'therubyracer', platforms: :ruby\n" + "# gem 'therubyracer', platforms: :ruby" end + <<-GEMFILE.gsub(/^ {10}/, '') + # See https://github.com/sstephenson/execjs#readme for more supported runtimes + #{runtime} + GEMFILE end def bundle_command(command) diff --git a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb index 32546936e3..85a1b01cc6 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb @@ -13,8 +13,17 @@ <% attributes.each do |attribute| -%> <div class="field"> +<% if attribute.password_digest? -%> + <%%= f.label :password %><br /> + <%%= f.password_field :password %> + </div> + <div> + <%%= f.label :password_confirmation %><br /> + <%%= f.password_field :password_confirmation %> +<% else -%> <%%= f.label :<%= attribute.name %> %><br /> <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %> +<% end -%> </div> <% end -%> <div class="actions"> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb index 90d8db1df5..d2fd99fdcb 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb @@ -3,7 +3,7 @@ <table> <thead> <tr> -<% attributes.each do |attribute| -%> +<% attributes.reject(&:password_digest?).each do |attribute| -%> <th><%= attribute.human_name %></th> <% end -%> <th></th> @@ -15,7 +15,7 @@ <tbody> <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %> <tr> -<% attributes.each do |attribute| -%> +<% attributes.reject(&:password_digest?).each do |attribute| -%> <td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td> <% end -%> <td><%%= link_to 'Show', <%= singular_table_name %> %></td> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb index daae72270f..5e634153be 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb @@ -1,6 +1,6 @@ <p id="notice"><%%= notice %></p> -<% attributes.each do |attribute| -%> +<% attributes.reject(&:password_digest?).each do |attribute| -%> <p> <strong><%= attribute.human_name %>:</strong> <%%= @<%= singular_table_name %>.<%= attribute.name %> %> diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb index 4ae8756ed0..5e2784c4b0 100644 --- a/railties/lib/rails/generators/generated_attribute.rb +++ b/railties/lib/rails/generators/generated_attribute.rb @@ -130,6 +130,10 @@ module Rails @has_uniq_index end + def password_digest? + name == 'password' && type == :digest + end + def inject_options "".tap { |s| @attr_options.each { |k,v| s << ", #{k}: #{v.inspect}" } } end diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index 9965db98de..d891ba1215 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -40,7 +40,7 @@ module Rails def indent(content, multiplier = 2) spaces = " " * multiplier - content = content.each_line.map {|line| line.blank? ? line : "#{spaces}#{line}" }.join + content.each_line.map {|line| line.blank? ? line : "#{spaces}#{line}" }.join end def wrap_with_namespace(content) @@ -163,6 +163,7 @@ module Rails def attributes_names @attributes_names ||= attributes.each_with_object([]) do |a, names| names << a.column_name + names << 'password_confirmation' if a.password_digest? names << "#{a.name}_type" if a.polymorphic? end end diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index b5db3d2187..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' @@ -23,5 +28,5 @@ gem 'jbuilder', '~> 1.0.1' <% unless defined?(JRUBY_VERSION) -%> # To use debugger -# gem 'debugger' +# gem 'debugger', group: [:development, :test] <% end -%> diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/images/.keep b/railties/lib/rails/generators/rails/app/templates/app/assets/images/.keep new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/images/.keep diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/images/rails.png b/railties/lib/rails/generators/rails/app/templates/app/assets/images/rails.png Binary files differdeleted file mode 100644 index d5edc04e65..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/images/rails.png +++ /dev/null diff --git a/railties/lib/rails/generators/rails/app/templates/config.ru b/railties/lib/rails/generators/rails/app/templates/config.ru index fcfbc6b07a..5bc2a619e8 100644 --- a/railties/lib/rails/generators/rails/app/templates/config.ru +++ b/railties/lib/rails/generators/rails/app/templates/config.ru @@ -1,4 +1,4 @@ # This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) -run <%= app_const %> +run Rails.application 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/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index d0e62d09cc..8b64881dbc 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -26,6 +26,8 @@ <%- unless options.skip_sprockets? -%> # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. config.assets.debug = true <%- end -%> end diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index 5669fe6d64..c40eef145f 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -24,10 +24,10 @@ <%- unless options.skip_sprockets? -%> # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier + config.assets.js_compressor = :uglifier # config.assets.css_compressor = :sass - # Whether to fallback to assets pipeline if a precompiled asset is missed. + # Do not fallback to assets pipeline if a precompiled asset is missed. config.assets.compile = false # Generate digests for assets URLs. diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt index e5caab3672..efccf72d3d 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt @@ -1,6 +1,6 @@ # Be sure to restart your server when you modify this file. -# Your secret key for verifying the integrity of signed cookies. +# Your secret key is used for verifying the integrity of signed cookies. # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, 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/app/templates/public/404.html b/railties/lib/rails/generators/rails/app/templates/public/404.html index 0ee82d3722..a0daa0c156 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/404.html +++ b/railties/lib/rails/generators/rails/app/templates/public/404.html @@ -2,16 +2,15 @@ <html> <head> <title>The page you were looking for doesn't exist (404)</title> - <style> - body - { - background-color: #efefef; + <style> + body { + background-color: #EFEFEF; color: #2E2F30; text-align: center; - font-family: arial,sans-serif; + font-family: arial, sans-serif; } - div.dialog - { + + div.dialog { width: 25em; margin: 4em auto 0 auto; border: 1px solid #CCC; @@ -24,17 +23,18 @@ background-color: white; padding: 7px 4em 0 4em; } - h1{ + + h1 { font-size: 100%; color: #730E15; line-height: 1.5em; } - body>p - { - width: 33em; + + body > p { + width: 33em; margin: 0 auto 1em; padding: 1em 0; - background-color: #f7f7f7; + background-color: #F7F7F7; border: 1px solid #CCC; border-right-color: #999; border-bottom-color: #999; @@ -42,7 +42,7 @@ border-bottom-right-radius: 4px; border-top-color: #DADADA; color: #666; - box-shadow:0 3px 8px rgba(50,50,50,0.17); + box-shadow:0 3px 8px rgba(50, 50, 50, 0.17); } </style> </head> diff --git a/railties/lib/rails/generators/rails/app/templates/public/422.html b/railties/lib/rails/generators/rails/app/templates/public/422.html index f1f32b83ae..fbb4b84d72 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/422.html +++ b/railties/lib/rails/generators/rails/app/templates/public/422.html @@ -2,16 +2,15 @@ <html> <head> <title>The change you wanted was rejected (422)</title> - <style> - body - { - background-color: #efefef; + <style> + body { + background-color: #EFEFEF; color: #2E2F30; text-align: center; - font-family: arial,sans-serif; + font-family: arial, sans-serif; } - div.dialog - { + + div.dialog { width: 25em; margin: 4em auto 0 auto; border: 1px solid #CCC; @@ -24,17 +23,18 @@ background-color: white; padding: 7px 4em 0 4em; } - h1{ + + h1 { font-size: 100%; color: #730E15; line-height: 1.5em; } - body>p - { + + body > p { width: 33em; margin: 0 auto 1em; padding: 1em 0; - background-color: #f7f7f7; + background-color: #F7F7F7; border: 1px solid #CCC; border-right-color: #999; border-bottom-color: #999; @@ -42,7 +42,7 @@ border-bottom-right-radius: 4px; border-top-color: #DADADA; color: #666; - box-shadow:0 3px 8px rgba(50,50,50,0.17); + box-shadow:0 3px 8px rgba(50, 50, 50, 0.17); } </style> </head> diff --git a/railties/lib/rails/generators/rails/app/templates/public/500.html b/railties/lib/rails/generators/rails/app/templates/public/500.html index 9417de0cc0..e9052d35bf 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/500.html +++ b/railties/lib/rails/generators/rails/app/templates/public/500.html @@ -2,16 +2,15 @@ <html> <head> <title>We're sorry, but something went wrong (500)</title> - <style> - body - { - background-color: #efefef; + <style> + body { + background-color: #EFEFEF; color: #2E2F30; text-align: center; - font-family: arial,sans-serif; + font-family: arial, sans-serif; } - div.dialog - { + + div.dialog { width: 25em; margin: 4em auto 0 auto; border: 1px solid #CCC; @@ -24,17 +23,18 @@ background-color: white; padding: 7px 4em 0 4em; } - h1{ + + h1 { font-size: 100%; color: #730E15; line-height: 1.5em; } - body>p - { - width: 33em; + + body > p { + width: 33em; margin: 0 auto 1em; padding: 1em 0; - background-color: #f7f7f7; + background-color: #F7F7F7; border: 1px solid #CCC; border-right-color: #999; border-bottom-color: #999; @@ -42,7 +42,7 @@ border-bottom-right-radius: 4px; border-top-color: #DADADA; color: #666; - box-shadow:0 3px 8px rgba(50,50,50,0.17); + box-shadow:0 3px 8px rgba(50, 50, 50, 0.17); } </style> </head> diff --git a/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb index 9afda2d0df..ca40914d3b 100644 --- a/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb @@ -1,4 +1,4 @@ -ENV["RAILS_ENV"] = "test" +ENV["RAILS_ENV"] ||= "test" require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' @@ -6,11 +6,12 @@ class ActiveSupport::TestCase <% unless options[:skip_active_record] -%> ActiveRecord::Migration.check_pending! - # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. + # Uncomment the `fixtures :all` line below to setup all fixtures in test/fixtures/*.yml + # for all tests in alphabetical order. # # Note: You'll currently still have to declare fixtures explicitly in integration tests # -- they do not yet inherit this setting - fixtures :all + # fixtures :all <% end -%> # Add more helper methods to be used by all tests here... diff --git a/railties/lib/rails/generators/rails/model/USAGE b/railties/lib/rails/generators/rails/model/USAGE index 6574200fbf..1998a392aa 100644 --- a/railties/lib/rails/generators/rails/model/USAGE +++ b/railties/lib/rails/generators/rails/model/USAGE @@ -52,20 +52,26 @@ Available field types: `rails generate model product supplier:references{polymorphic}` - You can also specify some options just after the field type. You can use the - following options: + For integer, string, text and binary fields an integer in curly braces will + be set as the limit: - limit Set the maximum size of the field giving a number between curly braces - default Set a default value for the field - precision Defines the precision for the decimal fields - scale Defines the scale for the decimal fields - uniq Defines the field values as unique - index Will add an index on the field + `rails generate model user pseudo:string{30}` - Examples: + For decimal two integers separated by a comma in curly braces will be used + for precision and scale: + + `rails generate model product price:decimal{10,2}` + + You can add a `:uniq` or `:index` suffix for unique or standard indexes + respectively: - `rails generate model user pseudo:string{30}` `rails generate model user pseudo:string:uniq` + `rails generate model user pseudo:string:index` + + You can combine any single curly brace option with the index options: + + `rails generate model user username:string{30}:uniq` + `rails generate model product supplier:references{polymorphic}:index` Examples: diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 5fe01d0961..850c9d5c0d 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -106,8 +106,6 @@ task default: :test remove_file "doc" remove_file "Gemfile" remove_file "lib/tasks" - remove_file "app/assets/images/rails.png" - remove_file "public/index.html" remove_file "public/robots.txt" remove_file "README" remove_file "test" diff --git a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb index 36589d65e2..2a0522e81c 100644 --- a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb @@ -10,6 +10,7 @@ module Rails class_option :stylesheet_engine, desc: "Engine for Stylesheets" def handle_skip + @options = @options.merge(stylesheets: false) unless options[:assets] @options = @options.merge(stylesheet_engine: false) unless options[:stylesheets] end 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/test_unit/model/templates/fixtures.yml b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml index c9d505c84a..90a92e6982 100644 --- a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml +++ b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml @@ -1,22 +1,20 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html - <% unless attributes.empty? -%> -one: +<% %w(one two).each do |name| %> +<%= name %>: <% attributes.each do |attribute| -%> + <%- if attribute.password_digest? -%> + password_digest: <%%= BCrypt::Password.create('secret') %> + <%- else -%> <%= yaml_key_value(attribute.column_name, attribute.default) %> - <%- if attribute.polymorphic? -%> - <%= yaml_key_value("#{attribute.name}_type", attribute.human_name) %> <%- end -%> -<% end -%> - -two: -<% attributes.each do |attribute| -%> - <%= yaml_key_value(attribute.column_name, attribute.default) %> <%- if attribute.polymorphic? -%> <%= yaml_key_value("#{attribute.name}_type", attribute.human_name) %> <%- end -%> <% end -%> +<% end -%> <% else -%> + # This model initially had no columns defined. If you add columns to the # model remove the '{}' from the fixture names and add the columns immediately # below each fixture, per the syntax in the comments below diff --git a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb index 8f3ecaadea..2e1f55f2a6 100644 --- a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +++ b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb @@ -21,7 +21,11 @@ module TestUnit # :nodoc: return if attributes_names.empty? attributes_names.map do |name| - "#{name}: @#{singular_table_name}.#{name}" + if %w(password password_confirmation).include?(name) && attributes.any?(&:password_digest?) + "#{name}: 'secret'" + else + "#{name}: @#{singular_table_name}.#{name}" + end end.sort.join(', ') 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..7576eba6e0 --- /dev/null +++ b/railties/lib/rails/generators/testing/behaviour.rb @@ -0,0 +1,106 @@ +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) do + args += ['--skip-bundle'] unless args.include? '--dev' + self.generator_class.start(args, config.reverse_merge(destination_root: destination_root)) + end + 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 diff --git a/railties/lib/rails/info.rb b/railties/lib/rails/info.rb index 592e74726e..f06ce659c5 100644 --- a/railties/lib/rails/info.rb +++ b/railties/lib/rails/info.rb @@ -29,7 +29,7 @@ module Rails def framework_version(framework) if Object.const_defined?(framework.classify) require "#{framework}/version" - "#{framework.classify}::VERSION::STRING".constantize + framework.classify.constantize.version.to_s end end @@ -75,7 +75,7 @@ module Rails # The Rails version. property 'Rails version' do - Rails::VERSION::STRING + Rails.version.to_s end property 'JavaScript Runtime' do diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake index 0057b0f887..1c3426028d 100644 --- a/railties/lib/rails/tasks/documentation.rake +++ b/railties/lib/rails/tasks/documentation.rake @@ -1,4 +1,5 @@ require 'rdoc/task' +require 'rails/api/task' # Monkey-patch to remove redoc'ing and clobber descriptions to cut down on rake -T noise class RDocTaskWithoutDescriptions < RDoc::Task @@ -52,52 +53,7 @@ namespace :doc do Rake::Task['doc:app'].comment = "Generate docs for the app -- also available doc:rails, doc:guides (options: TEMPLATE=/rdoc-template.rb, TITLE=\"Custom Title\")" # desc 'Generate documentation for the Rails framework.' - RDocTaskWithoutDescriptions.new("rails") { |rdoc| - rdoc.rdoc_dir = 'doc/api' - rdoc.template = "#{ENV['template']}.rb" if ENV['template'] - rdoc.title = "Rails Framework Documentation" - rdoc.options << '--line-numbers' - - gem_path('rails') do |rails| - rdoc.options << '-m' << "#{rails}/README.rdoc" - end - - gem_path('actionmailer') do |actionmailer| - %w(README.rdoc CHANGELOG.md MIT-LICENSE lib/action_mailer/base.rb).each do |file| - rdoc.rdoc_files.include("#{actionmailer}/#{file}") - end - end - - gem_path('actionpack') do |actionpack| - %w(README.rdoc CHANGELOG.md MIT-LICENSE lib/action_controller/**/*.rb lib/action_view/**/*.rb).each do |file| - rdoc.rdoc_files.include("#{actionpack}/#{file}") - end - end - - gem_path('activemodel') do |activemodel| - %w(README.rdoc CHANGELOG.md MIT-LICENSE lib/active_model/**/*.rb).each do |file| - rdoc.rdoc_files.include("#{activemodel}/#{file}") - end - end - - gem_path('activerecord') do |activerecord| - %w(README.rdoc CHANGELOG.md lib/active_record/**/*.rb).each do |file| - rdoc.rdoc_files.include("#{activerecord}/#{file}") - end - end - - gem_path('activesupport') do |activesupport| - %w(README.rdoc CHANGELOG.md lib/active_support/**/*.rb).each do |file| - rdoc.rdoc_files.include("#{activesupport}/#{file}") - end - end - - gem_path('railties') do |railties| - %w(README.rdoc CHANGELOG.md lib/{*.rb,commands/*.rb,generators/*.rb}).each do |file| - rdoc.rdoc_files.include("#{railties}/#{file}") - end - end - } + Rails::API::AppTask.new('rails') # desc "Generate Rails Guides" task :guides do diff --git a/railties/lib/rails/templates/rails/welcome/index.html.erb b/railties/lib/rails/templates/rails/welcome/index.html.erb index e239e1695e..4c4c80ecda 100644 --- a/railties/lib/rails/templates/rails/welcome/index.html.erb +++ b/railties/lib/rails/templates/rails/welcome/index.html.erb @@ -59,7 +59,7 @@ #header { - background-image: url("/assets/rails.png"); + background-image: url(data:image/png;base64,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); background-repeat: no-repeat; background-position: top left; height: 64px; diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index 44485d9b14..3c247f32c0 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -1,6 +1,7 @@ require 'rbconfig' require 'rake/testtask' require 'rails/test_unit/sub_test_task' +require 'active_support/deprecation' TEST_CHANGES_SINCE = Time.now - 600 @@ -47,7 +48,11 @@ task default: :test desc 'Runs test:units, test:functionals, test:integration together' task :test do - Rake::Task[ENV['TEST'] ? 'test:single' : 'test:run'].invoke + if ENV['TEST'] + exec "bundle exec rails test #{ENV['TEST'].inspect}" + else + exec 'bundle exec rails test' + end end namespace :test do @@ -56,19 +61,8 @@ namespace :test do end task :run do - errors = %w(test:units test:functionals test:integration).collect do |task| - begin - Rake::Task[task].invoke - nil - rescue => e - { task: task, exception: e } - end - end.compact - - if errors.any? - puts errors.map { |e| "Errors running #{e[:task]}! #{e[:exception].inspect}" }.join("\n") - abort - end + ActiveSupport::Deprecation.warn "`rake test:run` is deprecated. Please use `rails test`." + exec 'bundle exec rails test' end # Inspired by: http://ngauthier.com/2012/02/quick-tests-with-bash.html @@ -83,7 +77,12 @@ namespace :test do task :db => %w[db:test:prepare test:all] end - Rake::TestTask.new(recent: "test:prepare") do |t| + # Display deprecation message + task :deprecated do + ActiveSupport::Deprecation.warn "`rake #{ARGV.first}` is deprecated with no replacement." + end + + Rake::TestTask.new(recent: ["test:deprecated", "test:prepare"]) do |t| since = TEST_CHANGES_SINCE touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } + recent_tests('app/models/**/*.rb', 'test/models', since) + @@ -94,9 +93,9 @@ namespace :test do t.libs << 'test' t.test_files = touched.uniq end - Rake::Task['test:recent'].comment = "Test recent changes" + Rake::Task['test:recent'].comment = "Deprecated; Test recent changes" - Rake::TestTask.new(uncommitted: "test:prepare") do |t| + Rake::TestTask.new(uncommitted: ["test:deprecated", "test:prepare"]) do |t| def t.file_list if File.directory?(".svn") changed_since_checkin = silence_stderr { `svn status` }.split.map { |path| path.chomp[7 .. -1] } @@ -118,44 +117,20 @@ namespace :test do t.libs << 'test' end - Rake::Task['test:uncommitted'].comment = "Test changes since last checkin (only Subversion and Git)" - - Rake::TestTask.new(single: "test:prepare") do |t| - t.libs << "test" - end - - Rails::SubTestTask.new(models: "test:prepare") do |t| - t.libs << "test" - t.pattern = 'test/models/**/*_test.rb' - end - - Rails::SubTestTask.new(helpers: "test:prepare") do |t| - t.libs << "test" - t.pattern = 'test/helpers/**/*_test.rb' - end + Rake::Task['test:uncommitted'].comment = "Deprecated; Test changes since last checkin (only Subversion and Git)" - Rails::SubTestTask.new(units: "test:prepare") do |t| - t.libs << "test" - t.pattern = 'test/{models,helpers,unit}/**/*_test.rb' + desc "Deprecated; Please use `rails test \"#{ENV['TEST']}\"`" + task :single do + ActiveSupport::Deprecation.warn "`rake test:single` is deprecated. Please use `rails test \"#{ENV['TEST']}\"`." + exec "bundle exec rails test #{test_suit_name}" end - Rails::SubTestTask.new(controllers: "test:prepare") do |t| - t.libs << "test" - t.pattern = 'test/controllers/**/*_test.rb' - end + [:models, :helpers, :units, :controllers, :functionals, :integration].each do |test_suit_name| + desc "Deprecated; Please use `rails test #{test_suit_name}`" + task test_suit_name do + ActiveSupport::Deprecation.warn "`rake test:#{test_suit_name}` is deprecated. Please use `rails test #{test_suit_name}`." - Rails::SubTestTask.new(mailers: "test:prepare") do |t| - t.libs << "test" - t.pattern = 'test/mailers/**/*_test.rb' - end - - Rails::SubTestTask.new(functionals: "test:prepare") do |t| - t.libs << "test" - t.pattern = 'test/{controllers,mailers,functional}/**/*_test.rb' - end - - Rails::SubTestTask.new(integration: "test:prepare") do |t| - t.libs << "test" - t.pattern = 'test/integration/**/*_test.rb' + exec "bundle exec rails test #{test_suit_name}" + end end end diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb index 87fc7690ac..fee352db5a 100644 --- a/railties/lib/rails/version.rb +++ b/railties/lib/rails/version.rb @@ -1,10 +1,10 @@ module Rails - module VERSION #:nodoc: + module VERSION MAJOR = 4 MINOR = 0 TINY = 0 PRE = "beta1" - STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') + STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end end |