diff options
author | Pratik Naik <pratiknaik@gmail.com> | 2010-01-04 03:24:39 +0530 |
---|---|---|
committer | Pratik Naik <pratiknaik@gmail.com> | 2010-01-04 03:24:39 +0530 |
commit | cda36a0731f14b33a920bf7e32255661e06f890a (patch) | |
tree | 79ccba37953f9fe3055503be42b1610faa6d64ad /railties/lib | |
parent | bd4a3cce4ecd8e648179a91e26506e3622ac2162 (diff) | |
parent | a115b5d79a850bb56cd3c9db9a05d6da35e3d7be (diff) | |
download | rails-cda36a0731f14b33a920bf7e32255661e06f890a.tar.gz rails-cda36a0731f14b33a920bf7e32255661e06f890a.tar.bz2 rails-cda36a0731f14b33a920bf7e32255661e06f890a.zip |
Merge remote branch 'mainstream/master'
Diffstat (limited to 'railties/lib')
87 files changed, 1453 insertions, 1771 deletions
diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index c23b67e321..d69e3eea6a 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -1,13 +1,106 @@ require "pathname" +require 'active_support' +require 'active_support/core_ext/kernel/reporting' +require 'active_support/core_ext/logger' +require 'action_dispatch' + require 'rails/initializable' require 'rails/application' +require 'rails/railtie' +require 'rails/plugin' require 'rails/railties_path' require 'rails/version' require 'rails/rack' require 'rails/paths' -require 'rails/core' require 'rails/configuration' require 'rails/deprecation' -require 'rails/initializer' -require 'rails/plugin'
\ No newline at end of file +require 'rails/ruby_version_check' + +# For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the +# multibyte safe operations. Plugin authors supporting other encodings +# should override this behaviour and set the relevant +default_charset+ +# on ActionController::Base. +# +# For Ruby 1.9, UTF-8 is the default internal and external encoding. +if RUBY_VERSION < '1.9' + $KCODE='u' +else + Encoding.default_external = Encoding::UTF_8 +end + +RAILS_ENV = (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup unless defined?(RAILS_ENV) + +module Rails + # Needs to be duplicated from Active Support since its needed before Active + # Support is available. Here both Options and Hash are namespaced to prevent + # conflicts with other implementations AND with the classes residing in Active Support. + # --- + # TODO: w0t? + class << self + def application + @@application ||= nil + end + + def application=(application) + @@application = application + end + + # The Configuration instance used to configure the Rails environment + def configuration + application.configuration + end + + def initialize! + application.initialize! + end + + def initialized? + @initialized || false + end + + def initialized=(initialized) + @initialized ||= initialized + end + + def logger + if defined?(RAILS_DEFAULT_LOGGER) + RAILS_DEFAULT_LOGGER + else + nil + end + end + + def backtrace_cleaner + @@backtrace_cleaner ||= begin + # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded + require 'rails/backtrace_cleaner' + Rails::BacktraceCleaner.new + end + end + + def root + application && application.config.root + end + + def env + @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) + end + + def cache + RAILS_CACHE + end + + def version + VERSION::STRING + end + + def public_path + @@public_path ||= self.root ? File.join(self.root, "public") : "public" + end + + def public_path=(path) + @@public_path = path + end + end +end diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb new file mode 100644 index 0000000000..7dfe2b8b63 --- /dev/null +++ b/railties/lib/rails/all.rb @@ -0,0 +1,15 @@ +require "rails" + +%w( + active_model + active_record + action_controller + action_view + action_mailer + active_resource +).each do |framework| + begin + require "#{framework}/railtie" + rescue LoadError + end +end
\ No newline at end of file diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 7c2d8eab67..5401251397 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,58 +1,85 @@ +require "fileutils" +require 'active_support/core_ext/module/delegation' + module Rails class Application include Initializable class << self - def inherited(klass) - Rails.application ||= klass unless klass.name =~ /Rails/ - super - end + attr_writer :config + alias configure class_eval + delegate :initialize!, :load_tasks, :root, :to => :instance - # Stub out App initialize - def initialize! - new - end - - def new - @instance ||= super + private :new + def instance + @instance ||= new end def config - @config ||= Configuration.new + @config ||= Configuration.new(Plugin::Configuration.default) end - # TODO: change the plugin loader to use config - alias configuration config - - def config=(config) - @config = config + def routes + ActionController::Routing::Routes end + end - def root - config.root - end + delegate :config, :routes, :to => :'self.class' + delegate :root, :middleware, :to => :config + attr_reader :route_configuration_files - def call(env) - new.call(env) - end + def initialize + require_environment + Rails.application ||= self + @route_configuration_files = [] end - def initialize + def initialize! run_initializers(self) + self end - def config - self.class.config + def require_environment + require config.environment_path + rescue LoadError end - alias configuration config + def routes_changed_at + routes_changed_at = nil - def middleware - config.middleware + route_configuration_files.each do |config| + config_changed_at = File.stat(config).mtime + + if routes_changed_at.nil? || config_changed_at > routes_changed_at + routes_changed_at = config_changed_at + end + end + + routes_changed_at + end + + def reload_routes! + routes.disable_clear_and_finalize = true + + routes.clear! + route_configuration_files.each { |config| load(config) } + routes.finalize! + + nil + ensure + routes.disable_clear_and_finalize = false end - def routes - ActionController::Routing::Routes + def load_tasks + require "rails/tasks" + plugins.each { |p| p.load_tasks } + # Load all application tasks + # TODO: extract out the path to the rake tasks + Dir["#{root}/lib/tasks/**/*.rake"].sort.each { |ext| load ext } + task :environment do + $rails_rake_task = true + initialize! + end end def initializers @@ -61,9 +88,12 @@ module Rails initializers end + # TODO: Fix this method def plugins @plugins ||= begin - Plugin::Vendored.all(config.plugins || [:all], config.paths.vendor.plugins) + plugin_names = config.plugins || [:all] + Railtie.plugins.select { |p| plugin_names.include?(:all) || plugin_names.include?(p.plugin_name) }.map { |p| p.new } + + Plugin.all(config.plugins || [:all], config.paths.vendor.plugins) end end @@ -72,8 +102,8 @@ module Rails @app.call(env) end - initializer :initialize_rails do - Rails.run_initializers + initializer :load_all_active_support do + require "active_support/all" unless config.active_support.bare end # Set the <tt>$LOAD_PATH</tt> based on the value of @@ -83,24 +113,6 @@ module Rails $LOAD_PATH.uniq! end - # Requires all frameworks specified by the Configuration#frameworks - # list. By default, all frameworks (Active Record, Active Support, - # Action Pack, Action Mailer, and Active Resource) are loaded. - initializer :require_frameworks do - begin - require 'active_support' - require 'active_support/core_ext/kernel/reporting' - require 'active_support/core_ext/logger' - - # TODO: This is here to make Sam Ruby's tests pass. Needs discussion. - require 'active_support/core_ext/numeric/bytes' - config.frameworks.each { |framework| require(framework.to_s) } - rescue LoadError => e - # Re-raise as RuntimeError because Mongrel would swallow LoadError. - raise e.to_s - end - end - # Set the paths from which Rails will automatically load source files, and # the load_once paths. initializer :set_autoload_paths do @@ -123,25 +135,7 @@ module Rails # Create tmp directories initializer :ensure_tmp_directories_exist do %w(cache pids sessions sockets).each do |dir_to_make| - FileUtils.mkdir_p(File.join(config.root, 'tmp', dir_to_make)) - end - end - - # Loads the environment specified by Configuration#environment_path, which - # is typically one of development, test, or production. - initializer :load_environment do - silence_warnings do - next if @environment_loaded - next unless File.file?(config.environment_path) - - @environment_loaded = true - constants = self.class.constants - - eval(IO.read(config.environment_path), binding, config.environment_path) - - (self.class.constants - constants).each do |const| - Object.const_set(const, self.class.const_get(const)) - end + FileUtils.mkdir_p(File.join(root, 'tmp', dir_to_make)) end end @@ -149,44 +143,7 @@ module Rails # Used by Passenger to ensure everything's loaded before forking and # to avoid autoload race conditions in JRuby. initializer :preload_frameworks do - if config.preload_frameworks - config.frameworks.each do |framework| - # String#classify and #constantize aren't available yet. - toplevel = Object.const_get(framework.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }) - toplevel.load_all! if toplevel.respond_to?(:load_all!) - end - end - end - - # This initialization routine does nothing unless <tt>:active_record</tt> - # is one of the frameworks to load (Configuration#frameworks). If it is, - # this sets the database configuration from Configuration#database_configuration - # and then establishes the connection. - initializer :initialize_database do - if config.frameworks.include?(:active_record) - ActiveRecord::Base.configurations = config.database_configuration - ActiveRecord::Base.establish_connection - end - end - - # Include middleware to serve up static assets - initializer :initialize_static_server do - if config.frameworks.include?(:action_controller) && config.serve_static_assets - config.middleware.use(ActionDispatch::Static, Rails.public_path) - end - end - - initializer :initialize_middleware_stack do - if config.frameworks.include?(:action_controller) - config.middleware.use(::Rack::Lock) unless ActionController::Base.allow_concurrency - config.middleware.use(ActionDispatch::ShowExceptions, ActionController::Base.consider_all_requests_local) - config.middleware.use(ActionDispatch::Callbacks, ActionController::Dispatcher.prepare_each_request) - config.middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) - config.middleware.use(ActionDispatch::ParamsParser) - config.middleware.use(::Rack::MethodOverride) - config.middleware.use(::Rack::Head) - config.middleware.use(ActionDispatch::StringCoercion) - end + ActiveSupport::Autoload.eager_autoload! if config.preload_frameworks end initializer :initialize_cache do @@ -200,12 +157,6 @@ module Rails end end - initializer :initialize_framework_caches do - if config.frameworks.include?(:action_controller) - ActionController::Base.cache_store ||= RAILS_CACHE - end - end - initializer :initialize_logger do # if the environment has explicitly defined a logger, use it next if Rails.logger @@ -236,10 +187,6 @@ module Rails # logger is already set, it is not changed, otherwise it is set to use # RAILS_DEFAULT_LOGGER. initializer :initialize_framework_logging do - for framework in ([ :active_record, :action_controller, :action_mailer ] & config.frameworks) - framework.to_s.camelize.constantize.const_get("Base").logger ||= Rails.logger - end - ActiveSupport::Dependencies.logger ||= Rails.logger Rails.cache.logger ||= Rails.logger end @@ -257,7 +204,7 @@ module Rails require('active_support/whiny_nil') if config.whiny_nils end - # Sets the default value for Time.zone, and turns on ActiveRecord::Base#time_zone_aware_attributes. + # Sets the default value for Time.zone # If assigned value cannot be matched to a TimeZone, an exception will be raised. initializer :initialize_time_zone do if config.time_zone @@ -271,11 +218,6 @@ module Rails end Time.zone_default = zone_default - - if config.frameworks.include?(:active_record) - ActiveRecord::Base.time_zone_aware_attributes = true - ActiveRecord::Base.default_timezone = :utc - end end end @@ -291,110 +233,28 @@ module Rails end end - # Initializes framework-specific settings for each of the loaded frameworks - # (Configuration#frameworks). The available settings map to the accessors - # on each of the corresponding Base classes. - initializer :initialize_framework_settings do - config.frameworks.each do |framework| - base_class = framework.to_s.camelize.constantize.const_get("Base") - - config.send(framework).each do |setting, value| - base_class.send("#{setting}=", value) - end - end - config.active_support.each do |setting, value| - ActiveSupport.send("#{setting}=", value) - end - end - - # Sets +ActionController::Base#view_paths+ and +ActionMailer::Base#template_root+ - # (but only for those frameworks that are to be loaded). If the framework's - # paths have already been set, it is not changed, otherwise it is - # set to use Configuration#view_path. - initializer :initialize_framework_views do - if config.frameworks.include?(:action_view) - view_path = ActionView::PathSet.type_cast(config.view_path, config.cache_classes) - ActionMailer::Base.template_root = view_path if config.frameworks.include?(:action_mailer) && ActionMailer::Base.view_paths.blank? - ActionController::Base.view_paths = view_path if config.frameworks.include?(:action_controller) && ActionController::Base.view_paths.blank? - end - end - - initializer :initialize_metal do - # TODO: Make Rails and metal work without ActionController - if config.frameworks.include?(:action_controller) - Rails::Rack::Metal.requested_metals = config.metals - - config.middleware.insert_before( - :"ActionDispatch::ParamsParser", - Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?) - end - end - # # bail out if gems are missing - note that check_gem_dependencies will have # # already called abort() unless $gems_rake_task is set # return unless gems_dependencies_loaded initializer :load_application_initializers do - Dir["#{configuration.root}/config/initializers/**/*.rb"].sort.each do |initializer| + Dir["#{root}/config/initializers/**/*.rb"].sort.each do |initializer| load(initializer) end end # Fires the user-supplied after_initialize block (Configuration#after_initialize) initializer :after_initialize do - configuration.after_initialize_blocks.each do |block| + config.after_initialize_blocks.each do |block| block.call end end - # # Setup database middleware after initializers have run - initializer :initialize_database_middleware do - if configuration.frameworks.include?(:active_record) - if configuration.frameworks.include?(:action_controller) && ActionController::Base.session_store && - ActionController::Base.session_store.name == 'ActiveRecord::SessionStore' - configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement - configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache - else - configuration.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement - configuration.middleware.use ActiveRecord::QueryCache - end - end - end - - # TODO: Make a DSL way to limit an initializer to a particular framework - - # # Prepare dispatcher callbacks and run 'prepare' callbacks - initializer :prepare_dispatcher do - next unless configuration.frameworks.include?(:action_controller) - require 'rails/dispatcher' unless defined?(::Dispatcher) - Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) - end - - # Routing must be initialized after plugins to allow the former to extend the routes - # --- - # If Action Controller is not one of the loaded frameworks (Configuration#frameworks) - # this does nothing. Otherwise, it loads the routing definitions and sets up - # loading module used to lazily load controllers (Configuration#controller_paths). - initializer :initialize_routing do - next unless configuration.frameworks.include?(:action_controller) - - ActionController::Routing.controller_paths += configuration.controller_paths - ActionController::Routing::Routes.add_configuration_file(configuration.routes_configuration_file) - ActionController::Routing::Routes.reload! - end - # - # # Observers are loaded after plugins in case Observers or observed models are modified by plugins. - initializer :load_observers do - if configuration.frameworks.include?(:active_record) - ActiveRecord::Base.instantiate_observers - end - end - # Eager load application classes initializer :load_application_classes do next if $rails_rake_task - if configuration.cache_classes - configuration.eager_load_paths.each do |load_path| + if config.cache_classes + config.eager_load_paths.each do |load_path| matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/ Dir.glob("#{load_path}/**/*.rb").sort.each do |file| require_dependency file.sub(matcher, '\1') @@ -405,20 +265,9 @@ module Rails # Disable dependency loading during request cycle initializer :disable_dependency_loading do - if configuration.cache_classes && !configuration.dependency_loading + if config.cache_classes && !config.dependency_loading ActiveSupport::Dependencies.unhook! end end - - # For each framework, search for instrument file with Notifications hooks. - # - initializer :load_notifications_hooks do - config.frameworks.each do |framework| - begin - require "#{framework}/notifications" - rescue LoadError => e - end - end - end end end diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index b977b7162f..37eb6d40ea 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -1,45 +1,56 @@ -irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb' - require 'optparse' +require 'irb' +require "irb/completion" -options = { :sandbox => false, :irb => irb } -OptionParser.new do |opt| - opt.banner = "Usage: console [environment] [options]" - opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v } - opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v } - opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v } - opt.parse!(ARGV) -end +module Rails + class Console + ENVIRONMENTS = %w(production development test) -libs = " -r irb/completion" -libs << %( -r "#{Rails.root}/config/environment") -libs << " -r rails/console_app" -libs << " -r rails/console_sandbox" if options[:sandbox] -libs << " -r rails/console_with_helpers" - -if options[:debugger] - begin - require 'ruby-debug' - libs << " -r ruby-debug" - puts "=> Debugger enabled" - rescue Exception - puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'" - exit - end -end + def self.start(app) + new(app).start + end -ENV['RAILS_ENV'] = case ARGV.first - when "p"; "production" - when "d"; "development" - when "t"; "test" - else - ARGV.first || ENV['RAILS_ENV'] || 'development' -end + def initialize(app) + @app = app + end + + def start + options = {} -if options[:sandbox] - puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails.version})" - puts "Any modifications you make will be rolled back on exit" -else - puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails.version})" + OptionParser.new do |opt| + opt.banner = "Usage: console [environment] [options]" + opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v } + opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v } + opt.on('--irb') { |v| abort '--irb option is no longer supported. Invoke `/your/choice/of/ruby script/console` instead' } + opt.parse!(ARGV) + end + + if env = ARGV.first + ENV['RAILS_ENV'] = ENVIRONMENTS.find { |e| e.index(env) } || env + end + + @app.initialize! + require "rails/console_app" + require "rails/console_sandbox" if options[:sandbox] + require "rails/console_with_helpers" + + if options[:debugger] + begin + require 'ruby-debug' + puts "=> Debugger enabled" + rescue Exception + puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'" + exit + end + end + + if options[:sandbox] + puts "Loading #{Rails.env} environment in sandbox (Rails #{Rails.version})" + puts "Any modifications you make will be rolled back on exit" + else + puts "Loading #{Rails.env} environment (Rails #{Rails.version})" + end + IRB.start + end + end end -exec "#{options[:irb]} #{libs} --simple-prompt" diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb index 4e699acf6b..77c3404343 100644 --- a/railties/lib/rails/commands/dbconsole.rb +++ b/railties/lib/rails/commands/dbconsole.rb @@ -2,86 +2,99 @@ require 'erb' require 'yaml' require 'optparse' -include_password = false -options = {} - -OptionParser.new do |opt| - opt.banner = "Usage: dbconsole [options] [environment]" - opt.on("-p", "--include-password", "Automatically provide the password from database.yml") do |v| - include_password = true - end - - opt.on("--mode [MODE]", ['html', 'list', 'line', 'column'], - "Automatically put the sqlite3 database in the specified mode (html, list, line, column).") do |mode| - options['mode'] = mode - end - - opt.on("-h", "--header") do |h| - options['header'] = h - end - - opt.parse!(ARGV) - abort opt.to_s unless (0..1).include?(ARGV.size) -end - -env = ARGV.first || ENV['RAILS_ENV'] || 'development' -unless config = YAML::load(ERB.new(IO.read(Rails.root + "/config/database.yml")).result)[env] - abort "No database is configured for the environment '#{env}'" -end - +module Rails + class DBConsole + def self.start(app) + new(app).start + end -def find_cmd(*commands) - dirs_on_path = ENV['PATH'].to_s.split(File::PATH_SEPARATOR) - commands += commands.map{|cmd| "#{cmd}.exe"} if RUBY_PLATFORM =~ /win32/ + def initialize(app) + @app = app + end - full_path_command = nil - found = commands.detect do |cmd| - dir = dirs_on_path.detect do |path| - full_path_command = File.join(path, cmd) - File.executable? full_path_command + def start + include_password = false + options = {} + OptionParser.new do |opt| + opt.banner = "Usage: dbconsole [options] [environment]" + opt.on("-p", "--include-password", "Automatically provide the password from database.yml") do |v| + include_password = true + end + + opt.on("--mode [MODE]", ['html', 'list', 'line', 'column'], + "Automatically put the sqlite3 database in the specified mode (html, list, line, column).") do |mode| + options['mode'] = mode + end + + opt.on("-h", "--header") do |h| + options['header'] = h + end + + opt.parse!(ARGV) + abort opt.to_s unless (0..1).include?(ARGV.size) + end + + env = ARGV.first || ENV['RAILS_ENV'] || 'development' + unless config = YAML::load(ERB.new(IO.read("#{@app.root}/config/database.yml")).result)[env] + abort "No database is configured for the environment '#{env}'" + end + + + def find_cmd(*commands) + dirs_on_path = ENV['PATH'].to_s.split(File::PATH_SEPARATOR) + commands += commands.map{|cmd| "#{cmd}.exe"} if RUBY_PLATFORM =~ /win32/ + + full_path_command = nil + found = commands.detect do |cmd| + dir = dirs_on_path.detect do |path| + full_path_command = File.join(path, cmd) + File.executable? full_path_command + end + end + found ? full_path_command : abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.") + end + + case config["adapter"] + when "mysql" + args = { + 'host' => '--host', + 'port' => '--port', + 'socket' => '--socket', + 'username' => '--user', + 'encoding' => '--default-character-set' + }.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact + + if config['password'] && include_password + args << "--password=#{config['password']}" + elsif config['password'] && !config['password'].to_s.empty? + args << "-p" + end + + args << config['database'] + + exec(find_cmd('mysql', 'mysql5'), *args) + + when "postgresql" + ENV['PGUSER'] = config["username"] if config["username"] + ENV['PGHOST'] = config["host"] if config["host"] + ENV['PGPORT'] = config["port"].to_s if config["port"] + ENV['PGPASSWORD'] = config["password"].to_s if config["password"] && include_password + exec(find_cmd('psql'), config["database"]) + + when "sqlite" + exec(find_cmd('sqlite'), config["database"]) + + when "sqlite3" + args = [] + + args << "-#{options['mode']}" if options['mode'] + args << "-header" if options['header'] + args << config['database'] + + exec(find_cmd('sqlite3'), *args) + else + abort "Unknown command-line client for #{config['database']}. Submit a Rails patch to add support!" + end end end - found ? full_path_command : abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.") -end - -case config["adapter"] -when "mysql" - args = { - 'host' => '--host', - 'port' => '--port', - 'socket' => '--socket', - 'username' => '--user', - 'encoding' => '--default-character-set' - }.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact - - if config['password'] && include_password - args << "--password=#{config['password']}" - elsif config['password'] && !config['password'].to_s.empty? - args << "-p" - end - - args << config['database'] - - exec(find_cmd('mysql', 'mysql5'), *args) - -when "postgresql" - ENV['PGUSER'] = config["username"] if config["username"] - ENV['PGHOST'] = config["host"] if config["host"] - ENV['PGPORT'] = config["port"].to_s if config["port"] - ENV['PGPASSWORD'] = config["password"].to_s if config["password"] && include_password - exec(find_cmd('psql'), config["database"]) - -when "sqlite" - exec(find_cmd('sqlite'), config["database"]) - -when "sqlite3" - args = [] - - args << "-#{options['mode']}" if options['mode'] - args << "-header" if options['header'] - args << config['database'] - - exec(find_cmd('sqlite3'), *args) -else - abort "Unknown command-line client for #{config['database']}. Submit a Rails patch to add support!" -end +end
\ No newline at end of file diff --git a/railties/lib/rails/commands/ncgi/tracker b/railties/lib/rails/commands/ncgi/tracker deleted file mode 100755 index 4ca12d779b..0000000000 --- a/railties/lib/rails/commands/ncgi/tracker +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env ruby - -require 'drb' -require 'thread' - -def message(s) - $stderr.puts "tracker: #{s}" if ENV && ENV["DEBUG_GATEWAY"] -end - -class Tracker - include DRbUndumped - - def initialize(instances, socket_path) - @instances = instances - @socket = File.expand_path(socket_path) - @active = false - - @listeners = [] - @instances.times { @listeners << Mutex.new } - - message "using #{@listeners.length} listeners" - message "opening socket at #{@socket}" - - @service = DRb.start_service("drbunix://#{@socket}", self) - end - - def with_listener - message "listener requested" - - mutex = has_lock = index = nil - 3.times do - @listeners.each_with_index do |mutex, index| - has_lock = mutex.try_lock - break if has_lock - end - break if has_lock - sleep 0.05 - end - - if has_lock - message "obtained listener #{index}" - @active = true - begin yield index - ensure - mutex.unlock - message "released listener #{index}" - end - else - message "dropping request because no listeners are available!" - end - end - - def background(check_interval = nil) - if check_interval - loop do - sleep check_interval - message "Idle for #{check_interval}, shutting down" unless @active - @active = false - Kernel.exit 0 - end - else DRb.thread.join - end - end -end - -socket_path = ARGV.shift -instances = ARGV.shift.to_i -t = Tracker.new(instances, socket_path) -t.background(ARGV.first ? ARGV.shift.to_i : 90) diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 2c90851fb2..09d7207d51 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -1,73 +1,76 @@ -require 'action_dispatch' - require 'fileutils' require 'optparse' +require 'action_dispatch' -options = { - :Port => 3000, - :Host => "0.0.0.0", - :environment => (ENV['RAILS_ENV'] || "development").dup, - :config => "#{Rails.root}/config.ru", - :detach => false, - :debugger => false -} - -ARGV.clone.options do |opts| - opts.on("-p", "--port=port", Integer, - "Runs Rails on the specified port.", "Default: #{options[:Port]}") { |v| options[:Port] = v } - opts.on("-b", "--binding=ip", String, - "Binds Rails to the specified ip.", "Default: #{options[:Host]}") { |v| options[:Host] = v } - opts.on("-c", "--config=file", String, - "Use custom rackup configuration file") { |v| options[:config] = v } - opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:detach] = true } - opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { options[:debugger] = true } - opts.on("-e", "--environment=name", String, - "Specifies the environment to run this server under (test/development/production).", - "Default: #{options[:environment]}") { |v| options[:environment] = v } - - opts.separator "" +module Rails + class Server < ::Rack::Server + class Options + def parse!(args) + options = {} + args = args.dup + opt_parser = OptionParser.new do |opts| + opts.on("-p", "--port=port", Integer, + "Runs Rails on the specified port.", "Default: #{options[:Port]}") { |v| options[:Port] = v } + opts.on("-b", "--binding=ip", String, + "Binds Rails to the specified ip.", "Default: #{options[:Host]}") { |v| options[:Host] = v } + opts.on("-c", "--config=file", String, + "Use custom rackup configuration file") { |v| options[:config] = v } + opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:daemonize] = true } + opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { options[:debugger] = true } + opts.on("-e", "--environment=name", String, + "Specifies the environment to run this server under (test/development/production).", + "Default: #{options[:environment]}") { |v| options[:environment] = v } - opts.on("-h", "--help", "Show this help message.") { puts opts; exit } + opts.separator "" - opts.parse! -end + opts.on("-h", "--help", "Show this help message.") { puts opts; exit } + end -server = Rack::Handler.get(ARGV.first) rescue nil -unless server - begin - server = Rack::Handler::Mongrel - rescue LoadError => e - server = Rack::Handler::WEBrick - end -end + opt_parser.parse! args -puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" -puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}" + options[:server] = args.shift + options + end + end -if options[:detach] - Process.daemon - pid = "#{Rails.root}/tmp/pids/server.pid" - File.open(pid, 'w'){ |f| f.write(Process.pid) } - at_exit { File.delete(pid) if File.exist?(pid) } -end + def opt_parser + Options.new + end -ENV["RAILS_ENV"] = options[:environment] -RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV) + def start + puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" + puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}" + puts "=> Call with -d to detach" unless options[:daemonize] + trap(:INT) { exit } + puts "=> Ctrl-C to shutdown server" unless options[:daemonize] -app = Rack::Builder.new { - use Rails::Rack::LogTailer unless options[:detach] - use Rails::Rack::Debugger if options[:debugger] - run ActionDispatch::Utils.parse_config(options[:config]) -}.to_app + ENV["RAILS_ENV"] = options[:environment] + RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV) -puts "=> Call with -d to detach" + super + ensure + puts 'Exiting' unless options[:daemonize] + end -trap(:INT) { exit } + def middleware + middlewares = [] + middlewares << [Rails::Rack::LogTailer, log_path] unless options[:daemonize] + middlewares << [Rails::Rack::Debugger] if options[:debugger] + Hash.new(middlewares) + end -puts "=> Ctrl-C to shutdown server" + def log_path + "log/#{options[:environment]}.log" + end -begin - server.run(app, options.merge(:AccessLog => [])) -ensure - puts 'Exiting' + def default_options + super.merge({ + :Port => 3000, + :environment => (ENV['RAILS_ENV'] || "development").dup, + :daemonize => false, + :debugger => false, + :pid => "tmp/pids/server.pid" + }) + end + end end diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 102a0836dc..f0a0d5e55e 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,27 +1,74 @@ require 'active_support/ordered_options' module Rails - class Configuration - attr_accessor :cache_classes, :load_paths, :load_once_paths, :after_initialize_blocks, - :frameworks, :framework_root_path, :root, :gems, :plugins, - :i18n, :gems, :whiny_nils, :consider_all_requests_local, - :action_controller, :active_record, :action_view, :active_support, - :action_mailer, :active_resource, - :reload_plugins, :log_path, :log_level, :logger, :preload_frameworks, - :database_configuration_file, :cache_store, :time_zone, - :view_path, :metals, :controller_paths, :routes_configuration_file, - :eager_load_paths, :dependency_loading, :paths, :serve_static_assets - - def initialize + # Temporarily separate the plugin configuration class from the main + # configuration class while this bit is being cleaned up. + class Railtie::Configuration + + def self.default + @default ||= new + end + + attr_reader :middleware + + def initialize(base = nil) + if base + @options = base.options.dup + @middleware = base.middleware.dup + else + @options = Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new } + @middleware = ActionDispatch::MiddlewareStack.new + end + end + + def respond_to?(name) + super || name.to_s =~ config_key_regexp + end + + protected + + attr_reader :options + + private + + def method_missing(name, *args, &blk) + if name.to_s =~ config_key_regexp + return $2 == '=' ? @options[$1] = args.first : @options[$1] + end + + super + end + + def config_key_regexp + bits = config_keys.map { |n| Regexp.escape(n.to_s) }.join('|') + /^(#{bits})(?:=)?$/ + end + + def config_keys + ([ :active_support, :action_view ] + + Railtie.plugin_names).map { |n| n.to_s }.uniq + end + end + + class Configuration < Railtie::Configuration + attr_accessor :after_initialize_blocks, :cache_classes, + :consider_all_requests_local, :dependency_loading, :gems, + :load_once_paths, :logger, :metals, :plugins, + :preload_frameworks, :reload_plugins, :serve_static_assets, + :time_zone, :whiny_nils + + attr_writer :cache_store, :controller_paths, + :database_configuration_file, :eager_load_paths, + :i18n, :load_paths, + :log_level, :log_path, :paths, :routes_configuration_file, + :view_path + + def initialize(base = nil) + super @load_once_paths = [] @after_initialize_blocks = [] @dependency_loading = true @serve_static_assets = true - - for framework in frameworks - self.send("#{framework}=", ActiveSupport::OrderedOptions.new) - end - self.active_support = ActiveSupport::OrderedOptions.new end def after_initialize(&blk) @@ -31,7 +78,7 @@ module Rails def root @root ||= begin call_stack = caller.map { |p| p.split(':').first } - root_path = call_stack.detect { |p| p !~ %r[railties/lib/rails] } + root_path = call_stack.detect { |p| p !~ %r[railties/lib/rails|rack/lib/rack] } root_path = File.dirname(root_path) while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/config.ru") @@ -72,6 +119,13 @@ module Rails end end + def frameworks(*args) + raise "config.frameworks in no longer supported. See the generated" \ + "config/boot.rb for steps on how to limit the frameworks that" \ + "will be loaded" + end + alias frameworks= frameworks + # Enable threaded mode. Allows concurrent requests to controller actions and # multiple database connections. Also disables automatic dependency loading # after boot, and disables reloading code on every request, as these are @@ -80,28 +134,11 @@ module Rails self.preload_frameworks = true self.cache_classes = true self.dependency_loading = false - self.action_controller.allow_concurrency = true - self - end - def framework_paths - paths = %w(railties railties/lib activesupport/lib) - paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view) - - [:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework| - paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework) + if respond_to?(:action_controller) + action_controller.allow_concurrency = true end - - paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) } - end - - def framework_root_path - defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root}/vendor/rails" - end - - def middleware - require 'action_dispatch' - @middleware ||= ActionDispatch::MiddlewareStack.new + self end # Loads and returns the contents of the #database_configuration_file. The @@ -116,6 +153,10 @@ module Rails @routes_configuration_file ||= File.join(root, 'config', 'routes.rb') end + def builtin_routes_configuration_file + @builtin_routes_configuration_file ||= File.join(RAILTIES_PATH, 'builtin', 'routes.rb') + end + def controller_paths @controller_paths ||= begin paths = [File.join(root, 'app', 'controllers')] @@ -190,10 +231,6 @@ module Rails @log_level ||= RAILS_ENV == 'production' ? :info : :debug end - def frameworks - @frameworks ||= [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] - end - def i18n @i18n ||= begin i18n = ActiveSupport::OrderedOptions.new diff --git a/railties/lib/rails/console_app.rb b/railties/lib/rails/console_app.rb index 1ad62e5058..2c4a7a51e8 100644 --- a/railties/lib/rails/console_app.rb +++ b/railties/lib/rails/console_app.rb @@ -27,6 +27,6 @@ end def reload! puts "Reloading..." ActionDispatch::Callbacks.new(lambda {}, true) - ActionController::Routing::Routes.reload + Rails.application.reload_routes! true end diff --git a/railties/lib/rails/core.rb b/railties/lib/rails/core.rb deleted file mode 100644 index a5e51ad04a..0000000000 --- a/railties/lib/rails/core.rb +++ /dev/null @@ -1,73 +0,0 @@ -module Rails - # Needs to be duplicated from Active Support since its needed before Active - # Support is available. Here both Options and Hash are namespaced to prevent - # conflicts with other implementations AND with the classes residing in Active Support. - # --- - # TODO: w0t? - class << self - def application - @@application ||= nil - end - - def application=(application) - @@application = application - end - - # The Configuration instance used to configure the Rails environment - def configuration - application.configuration - end - - def initialize! - application.initialize! - end - - def initialized? - @initialized || false - end - - def initialized=(initialized) - @initialized ||= initialized - end - - def logger - if defined?(RAILS_DEFAULT_LOGGER) - RAILS_DEFAULT_LOGGER - else - nil - end - end - - def backtrace_cleaner - @@backtrace_cleaner ||= begin - # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded - require 'rails/backtrace_cleaner' - Rails::BacktraceCleaner.new - end - end - - def root - application && application.config.root - end - - def env - @_env ||= ActiveSupport::StringInquirer.new(RAILS_ENV) - end - - def cache - RAILS_CACHE - end - - def version - VERSION::STRING - end - - def public_path - @@public_path ||= self.root ? File.join(self.root, "public") : "public" - end - - def public_path=(path) - @@public_path = path - end - end -end
\ No newline at end of file diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 19412c259e..3713a38b33 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -1,15 +1,16 @@ -activesupport_path = "#{File.dirname(__FILE__)}/../../../activesupport/lib" -$LOAD_PATH.unshift(activesupport_path) if File.directory?(activesupport_path) +activesupport_path = File.expand_path('../../../../activesupport/lib', __FILE__) +$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) + require 'active_support' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/metaclass' -require 'active_support/core_ext/array' -require 'active_support/core_ext/hash' +require 'active_support/core_ext/array/extract_options' +require 'active_support/core_ext/hash/deep_merge' require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/string/inflections' # TODO: Do not always push on vendored thor -$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.12.0/lib") +$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.12.3/lib") require 'rails/generators/base' require 'rails/generators/named_base' @@ -86,28 +87,16 @@ module Rails @options ||= DEFAULT_OPTIONS.dup end - # We have two scenarios here: when rubygems is loaded and when bundler is - # being used. If rubygems is loaded, we get all generators paths from loaded - # specs. Otherwise we just have to look into vendor/gems/gems. - # - def self.gems_generators_paths - paths = [] - - if defined?(Gem) && Gem.respond_to?(:loaded_specs) - Gem.loaded_specs.each do |name, spec| - generator_path = File.join(spec.full_gem_path, "lib/generators") - paths << generator_path if File.exist?(generator_path) - end + def self.gems_generators_paths #:nodoc: + return [] unless defined?(Gem) && Gem.respond_to?(:loaded_specs) + Gem.loaded_specs.inject([]) do |paths, (name, spec)| + paths += Dir[File.join(spec.full_gem_path, "lib/{generators,rails_generators}")] end - - paths end - # Load paths from plugin. - # - def self.plugins_generators_paths - return [] unless Rails.root - Dir[File.join(Rails.root, "vendor", "plugins", "*", "lib", "generators")] + def self.plugins_generators_paths #:nodoc: + return [] unless defined?(Rails.root) && Rails.root + Dir[File.join(Rails.root, "vendor", "plugins", "*", "lib", "{generators,rails_generators}")] end # Hold configured generators fallbacks. If a plugin developer wants a @@ -128,11 +117,15 @@ module Rails end # Remove the color from output. - # def self.no_color! Thor::Base.shell = Thor::Shell::Basic end + # Track all generators subclasses. + def self.subclasses + @subclasses ||= [] + end + # Generators load paths used on lookup. The lookup happens as: # # 1) lib generators @@ -147,8 +140,8 @@ module Rails def self.load_paths @load_paths ||= begin paths = [] - paths << File.join(Rails.root, "lib", "generators") if Rails.root - paths << File.join(Thor::Util.user_home, ".rails", "generators") + paths += Dir[File.join(Rails.root, "lib", "{generators,rails_generators}")] if defined?(Rails.root) && Rails.root + paths += Dir[File.join(Thor::Util.user_home, ".rails", "{generators,rails_generators}")] paths += self.plugins_generators_paths paths += self.gems_generators_paths paths << File.expand_path(File.join(File.dirname(__FILE__), "generators")) @@ -158,18 +151,10 @@ module Rails end load_paths # Cache load paths. Needed to avoid __FILE__ pointing to wrong paths. - # Rails finds namespaces exactly as thor, with three conveniences: + # Rails finds namespaces similar to thor, it only adds one rule: # - # 1) If your generator name ends with generator, as WebratGenerator, it sets - # its namespace to "webrat", so it can be invoked as "webrat" and not - # "webrat_generator"; - # - # 2) If your generator has a generators namespace, as Rails::Generators::WebratGenerator, - # the namespace is set to "rails:generators:webrat", but Rails allows it - # to be invoked simply as "rails:webrat". The "generators" is added - # automatically when doing the lookup; - # - # 3) Rails looks in load paths and loads the generator just before it's going to be used. + # Generators names must end with "_generator.rb". This is required because Rails + # looks in load paths and loads the generator just before it's going to be used. # # ==== Examples # @@ -177,114 +162,82 @@ module Rails # # Will search for the following generators: # - # "rails:generators:webrat", "webrat:generators:integration", "webrat" - # - # On the other hand, if "rails:webrat" is given, it will search for: + # "rails:webrat", "webrat:integration", "webrat" # - # "rails:generators:webrat", "rails:webrat" - # - # Notice that the "generators" namespace is handled automatically by Rails, - # so you don't need to type it when you want to invoke a generator in specific. + # Notice that "rails:generators:webrat" could be loaded as well, what + # Rails looks for is the first and last parts of the namespace. # def self.find_by_namespace(name, base=nil, context=nil) #:nodoc: - name, attempts = name.to_s, [ ] - - case name.count(':') - when 1 - base, name = name.split(':') - return find_by_namespace(name, base) - when 0 - attempts += generator_names(base, name) if base - attempts += generator_names(name, context) if context - end - - attempts << name - attempts += generator_names(name, name) unless name.include?(?:) - attempts.uniq! - - unloaded = attempts - namespaces - lookup(unloaded) + # Mount regexps to lookup + regexps = [] + regexps << /^#{base}:[\w:]*#{name}$/ if base + regexps << /^#{name}:[\w:]*#{context}$/ if context + regexps << /^[(#{name}):]+$/ + regexps.uniq! + + # Check if generator happens to be loaded + checked = subclasses.dup + klass = find_by_regexps(regexps, checked) + return klass if klass + + # Try to require other generators by looking in load_paths + lookup(name, context) + unchecked = subclasses - checked + klass = find_by_regexps(regexps, unchecked) + return klass if klass + + # Invoke fallbacks + invoke_fallbacks_for(name, base) || invoke_fallbacks_for(context, name) + end - attempts.each do |namespace| - klass = Thor::Util.find_by_namespace(namespace) - return klass if klass + # Tries to find a generator which the namespace match the regexp. + def self.find_by_regexps(regexps, klasses) + klasses.find do |klass| + namespace = klass.namespace + regexps.find { |r| namespace =~ r } end - - invoke_fallbacks_for(name, base) end # Receives a namespace, arguments and the behavior to invoke the generator. # It's used as the default entry point for generate, destroy and update # commands. - # def self.invoke(namespace, args=ARGV, config={}) - if klass = find_by_namespace(namespace, "rails") + names = namespace.to_s.split(':') + + if klass = find_by_namespace(names.pop, names.shift || "rails") args << "--help" if klass.arguments.any? { |a| a.required? } && args.empty? - klass.start args, config + klass.start(args, config) else puts "Could not find generator #{namespace}." end end # Show help message with available generators. - # def self.help - rails = Rails::Generators.builtin.map do |group, name| - name if group == "rails" - end - rails.compact! - rails.sort! - - puts "Please select a generator." - puts "Builtin: #{rails.join(', ')}." - - # Load paths and remove builtin - paths, others = load_paths.dup, [] - paths.pop - - paths.each do |path| - tail = [ "*", "*", "*_generator.rb" ] - - until tail.empty? - others += Dir[File.join(path, *tail)].collect do |file| - name = file.split('/')[-tail.size, 2] - name.last.sub!(/_generator\.rb$/, '') - name.uniq! - name.join(':') - end - tail.shift - end - end + builtin = Rails::Generators.builtin.each { |n| n.sub!(/^rails:/, '') } + builtin.sort! + lookup("*") + others = subclasses.map{ |k| k.namespace.gsub(':generators:', ':') } + others -= Rails::Generators.builtin others.sort! + + puts "Please select a generator." + puts "Builtin: #{builtin.join(', ')}." puts "Others: #{others.join(', ')}." unless others.empty? end protected - # Return all defined namespaces. - # - def self.namespaces #:nodoc: - Thor::Base.subclasses.map { |klass| klass.namespace } - end - - # Keep builtin generators in an Array[Array[group, name]]. - # + # Keep builtin generators in an Array. def self.builtin #:nodoc: Dir[File.dirname(__FILE__) + '/generators/*/*'].collect do |file| - file.split('/')[-2, 2] + file.split('/')[-2, 2].join(':') end end - # By default, Rails strips the generator namespace to make invocations - # easier. This method generaters the both possibilities names. - def self.generator_names(first, second) - [ "#{first}:generators:#{second}", "#{first}:#{second}" ] - end - - # Try callbacks for the given base. - # - def self.invoke_fallbacks_for(name, base) + # Try fallbacks for the given base. + def self.invoke_fallbacks_for(name, base) #:nodoc: return nil unless base && fallbacks[base.to_sym] invoked_fallbacks = [] @@ -301,10 +254,10 @@ module Rails # Receives namespaces in an array and tries to find matching generators # in the load path. - # - def self.lookup(attempts) #:nodoc: - attempts = attempts.map { |a| "#{a.split(":").last}_generator" }.uniq - attempts = "{#{attempts.join(',')}}.rb" + def self.lookup(*attempts) #:nodoc: + attempts.compact! + attempts.uniq! + attempts = "{#{attempts.join(',')}}_generator.rb" self.load_paths.each do |path| Dir[File.join(path, '**', attempts)].each do |file| diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 8677bf283b..f95b15acce 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -104,7 +104,7 @@ module Rails # file in config/environments. # def environment(data=nil, options={}, &block) - sentinel = "Rails::Initializer.run do |config|" + sentinel = /class [a-z_:]+ < Rails::Application/i data = block.call if !data && block_given? in_root do @@ -269,11 +269,11 @@ module Rails # # === Example # - # route "map.root :controller => :welcome" + # route "root :to => 'welcome'" # def route(routing_code) log :route, routing_code - sentinel = "ActionController::Routing::Routes.draw do |map|" + sentinel = "routes.draw do |map|" in_root do inject_into_file 'config/routes.rb', "\n #{routing_code}\n", { :after => sentinel, :verbose => false } diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index 226ae63963..5e8c2730fd 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -76,17 +76,18 @@ module Rails # # The controller generator will then try to invoke the following generators: # - # "rails:generators:test_unit", "test_unit:generators:controller", "test_unit" + # "rails:test_unit", "test_unit:controller", "test_unit" # - # In this case, the "test_unit:generators:controller" is available and is - # invoked. This allows any test framework to hook into Rails as long as it - # provides any of the hooks above. + # Notice that "rails:generators:test_unit" could be loaded as well, what + # Rails looks for is the first and last parts of the namespace. This is what + # allows any test framework to hook into Rails as long as it provides any + # of the hooks above. # # ==== Options # - # This lookup can be customized with two options: :base and :as. The first - # is the root module value and in the example above defaults to "rails". - # The later defaults to the generator name, without the "Generator" ending. + # The first and last part used to find the generator to be invoked are + # guessed based on class invokes hook_for, as noticed in the example above. + # This can be customized with two options: :base and :as. # # Let's suppose you are creating a generator that needs to invoke the # controller generator from test unit. Your first attempt is: @@ -97,7 +98,7 @@ module Rails # # The lookup in this case for test_unit as input is: # - # "test_unit:generators:awesome", "test_unit" + # "test_unit:awesome", "test_unit" # # Which is not the desired the lookup. You can change it by providing the # :as option: @@ -108,18 +109,18 @@ module Rails # # And now it will lookup at: # - # "test_unit:generators:awesome", "test_unit" + # "test_unit:controller", "test_unit" # # Similarly, if you want it to also lookup in the rails namespace, you just # need to provide the :base value: # # class AwesomeGenerator < Rails::Generators::Base - # hook_for :test_framework, :base => :rails, :as => :controller + # hook_for :test_framework, :in => :rails, :as => :controller # end # # And the lookup is exactly the same as previously: # - # "rails:generators:test_unit", "test_unit:generators:controller", "test_unit" + # "rails:test_unit", "test_unit:controller", "test_unit" # # ==== Switches # @@ -151,11 +152,11 @@ module Rails # ==== Custom invocations # # You can also supply a block to hook_for to customize how the hook is - # going to be invoked. The block receives two parameters, an instance + # going to be invoked. The block receives two arguments, an instance # of the current class and the klass to be invoked. # # For example, in the resource generator, the controller should be invoked - # with a pluralized class name. By default, it is invoked with the same + # with a pluralized class name. But by default it is invoked with the same # name as the resource generator, which is singular. To change this, we # can give a block to customize how the controller can be invoked. # @@ -178,11 +179,11 @@ module Rails end unless class_options.key?(name) - class_option name, defaults.merge!(options) + class_option(name, defaults.merge!(options)) end hooks[name] = [ in_base, as_hook ] - invoke_from_option name, options, &block + invoke_from_option(name, options, &block) end end @@ -193,7 +194,7 @@ module Rails # remove_hook_for :orm # def self.remove_hook_for(*names) - remove_invocation *names + remove_invocation(*names) names.each do |name| hooks.delete(name) @@ -219,12 +220,16 @@ module Rails # and can point to wrong directions when inside an specified directory. base.source_root - if base.name && base.name !~ /Base$/ && base.base_name && base.generator_name && defined?(Rails.root) && Rails.root - path = File.expand_path(File.join(Rails.root, 'lib', 'templates')) - if base.name.include?('::') - base.source_paths << File.join(path, base.base_name, base.generator_name) - else - base.source_paths << File.join(path, base.generator_name) + if base.name && base.name !~ /Base$/ + Rails::Generators.subclasses << base + + if defined?(Rails.root) && Rails.root + path = File.expand_path(File.join(Rails.root, 'lib', 'templates')) + if base.name.include?('::') + base.source_paths << File.join(path, base.base_name, base.generator_name) + else + base.source_paths << File.join(path, base.generator_name) + end end end end @@ -267,7 +272,7 @@ module Rails # parameters. # def invoked?(args) - args.last.is_a?(Hash) && args.last.key?(:invocations) + args.last.is_a?(Hash) && (args.last.key?(:invocations) || args.last.key?(:destination_root)) end # Use Rails default banner. @@ -290,12 +295,10 @@ module Rails # Rails::Generators::MetalGenerator will return "metal" as generator name. # def self.generator_name - if name - @generator_name ||= begin - if klass_name = name.to_s.split('::').last - klass_name.sub!(/Generator$/, '') - klass_name.underscore - end + @generator_name ||= begin + if generator = name.to_s.split('::').last + generator.sub!(/Generator$/, '') + generator.underscore end end end @@ -339,6 +342,7 @@ module Rails # def self.prepare_for_invocation(name, value) #:nodoc: if value && constants = self.hooks[name] + value = name if TrueClass === value Rails::Generators.find_by_namespace(value, *constants) else super diff --git a/railties/lib/rails/generators/erb/scaffold/templates/layout.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/layout.html.erb index 6460e5b599..51c4ad0e2e 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/layout.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/layout.html.erb @@ -7,7 +7,7 @@ </head> <body> -<p class="notice"><%%= flash[:notice] %></p> +<p class="notice"><%%= notice %></p> <%%= yield %> diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 2bcea4bc8f..fc6a3cdee8 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -3,6 +3,10 @@ require 'active_support/secure_random' require 'rails/version' unless defined?(Rails::VERSION) module Rails::Generators + # We need to store the RAILS_DEV_PATH in a constant, otherwise the path + # can change in Ruby 1.8.7 when we FileUtils.cd. + RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__)) + class AppGenerator < Base DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) add_shebang_option! @@ -15,17 +19,25 @@ module Rails::Generators class_option :template, :type => :string, :aliases => "-m", :desc => "Path to an application template (can be a filesystem path or URL)." + class_option :dev, :type => :boolean, :default => false, + :desc => "Setup the application with Gemfile pointing to your Rails checkout" + + class_option :edge, :type => :boolean, :default => false, + :desc => "Setup the application with Gemfile pointing to Rails repository" + class_option :skip_activerecord, :type => :boolean, :aliases => "-O", :default => false, - :desc => "Skip ActiveRecord files" + :desc => "Skip ActiveRecord files" class_option :skip_testunit, :type => :boolean, :aliases => "-T", :default => false, - :desc => "Skip TestUnit files" + :desc => "Skip TestUnit files" class_option :skip_prototype, :type => :boolean, :aliases => "-J", :default => false, - :desc => "Skip Prototype files" + :desc => "Skip Prototype files" + + class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, + :desc => "Skip Git ignores and keeps" - # Add Rails options - # + # Add bin/rails options class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, :desc => "Show Rails version number and quit" @@ -34,23 +46,25 @@ module Rails::Generators def initialize(*args) super - if !options[:no_activerecord] && !DATABASES.include?(options[:database]) + if !options[:skip_activerecord] && !DATABASES.include?(options[:database]) raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}." end end def create_root self.destination_root = File.expand_path(app_path, destination_root) - empty_directory '.' + valid_app_const? + empty_directory '.' set_default_accessors! FileUtils.cd(destination_root) end def create_root_files - copy_file "Rakefile" copy_file "README" - copy_file "config.ru" + copy_file "gitignore", ".gitignore" unless options[:skip_git] + template "Rakefile" + template "config.ru" template "Gemfile" end @@ -62,9 +76,9 @@ module Rails::Generators empty_directory "config" inside "config" do - copy_file "routes.rb" - template "application.rb" - template "environment.rb" + template "routes.rb" + template "application.rb" + template "environment.rb" directory "environments" directory "initializers" @@ -91,7 +105,7 @@ module Rails::Generators def create_lib_files empty_directory "lib" - empty_directory "lib/tasks" + empty_directory_with_gitkeep "lib/tasks" end def create_log_files @@ -114,7 +128,7 @@ module Rails::Generators end def create_public_stylesheets_files - directory "public/stylesheets" + empty_directory_with_gitkeep "public/stylesheets" end def create_prototype_files @@ -123,10 +137,10 @@ module Rails::Generators end def create_script_files - directory "script" do |file| - prepend_file file, "#{shebang}\n", :verbose => false - chmod file, 0755, :verbose => false + directory "script" do |content| + "#{shebang}\n" + content end + chmod "script", 0755, :verbose => false end def create_test_files @@ -139,13 +153,13 @@ module Rails::Generators inside "tmp" do %w(sessions sockets cache pids).each do |dir| - empty_directory dir + empty_directory(dir) end end end def create_vendor_files - empty_directory "vendor/plugins" + empty_directory_with_gitkeep "vendor/plugins" end def apply_rails_template @@ -155,7 +169,6 @@ module Rails::Generators end protected - attr_accessor :rails_template def set_default_accessors! @@ -172,7 +185,6 @@ module Rails::Generators end # Define file as an alias to create_file for backwards compatibility. - # def file(*args, &block) create_file(*args, &block) end @@ -181,10 +193,25 @@ module Rails::Generators @app_name ||= File.basename(destination_root) end + def app_const + @app_const ||= "#{app_name.gsub(/\W/, '_').squeeze('_').classify}::Application" + end + + def valid_app_const? + case app_const + when /^\d/ + raise Error, "Invalid application name #{app_name}. Please give a name which does not start with numbers." + end + end + def app_secret ActiveSupport::SecureRandom.hex(64) end + def dev_or_edge? + options.dev? || options.edge? + end + def self.banner "#{$0} #{self.arguments.map(&:usage).join(' ')} [options]" end @@ -202,5 +229,10 @@ module Rails::Generators "/opt/lampp/var/mysql/mysql.sock" # xampp for linux ].find { |f| File.exist?(f) } unless RUBY_PLATFORM =~ /(:?mswin|mingw)/ end + + def empty_directory_with_gitkeep(destination, config = {}) + empty_directory(destination, config) + create_file("#{destination}/.gitkeep") unless options[:skip_git] + end end end diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 8e851a64e7..59c6d333e2 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -1,9 +1,14 @@ # Edit this Gemfile to bundle your application's dependencies. - +<% if !dev_or_edge? %> gem "rails", "<%= Rails::VERSION::STRING %>" +<% end -%> ## Bundle edge rails: -# gem "rails", :git => "git://github.com/rails/rails.git" +<%- if options.dev? -%> +gem "rails", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" +<%- else -%> +<%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git" +<%- end -%> ## Bundle the gems you use: # gem "bj" diff --git a/railties/lib/rails/generators/rails/app/templates/Rakefile b/railties/lib/rails/generators/rails/app/templates/Rakefile index 6b6d07e8cc..c19ad0e945 100755 --- a/railties/lib/rails/generators/rails/app/templates/Rakefile +++ b/railties/lib/rails/generators/rails/app/templates/Rakefile @@ -7,4 +7,4 @@ require 'rake' require 'rake/testtask' require 'rake/rdoctask' -require 'rails/tasks' +<%= app_const %>.load_tasks diff --git a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb index 6635a3f487..9889b52893 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb +++ b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb @@ -2,9 +2,7 @@ # Likewise, all the methods added will be available for all controllers. class ApplicationController < ActionController::Base - helper :all # include all helpers, all the time - protect_from_forgery # See ActionController::RequestForgeryProtection for details - - # Scrub sensitive parameters from your log - # filter_parameter_logging :password + helper :all + protect_from_forgery + filter_parameter_logging :password end diff --git a/railties/lib/rails/generators/rails/app/templates/config.ru b/railties/lib/rails/generators/rails/app/templates/config.ru index 509a0da5b7..acb8435446 100644 --- a/railties/lib/rails/generators/rails/app/templates/config.ru +++ b/railties/lib/rails/generators/rails/app/templates/config.ru @@ -2,4 +2,4 @@ require ::File.expand_path('../config/environment', __FILE__) # Dispatch the request -run Rails.application +run <%= app_const %>.instance 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 8008c6ba07..4097f766a6 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -1,41 +1,35 @@ require File.expand_path('../boot', __FILE__) -Rails::Initializer.run do |config| - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - - # Add additional load paths for your own custom dirs - # config.load_paths += %W( #{root}/extras ) - - # Only load the plugins named here, in the order given (default is alphabetical). - # :all can be used as a placeholder for all plugins not explicitly named - # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - - # Skip frameworks you're not going to use. To use Rails without a database, - # you must remove the Active Record framework. -<% if options[:skip_activerecord] -%> - config.frameworks -= [ :active_record ] -<% else -%> - # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] - - # Activate observers that should always be running - # config.active_record.observers = :cacher, :garbage_collector, :forum_observer -<% end -%> - - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. - config.time_zone = 'UTC' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')] - # config.i18n.default_locale = :de - - # Configure generators values. Many other options are available, be sure to - # check the documentation. - # config.generators do |g| - # g.orm :active_record - # g.template_engine :erb - # g.test_framework :test_unit, :fixture => true - # end +module <%= app_name.classify %> + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Add additional load paths for your own custom dirs + # config.load_paths += %W( #{config.root}/extras ) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. + config.time_zone = 'UTC' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')] + # config.i18n.default_locale = :de + + # Configure generators values. Many other options are available, be sure to + # check the documentation. + # config.generators do |g| + # g.orm :active_record + # g.template_engine :erb + # g.test_framework :test_unit, :fixture => true + # end + end end diff --git a/railties/lib/rails/generators/rails/app/templates/config/boot.rb b/railties/lib/rails/generators/rails/app/templates/config/boot.rb index 5aa49ca5e6..6de1725260 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/boot.rb @@ -13,4 +13,13 @@ else require 'rubygems' end -require 'rails' +require 'rails/all' +# To pick the frameworks you want, remove 'require "rails/all"' +# and list the framework railties that you want: +# +# require "active_model/railtie" +# require "active_record/railtie" +# require "action_controller/railtie" +# require "action_view/railtie" +# require "action_mailer/railtie" +# require "active_resource/railtie"
\ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/environment.rb b/railties/lib/rails/generators/rails/app/templates/config/environment.rb index 0bb191f205..1684986a59 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environment.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/environment.rb @@ -2,4 +2,4 @@ require File.expand_path('../application', __FILE__) # Initialize the rails application -Rails.initialize! +<%= app_const %>.initialize! diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb deleted file mode 100644 index 85c9a6080e..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb +++ /dev/null @@ -1,17 +0,0 @@ -# Settings specified here will take precedence over those in config/environment.rb - -# In the development environment your application's code is reloaded on -# every request. This slows down response time but is perfect for development -# since you don't have to restart the webserver when you make code changes. -config.cache_classes = false - -# Log error messages when you accidentally call methods on nil. -config.whiny_nils = true - -# Show full error reports and disable caching -config.action_controller.consider_all_requests_local = true -config.action_view.debug_rjs = true -config.action_controller.perform_caching = false - -# Don't care if the mailer can't send -config.action_mailer.raise_delivery_errors = false
\ No newline at end of file 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 new file mode 100644 index 0000000000..b10103b436 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -0,0 +1,19 @@ +<%= app_const %>.configure do + # Settings specified here will take precedence over those in config/environment.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the webserver when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.action_controller.consider_all_requests_local = true + config.action_view.debug_rjs = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false +end
\ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb deleted file mode 100644 index 377b9207c7..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb +++ /dev/null @@ -1,31 +0,0 @@ -# Settings specified here will take precedence over those in config/environment.rb - -# The production environment is meant for finished, "live" apps. -# Code is not reloaded between requests -config.cache_classes = true - -# Full error reports are disabled and caching is turned on -config.action_controller.consider_all_requests_local = false -config.action_controller.perform_caching = true - -# See everything in the log (default is :info) -# config.log_level = :debug - -# Use a different logger for distributed setups -# config.logger = SyslogLogger.new - -# Use a different cache store in production -# config.cache_store = :mem_cache_store - -# Disable Rails's static asset server -# In production, Apache or nginx will already do this -config.serve_static_assets = false - -# Enable serving of images, stylesheets, and javascripts from an asset server -# config.action_controller.asset_host = "http://assets.example.com" - -# Disable delivery errors, bad email addresses will be ignored -# config.action_mailer.raise_delivery_errors = false - -# Enable threaded mode -# config.threadsafe! 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 new file mode 100644 index 0000000000..543a40108c --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -0,0 +1,33 @@ +<%= app_const %>.configure do + # Settings specified here will take precedence over those in config/environment.rb + + # The production environment is meant for finished, "live" apps. + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.action_controller.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Disable Rails's static asset server + # In production, Apache or nginx will already do this + config.serve_static_assets = false + + # Enable serving of images, stylesheets, and javascripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! +end
\ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb deleted file mode 100644 index 496eb9572b..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb +++ /dev/null @@ -1,27 +0,0 @@ -# Settings specified here will take precedence over those in config/environment.rb - -# The test environment is used exclusively to run your application's -# test suite. You never need to work with it otherwise. Remember that -# your test database is "scratch space" for the test suite and is wiped -# and recreated between test runs. Don't rely on the data there! -config.cache_classes = true - -# Log error messages when you accidentally call methods on nil. -config.whiny_nils = true - -# Show full error reports and disable caching -config.action_controller.consider_all_requests_local = true -config.action_controller.perform_caching = false - -# Disable request forgery protection in test environment -config.action_controller.allow_forgery_protection = false - -# Tell Action Mailer not to deliver emails to the real world. -# The :test delivery method accumulates sent emails in the -# ActionMailer::Base.deliveries array. -config.action_mailer.delivery_method = :test - -# Use SQL instead of Active Record's schema dumper when creating the test database. -# This is necessary if your schema can't be completely dumped by the schema dumper, -# like if you have constraints or database-specific column types -# config.active_record.schema_format = :sql
\ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt new file mode 100644 index 0000000000..428fa35633 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt @@ -0,0 +1,29 @@ +<%= app_const %>.configure do + # Settings specified here will take precedence over those in config/environment.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.action_controller.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql +end
\ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt new file mode 100644 index 0000000000..9f05cd5a31 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key 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, +# no regular words or you'll be exposed to dictionary attacks. +ActionController::Base.cookie_verifier_secret = '<%= app_secret %>'; diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index ea14ce1bfc..d6c0365c04 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -1,43 +1,58 @@ -ActionController::Routing::Routes.draw do |map| - # The priority is based upon order of creation: first created -> highest priority. +<%= app_const %>.routes.draw do |map| + # The priority is based upon order of creation: + # first created -> highest priority. # Sample of regular route: - # map.connect 'products/:id', :controller => 'catalog', :action => 'view' + # match 'products/:id' => 'catalog#view' # Keep in mind you can assign values other than :controller and :action # Sample of named route: - # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase' + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase # This route can be invoked with purchase_url(:id => product.id) # Sample resource route (maps HTTP verbs to controller actions automatically): - # map.resources :products + # resources :products # Sample resource route with options: - # map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get } + # resources :products do + # member do + # get :short + # post :toggle + # end + # + # collection do + # get :sold + # end + # end # Sample resource route with sub-resources: - # map.resources :products, :has_many => [ :comments, :sales ], :has_one => :seller - + # resources :products do + # resources :comments, :sales + # resource :seller + # end + # Sample resource route with more complex sub-resources - # map.resources :products do |products| - # products.resources :comments - # products.resources :sales, :collection => { :recent => :get } + # resources :products do + # resources :comments + # resources :sales do + # get :recent, :on => :collection + # end # end # Sample resource route within a namespace: - # map.namespace :admin do |admin| - # # Directs /admin/products/* to Admin::ProductsController (app/controllers/admin/products_controller.rb) - # admin.resources :products + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products # end - # You can have the root of your site routed with map.root -- just remember to delete public/index.html. - # map.root :controller => "welcome" + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + # root :to => "welcome#index" # See how all your routes lay out with "rake routes" - # Install the default routes as the lowest priority. - # Note: These default routes make all actions in every controller accessible via GET requests. You should - # consider removing or commenting them out if you're using named routes and resources. - map.connect ':controller/:action/:id' - map.connect ':controller/:action/:id.:format' + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id(.:format)))' end diff --git a/railties/lib/rails/generators/rails/app/templates/gitignore b/railties/lib/rails/generators/rails/app/templates/gitignore new file mode 100644 index 0000000000..a4f05d101d --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/gitignore @@ -0,0 +1,3 @@ +db/*.sqlite3 +log/*.log +tmp/**/* diff --git a/railties/lib/rails/generators/rails/app/templates/script/console b/railties/lib/rails/generators/rails/app/templates/script/console.tt index 20aa799d2f..9ddd4cfe62 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/console +++ b/railties/lib/rails/generators/rails/app/templates/script/console.tt @@ -1,2 +1,3 @@ require File.expand_path('../../config/application', __FILE__) require 'rails/commands/console' +Rails::Console.start(<%= app_const %>.instance) diff --git a/railties/lib/rails/generators/rails/app/templates/script/dbconsole b/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt index e6a1c59394..96e0bc191b 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/dbconsole +++ b/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt @@ -1,2 +1,3 @@ require File.expand_path('../../config/application', __FILE__) require 'rails/commands/dbconsole' +Rails::DBConsole.start(<%= app_const %>.instance) diff --git a/railties/lib/rails/generators/rails/app/templates/script/server b/railties/lib/rails/generators/rails/app/templates/script/server deleted file mode 100755 index a7aaee2953..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/script/server +++ /dev/null @@ -1,2 +0,0 @@ -require File.expand_path('../../config/application', __FILE__) -require 'rails/commands/server' diff --git a/railties/lib/rails/generators/rails/app/templates/script/server.tt b/railties/lib/rails/generators/rails/app/templates/script/server.tt new file mode 100755 index 0000000000..4fd0cc7832 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/script/server.tt @@ -0,0 +1,5 @@ +require File.expand_path('../../config/boot', __FILE__) +require 'rails/commands/server' + +Dir.chdir(File.expand_path('../..', __FILE__)) +Rails::Server.start diff --git a/railties/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt b/railties/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt index 675f00043f..d8757460e4 100644 --- a/railties/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt +++ b/railties/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt @@ -1,5 +1,5 @@ class <%= class_name %>Generator < Rails::Generators::NamedBase def self.source_root - @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates')) + @source_root ||= File.expand_path('../templates', __FILE__) end end diff --git a/railties/lib/rails/generators/rails/plugin/templates/Rakefile b/railties/lib/rails/generators/rails/plugin/templates/Rakefile index 85e8ff1834..23c2245a41 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/Rakefile +++ b/railties/lib/rails/generators/rails/plugin/templates/Rakefile @@ -10,7 +10,6 @@ Rake::TestTask.new(:test) do |t| t.libs << 'lib' t.libs << 'test' t.pattern = 'test/**/*_test.rb' - t.verbose = true end desc 'Generate documentation for the <%= file_name %> plugin.' diff --git a/railties/lib/rails/generators/rails/resource/resource_generator.rb b/railties/lib/rails/generators/rails/resource/resource_generator.rb index e49f9aea1b..a89ce7faed 100644 --- a/railties/lib/rails/generators/rails/resource/resource_generator.rb +++ b/railties/lib/rails/generators/rails/resource/resource_generator.rb @@ -16,7 +16,7 @@ module Rails class_option :singleton, :type => :boolean, :desc => "Supply to create a singleton controller" def add_resource_route - route "map.resource#{:s unless options[:singleton]} :#{pluralize?(file_name)}" + route "resource#{:s unless options[:singleton]} :#{pluralize?(file_name)}" end protected diff --git a/railties/lib/rails/generators/rails/scaffold/USAGE b/railties/lib/rails/generators/rails/scaffold/USAGE index 71edd2f469..530ccdaf0a 100644 --- a/railties/lib/rails/generators/rails/scaffold/USAGE +++ b/railties/lib/rails/generators/rails/scaffold/USAGE @@ -17,7 +17,7 @@ Description: For example, 'scaffold post title:string body:text published:boolean' gives you a model with those three attributes, a controller that handles the create/show/update/destroy, forms to create and edit your posts, and - an index that lists them all, as well as a map.resources :posts + an index that lists them all, as well as a resources :posts declaration in config/routes.rb. If you want to remove all the generated files, run diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index 3cc8bbf8e7..874e96a2b4 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -46,8 +46,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| if @<%= orm_instance.save %> - flash[:notice] = '<%= class_name %> was successfully created.' - format.html { redirect_to(@<%= file_name %>) } + format.html { redirect_to(@<%= file_name %>, :notice => '<%= class_name %> was successfully created.') } format.xml { render :xml => @<%= file_name %>, :status => :created, :location => @<%= file_name %> } else format.html { render :action => "new" } @@ -63,8 +62,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| if @<%= orm_instance.update_attributes("params[:#{file_name}]") %> - flash[:notice] = '<%= class_name %> was successfully updated.' - format.html { redirect_to(@<%= file_name %>) } + format.html { redirect_to(@<%= file_name %>, :notice => '<%= class_name %> was successfully updated.') } format.xml { head :ok } else format.html { render :action => "edit" } diff --git a/railties/lib/rails/generators/test_case.rb b/railties/lib/rails/generators/test_case.rb new file mode 100644 index 0000000000..643d7856c5 --- /dev/null +++ b/railties/lib/rails/generators/test_case.rb @@ -0,0 +1,239 @@ +require 'active_support/test_case' +require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/hash/reverse_merge' +require 'rails/generators' +require 'fileutils' + +module Rails + module Generators + # Disable color in output. Easier to debug. + no_color! + + # This class provides a TestCase for testing generators. To setup, you need + # just to configure the destination and set which generator is being tested: + # + # class AppGeneratorTest < Rails::Generators::TestCase + # tests AppGenerator + # destination File.expand_path("../tmp", File.dirname(__FILE__)) + # end + # + # If you want to ensure your destination root is clean before running each test, + # you can set a setup callback: + # + # class AppGeneratorTest < Rails::Generators::TestCase + # tests AppGenerator + # destination File.expand_path("../tmp", File.dirname(__FILE__)) + # setup :prepare_destination + # end + # + class TestCase < ActiveSupport::TestCase + include FileUtils + + extlib_inheritable_accessor :destination_root, :current_path, :generator_class, + :default_arguments, :instance_writer => false + + # 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 = [] + + setup :destination_root_is_set?, :ensure_current_path + teardown :ensure_current_path + + # 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-activerecord) + # + 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 + + # Captures the given stream and returns it: + # + # stream = capture(:stdout){ puts "Cool" } + # stream #=> "Cool\n" + # + def capture(stream) + begin + stream = stream.to_s + eval "$#{stream} = StringIO.new" + yield + result = eval("$#{stream}").string + ensure + eval("$#{stream} = #{stream.upcase}") + end + + result + end + alias :silence :capture + + # 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/controller/products_controller.rb" do |controller| + # assert_instance_method :index, content 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 file does not exist. 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_file "config/random.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/controller/products_controller.rb" do |controller| + # assert_instance_method :index, content do |index| + # assert_match /Product\.all/, index + # end + # end + # + def assert_instance_method(method, content) + assert content =~ /def #{method}(\(.+\))?(.*?)\n end/m, "Expected to have method #{method}" + yield $2.strip if block_given? + end + alias :assert_method :assert_instance_method + + # 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 activerecord" do + # run_generator %w(myapp --skip-activerecord) + # 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 + + 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 + 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
\ No newline at end of file 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 c21035113e..a30132bc99 100644 --- a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml +++ b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml @@ -11,9 +11,13 @@ two: <%= attribute.name %>: <%= attribute.default %> <% end -%> <% else -%> -# one: -# column: value +# 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 # -# two: -# column: value -<% end -%> +one: {} +# column: value +# +two: {} +# column: value +<% end -%>
\ No newline at end of file diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb index 3866b856b2..8fcb254590 100644 --- a/railties/lib/rails/initializable.rb +++ b/railties/lib/rails/initializable.rb @@ -5,7 +5,7 @@ module Rails end class Initializer - attr_reader :name, :before, :after, :global, :block + attr_reader :name, :block def initialize(name, context, options, &block) @name, @context, @options, @block = name, context, options, block @@ -62,7 +62,7 @@ module Rails end def run_initializers(*args) - return if @ran + return if instance_variable_defined?(:@ran) initializers.each do |initializer| initializer.run(*args) end @@ -93,6 +93,7 @@ module Rails end def initializer(name, opts = {}, &blk) + raise ArgumentError, "A block must be passed when defining an initializer" unless blk @initializers ||= [] @initializers << Initializer.new(name, nil, opts, &blk) end @@ -106,26 +107,4 @@ module Rails end end end - - include Initializable - - # Check for valid Ruby version (1.8.2 or 1.8.4 or higher). This is done in an - # external file, so we can use it from the `rails` program as well without duplication. - initializer :check_ruby_version, :global => true do - require 'rails/ruby_version_check' - end - - # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the - # multibyte safe operations. Plugin authors supporting other encodings - # should override this behaviour and set the relevant +default_charset+ - # on ActionController::Base. - # - # For Ruby 1.9, UTF-8 is the default internal and external encoding. - initializer :initialize_encoding, :global => true do - if RUBY_VERSION < '1.9' - $KCODE='u' - else - Encoding.default_external = Encoding::UTF_8 - end - end end
\ No newline at end of file diff --git a/railties/lib/rails/initializer.rb b/railties/lib/rails/initializer.rb deleted file mode 100644 index 44d04688c8..0000000000 --- a/railties/lib/rails/initializer.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "rails" # In case people require this file directly - -RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) - -module Rails - class Initializer - class Error < StandardError ; end - def self.run(initializer = nil, config = nil) - if initializer - # Deprecated - else - Rails.application = Class.new(Application) - yield Rails.application.config if block_given? - end - end - end -end
\ No newline at end of file diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 86bf032641..9cc6b9c35b 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -1,63 +1,63 @@ module Rails - class Plugin - include Initializable - - class Vendored < Plugin - def self.all(list, paths) - plugins = [] - paths.each do |path| - Dir["#{path}/*"].each do |plugin_path| - plugin = new(plugin_path) - next unless list.include?(plugin.name) || list.include?(:all) - plugins << plugin - end + class Plugin < Railtie + def self.all(list, paths) + plugins = [] + paths.each do |path| + Dir["#{path}/*"].each do |plugin_path| + plugin = new(plugin_path) + next unless list.include?(plugin.name) || list.include?(:all) + plugins << plugin end + end - plugins.sort_by do |p| - [list.index(p.name) || list.index(:all), p.name.to_s] - end + plugins.sort_by do |p| + [list.index(p.name) || list.index(:all), p.name.to_s] end + end - attr_reader :name, :path + attr_reader :name, :path - def initialize(path) - @name = File.basename(path).to_sym - @path = path - end + def initialize(path) + @name = File.basename(path).to_sym + @path = path + end - def load_paths - Dir["#{path}/{lib}", "#{path}/app/{models,controllers,helpers}"] - end + def load_paths + Dir["#{path}/{lib}", "#{path}/app/{models,controllers,helpers}"] + end - initializer :add_to_load_path, :after => :set_autoload_paths do |app| - load_paths.each do |path| - $LOAD_PATH << path - require "active_support/dependencies" + def load_tasks + Dir["#{path}/**/tasks/**/*.rake"].sort.each { |ext| load ext } + end + + initializer :add_to_load_path, :after => :set_autoload_paths do |app| + load_paths.each do |path| + $LOAD_PATH << path + require "active_support/dependencies" - ActiveSupport::Dependencies.load_paths << path + ActiveSupport::Dependencies.load_paths << path - unless app.config.reload_plugins - ActiveSupport::Dependencies.load_once_paths << path - end + unless app.config.reload_plugins + ActiveSupport::Dependencies.load_once_paths << path end end + end - initializer :load_init_rb, :before => :load_application_initializers do |app| - file = "#{@path}/init.rb" - config = app.config - eval File.read(file), binding, file if File.file?(file) - end + initializer :load_init_rb, :before => :load_application_initializers do |app| + file = "#{@path}/init.rb" + config = app.config + eval File.read(file), binding, file if File.file?(file) + end - initializer :add_view_paths, :after => :initialize_framework_views do - ActionController::Base.view_paths.concat ["#{path}/app/views"] if File.directory?("#{path}/app/views") - end + initializer :add_view_paths, :after => :initialize_framework_views do + ActionController::Base.view_paths.concat ["#{path}/app/views"] if File.directory?("#{path}/app/views") + end - initializer :add_routing_file, :after => :initialize_routing do |app| - routing_file = "#{path}/config/routes.rb" - if File.exist?(routing_file) - app.routes.add_configuration_file(routing_file) - app.routes.reload! - end + initializer :add_routing_file, :after => :initialize_routing do |app| + routing_file = "#{path}/config/routes.rb" + if File.exist?(routing_file) + app.route_configuration_files << routing_file + app.reload_routes! end end end diff --git a/railties/lib/rails/rack/debugger.rb b/railties/lib/rails/rack/debugger.rb index aa2711c616..0a7b405553 100644 --- a/railties/lib/rails/rack/debugger.rb +++ b/railties/lib/rails/rack/debugger.rb @@ -4,6 +4,8 @@ module Rails def initialize(app) @app = app + ARGV.clear # clear ARGV so that script/server options aren't passed to IRB + require_library_or_gem 'ruby-debug' ::Debugger.start ::Debugger.settings[:autoeval] = true if ::Debugger.respond_to?(:settings) diff --git a/railties/lib/rails/rack/log_tailer.rb b/railties/lib/rails/rack/log_tailer.rb index a237cee6bc..077311be3c 100644 --- a/railties/lib/rails/rack/log_tailer.rb +++ b/railties/lib/rails/rack/log_tailer.rb @@ -1,12 +1,10 @@ module Rails module Rack class LogTailer - EnvironmentLog = "#{File.expand_path(Rails.root)}/log/#{Rails.env}.log" - def initialize(app, log = nil) @app = app - path = Pathname.new(log || EnvironmentLog).cleanpath + path = Pathname.new(log || "#{File.expand_path(Rails.root)}/log/#{Rails.env}.log").cleanpath @cursor = ::File.size(path) @last_checked = Time.now.to_f diff --git a/railties/lib/rails/rack/static.rb b/railties/lib/rails/rack/static.rb index d6b8face27..ebe8b9e103 100644 --- a/railties/lib/rails/rack/static.rb +++ b/railties/lib/rails/rack/static.rb @@ -1,5 +1,5 @@ require 'action_dispatch' module Rails::Rack - Static = Deprecation::DeprecatedConstantProxy.new('Rails::Rack::Static', ActionDispatch::Static) + Static = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Rails::Rack::Static', ActionDispatch::Static) end diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb new file mode 100644 index 0000000000..ff28ade35d --- /dev/null +++ b/railties/lib/rails/railtie.rb @@ -0,0 +1,43 @@ +module Rails + class Railtie + include Initializable + + def self.plugin_name(plugin_name = nil) + @plugin_name ||= name.demodulize.underscore + @plugin_name = plugin_name if plugin_name + @plugin_name + end + + def self.inherited(klass) + @plugins ||= [] + @plugins << klass unless klass == Plugin + end + + def self.plugins + @plugins + end + + def self.plugin_names + plugins.map { |p| p.plugin_name } + end + + def self.config + Configuration.default + end + + def self.rake_tasks(&blk) + @rake_tasks ||= [] + @rake_tasks << blk if blk + @rake_tasks + end + + def rake_tasks + self.class.rake_tasks + end + + def load_tasks + return unless rake_tasks + rake_tasks.each { |blk| blk.call } + end + end +end diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb index 82113a297c..44c014efe8 100644 --- a/railties/lib/rails/tasks.rb +++ b/railties/lib/rails/tasks.rb @@ -3,7 +3,6 @@ $VERBOSE = nil # Load Rails rakefile extensions %w( annotations - databases documentation framework log @@ -16,8 +15,3 @@ $VERBOSE = nil ).each do |task| load "rails/tasks/#{task}.rake" end - -# Load any custom rakefile extensions -# TODO: Don't hardcode these paths. -Dir["#{Rails.root}/vendor/plugins/*/**/tasks/**/*.rake"].sort.each { |ext| load ext } -Dir["#{Rails.root}/lib/tasks/**/*.rake"].sort.each { |ext| load ext } diff --git a/railties/lib/rails/tasks/databases.rake b/railties/lib/rails/tasks/databases.rake deleted file mode 100644 index a35a6c156b..0000000000 --- a/railties/lib/rails/tasks/databases.rake +++ /dev/null @@ -1,469 +0,0 @@ -namespace :db do - task :load_config => :rails_env do - require 'active_record' - ActiveRecord::Base.configurations = Rails::Configuration.new.database_configuration - end - - namespace :create do - desc 'Create all the local databases defined in config/database.yml' - task :all => :load_config do - ActiveRecord::Base.configurations.each_value do |config| - # Skip entries that don't have a database key, such as the first entry here: - # - # defaults: &defaults - # adapter: mysql - # username: root - # password: - # host: localhost - # - # development: - # database: blog_development - # <<: *defaults - next unless config['database'] - # Only connect to local databases - local_database?(config) { create_database(config) } - end - end - end - - desc 'Create the database defined in config/database.yml for the current RAILS_ENV' - task :create => :load_config do - create_database(ActiveRecord::Base.configurations[RAILS_ENV]) - end - - def create_database(config) - begin - if config['adapter'] =~ /sqlite/ - if File.exist?(config['database']) - $stderr.puts "#{config['database']} already exists" - else - begin - # Create the SQLite database - ActiveRecord::Base.establish_connection(config) - ActiveRecord::Base.connection - rescue - $stderr.puts $!, *($!.backtrace) - $stderr.puts "Couldn't create database for #{config.inspect}" - end - end - return # Skip the else clause of begin/rescue - else - ActiveRecord::Base.establish_connection(config) - ActiveRecord::Base.connection - end - rescue - case config['adapter'] - when 'mysql' - @charset = ENV['CHARSET'] || 'utf8' - @collation = ENV['COLLATION'] || 'utf8_unicode_ci' - creation_options = {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)} - begin - ActiveRecord::Base.establish_connection(config.merge('database' => nil)) - ActiveRecord::Base.connection.create_database(config['database'], creation_options) - ActiveRecord::Base.establish_connection(config) - rescue Mysql::Error => sqlerr - if sqlerr.errno == Mysql::Error::ER_ACCESS_DENIED_ERROR - print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>" - root_password = $stdin.gets.strip - grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \ - "TO '#{config['username']}'@'localhost' " \ - "IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;" - ActiveRecord::Base.establish_connection(config.merge( - 'database' => nil, 'username' => 'root', 'password' => root_password)) - ActiveRecord::Base.connection.create_database(config['database'], creation_options) - ActiveRecord::Base.connection.execute grant_statement - ActiveRecord::Base.establish_connection(config) - else - $stderr.puts sqlerr.error - $stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation}" - $stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['charset'] - end - end - when 'postgresql' - @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8' - begin - ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) - ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding)) - ActiveRecord::Base.establish_connection(config) - rescue - $stderr.puts $!, *($!.backtrace) - $stderr.puts "Couldn't create database for #{config.inspect}" - end - end - else - $stderr.puts "#{config['database']} already exists" - end - end - - namespace :drop do - desc 'Drops all the local databases defined in config/database.yml' - task :all => :load_config do - ActiveRecord::Base.configurations.each_value do |config| - # Skip entries that don't have a database key - next unless config['database'] - begin - # Only connect to local databases - local_database?(config) { drop_database(config) } - rescue Exception => e - puts "Couldn't drop #{config['database']} : #{e.inspect}" - end - end - end - end - - desc 'Drops the database for the current RAILS_ENV' - task :drop => :load_config do - config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] - begin - drop_database(config) - rescue Exception => e - puts "Couldn't drop #{config['database']} : #{e.inspect}" - end - end - - def local_database?(config, &block) - if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank? - yield - else - puts "This task only modifies local databases. #{config['database']} is on a remote host." - end - end - - - desc "Migrate the database through scripts in db/migrate and update db/schema.rb by invoking db:schema:dump. Target specific version with VERSION=x. Turn off output with VERBOSE=false." - task :migrate => :environment do - ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true - ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - namespace :migrate do - desc 'Rollbacks the database one migration and re migrate up. If you want to rollback more than one step, define STEP=x. Target specific version with VERSION=x.' - task :redo => :environment do - if ENV["VERSION"] - Rake::Task["db:migrate:down"].invoke - Rake::Task["db:migrate:up"].invoke - else - Rake::Task["db:rollback"].invoke - Rake::Task["db:migrate"].invoke - end - end - - desc 'Resets your database using your migrations for the current environment' - task :reset => ["db:drop", "db:create", "db:migrate"] - - desc 'Runs the "up" for a given migration VERSION.' - task :up => :environment do - version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:up, "db/migrate/", version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - desc 'Runs the "down" for a given migration VERSION.' - task :down => :environment do - version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:down, "db/migrate/", version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - end - - desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n' - task :rollback => :environment do - step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.rollback('db/migrate/', step) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - desc 'Pushes the schema to the next version. Specify the number of steps with STEP=n' - task :forward => :environment do - step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.forward('db/migrate/', step) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.' - task :reset => [ 'db:drop', 'db:setup' ] - - desc "Retrieves the charset for the current environment's database" - task :charset => :environment do - config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] - case config['adapter'] - when 'mysql' - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.charset - when 'postgresql' - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.encoding - else - puts 'sorry, your database adapter is not supported yet, feel free to submit a patch' - end - end - - desc "Retrieves the collation for the current environment's database" - task :collation => :environment do - config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] - case config['adapter'] - when 'mysql' - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.collation - else - puts 'sorry, your database adapter is not supported yet, feel free to submit a patch' - end - end - - desc "Retrieves the current schema version number" - task :version => :environment do - puts "Current version: #{ActiveRecord::Migrator.current_version}" - end - - desc "Raises an error if there are pending migrations" - task :abort_if_pending_migrations => :environment do - if defined? ActiveRecord - pending_migrations = ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations - - if pending_migrations.any? - puts "You have #{pending_migrations.size} pending migrations:" - pending_migrations.each do |pending_migration| - puts ' %4d %s' % [pending_migration.version, pending_migration.name] - end - abort %{Run "rake db:migrate" to update your database then try again.} - end - end - end - - desc 'Create the database, load the schema, and initialize with the seed data' - task :setup => [ 'db:create', 'db:schema:load', 'db:seed' ] - - desc 'Load the seed data from db/seeds.rb' - task :seed => :environment do - seed_file = File.join(Rails.root, 'db', 'seeds.rb') - load(seed_file) if File.exist?(seed_file) - end - - namespace :fixtures do - desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures." - task :load => :environment do - require 'active_record/fixtures' - ActiveRecord::Base.establish_connection(Rails.env) - base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures') - fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir - - (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir.glob(File.join(fixtures_dir, '*.{yml,csv}'))).each do |fixture_file| - Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*')) - end - end - - desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures." - task :identify => :environment do - require "active_record/fixtures" - - label, id = ENV["LABEL"], ENV["ID"] - raise "LABEL or ID required" if label.blank? && id.blank? - - puts %Q(The fixture ID for "#{label}" is #{Fixtures.identify(label)}.) if label - - base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures') - Dir["#{base_dir}/**/*.yml"].each do |file| - if data = YAML::load(ERB.new(IO.read(file)).result) - data.keys.each do |key| - key_id = Fixtures.identify(key) - - if key == label || key_id == id.to_i - puts "#{file}: #{key} (#{key_id})" - end - end - end - end - end - end - - namespace :schema do - desc "Create a db/schema.rb file that can be portably used against any DB supported by AR" - task :dump => :environment do - require 'active_record/schema_dumper' - File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", "w") do |file| - ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) - end - Rake::Task["db:schema:dump"].reenable - end - - desc "Load a schema.rb file into the database" - task :load => :environment do - file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb" - if File.exists?(file) - load(file) - else - abort %{#{file} doesn't exist yet. Run "rake db:migrate" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to prevent active_record from loading: config.frameworks -= [ :active_record ]} - end - end - end - - namespace :structure do - desc "Dump the database structure to a SQL file" - task :dump => :environment do - abcs = ActiveRecord::Base.configurations - case abcs[RAILS_ENV]["adapter"] - when "mysql", "oci", "oracle" - ActiveRecord::Base.establish_connection(abcs[RAILS_ENV]) - File.open("#{Rails.root}/db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump } - when "postgresql" - ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"] - ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"] - ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"] - search_path = abcs[RAILS_ENV]["schema_search_path"] - unless search_path.blank? - search_path = search_path.split(",").map{|search_path| "--schema=#{search_path.strip}" }.join(" ") - end - `pg_dump -i -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{search_path} #{abcs[RAILS_ENV]["database"]}` - raise "Error dumping database" if $?.exitstatus == 1 - when "sqlite", "sqlite3" - dbfile = abcs[RAILS_ENV]["database"] || abcs[RAILS_ENV]["dbfile"] - `#{abcs[RAILS_ENV]["adapter"]} #{dbfile} .schema > db/#{RAILS_ENV}_structure.sql` - when "sqlserver" - `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r` - `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r` - when "firebird" - set_firebird_env(abcs[RAILS_ENV]) - db_string = firebird_db_string(abcs[RAILS_ENV]) - sh "isql -a #{db_string} > #{Rails.root}/db/#{RAILS_ENV}_structure.sql" - else - raise "Task not supported by '#{abcs["test"]["adapter"]}'" - end - - if ActiveRecord::Base.connection.supports_migrations? - File.open("#{Rails.root}/db/#{RAILS_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information } - end - end - end - - namespace :test do - desc "Recreate the test database from the current schema.rb" - task :load => 'db:test:purge' do - ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) - ActiveRecord::Schema.verbose = false - Rake::Task["db:schema:load"].invoke - end - - desc "Recreate the test database from the current environment's database schema" - task :clone => %w(db:schema:dump db:test:load) - - desc "Recreate the test databases from the development structure" - task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do - abcs = ActiveRecord::Base.configurations - case abcs["test"]["adapter"] - when "mysql" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') - IO.readlines("#{Rails.root}/db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table| - ActiveRecord::Base.connection.execute(table) - end - when "postgresql" - ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"] - ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"] - ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"] - `psql -U "#{abcs["test"]["username"]}" -f #{Rails.root}/db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}` - when "sqlite", "sqlite3" - dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] - `#{abcs["test"]["adapter"]} #{dbfile} < #{Rails.root}/db/#{RAILS_ENV}_structure.sql` - when "sqlserver" - `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` - when "oci", "oracle" - ActiveRecord::Base.establish_connection(:test) - IO.readlines("#{Rails.root}/db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl| - ActiveRecord::Base.connection.execute(ddl) - end - when "firebird" - set_firebird_env(abcs["test"]) - db_string = firebird_db_string(abcs["test"]) - sh "isql -i #{Rails.root}/db/#{RAILS_ENV}_structure.sql #{db_string}" - else - raise "Task not supported by '#{abcs["test"]["adapter"]}'" - end - end - - desc "Empty the test database" - task :purge => :environment do - abcs = ActiveRecord::Base.configurations - case abcs["test"]["adapter"] - when "mysql" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"], abcs["test"]) - when "postgresql" - ActiveRecord::Base.clear_active_connections! - drop_database(abcs['test']) - create_database(abcs['test']) - when "sqlite","sqlite3" - dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] - File.delete(dbfile) if File.exist?(dbfile) - when "sqlserver" - dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-') - `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}` - `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` - when "oci", "oracle" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl| - ActiveRecord::Base.connection.execute(ddl) - end - when "firebird" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.recreate_database! - else - raise "Task not supported by '#{abcs["test"]["adapter"]}'" - end - end - - desc 'Check for pending migrations and load the test schema' - task :prepare => 'db:abort_if_pending_migrations' do - if defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank? - Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:load" }[ActiveRecord::Base.schema_format]].invoke - end - end - end - - namespace :sessions do - desc "Creates a sessions migration for use with ActiveRecord::SessionStore" - task :create => :environment do - raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations? - require 'rails/generators' - require 'rails/generators/rails/session_migration/session_migration_generator' - Rails::Generators::SessionMigrationGenerator.start [ ENV["MIGRATION"] || "add_sessions_table" ] - end - - desc "Clear the sessions table" - task :clear => :environment do - ActiveRecord::Base.connection.execute "DELETE FROM #{session_table_name}" - end - end -end - -def drop_database(config) - case config['adapter'] - when 'mysql' - ActiveRecord::Base.establish_connection(config) - ActiveRecord::Base.connection.drop_database config['database'] - when /^sqlite/ - require 'pathname' - path = Pathname.new(config['database']) - file = path.absolute? ? path.to_s : File.join(Rails.root, path) - - FileUtils.rm(file) - when 'postgresql' - ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) - ActiveRecord::Base.connection.drop_database config['database'] - end -end - -def session_table_name - ActiveRecord::SessionStore::Session.table_name -end - -def set_firebird_env(config) - ENV["ISC_USER"] = config["username"].to_s if config["username"] - ENV["ISC_PASSWORD"] = config["password"].to_s if config["password"] -end - -def firebird_db_string(config) - FireRuby::Database.db_string_for(config.symbolize_keys) -end diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake index 1611d1d94d..f7b53885c8 100644 --- a/railties/lib/rails/tasks/framework.rake +++ b/railties/lib/rails/tasks/framework.rake @@ -92,7 +92,7 @@ namespace :rails do namespace :update do def invoke_from_app_generator(method) - require 'generators' + require 'rails/generators' require 'rails/generators/rails/app/app_generator' generator = Rails::Generators::AppGenerator.new ["rails"], { :with_dispatchers => true }, @@ -100,6 +100,12 @@ namespace :rails do generator.invoke(method) end + desc "Update config/boot.rb from your current rails install" + task :configs do + invoke_from_app_generator :create_boot_file + invoke_from_app_generator :create_config_files + end + desc "Update Prototype javascripts from your current rails install" task :javascripts do invoke_from_app_generator :create_prototype_files diff --git a/railties/lib/rails/tasks/misc.rake b/railties/lib/rails/tasks/misc.rake index 7f244ebaed..9433b3556a 100644 --- a/railties/lib/rails/tasks/misc.rake +++ b/railties/lib/rails/tasks/misc.rake @@ -1,8 +1,4 @@ task :default => :test -task :environment do - $rails_rake_task = true - require(File.join(Rails.root, 'config', 'environment')) -end task :rails_env do unless defined? RAILS_ENV diff --git a/railties/lib/rails/tasks/testing.rake b/railties/lib/rails/tasks/testing.rake index fd5e52a05b..57857fb911 100644 --- a/railties/lib/rails/tasks/testing.rake +++ b/railties/lib/rails/tasks/testing.rake @@ -48,7 +48,7 @@ task :test do task end end.compact - abort "Errors running #{errors.to_sentence(:locale => :en)}!" if errors.any? + abort "Errors running #{errors * ', '}!" if errors.any? end namespace :test do @@ -59,7 +59,6 @@ namespace :test do recent_tests('app/controllers/**/*.rb', 'test/functional', since) t.libs << 'test' - t.verbose = true t.test_files = touched.uniq end Rake::Task['test:recent'].comment = "Test recent changes" @@ -84,35 +83,30 @@ namespace :test do end t.libs << 'test' - t.verbose = true end Rake::Task['test:uncommitted'].comment = "Test changes since last checkin (only Subversion and Git)" Rake::TestTask.new(:units => "db:test:prepare") do |t| t.libs << "test" t.pattern = 'test/unit/**/*_test.rb' - t.verbose = true end Rake::Task['test:units'].comment = "Run the unit tests in test/unit" Rake::TestTask.new(:functionals => "db:test:prepare") do |t| t.libs << "test" t.pattern = 'test/functional/**/*_test.rb' - t.verbose = true end Rake::Task['test:functionals'].comment = "Run the functional tests in test/functional" Rake::TestTask.new(:integration => "db:test:prepare") do |t| t.libs << "test" t.pattern = 'test/integration/**/*_test.rb' - t.verbose = true end Rake::Task['test:integration'].comment = "Run the integration tests in test/integration" Rake::TestTask.new(:benchmark => 'db:test:prepare') do |t| t.libs << 'test' t.pattern = 'test/performance/**/*_test.rb' - t.verbose = true t.options = '-- --benchmark' end Rake::Task['test:benchmark'].comment = 'Benchmark the performance tests' @@ -120,7 +114,6 @@ namespace :test do Rake::TestTask.new(:profile => 'db:test:prepare') do |t| t.libs << 'test' t.pattern = 'test/performance/**/*_test.rb' - t.verbose = true end Rake::Task['test:profile'].comment = 'Profile the performance tests' @@ -132,8 +125,6 @@ namespace :test do else t.pattern = 'vendor/plugins/*/**/test/**/*_test.rb' end - - t.verbose = true end Rake::Task['test:plugins'].comment = "Run the plugin tests in vendor/plugins/*/**/test (or specify with PLUGIN=name)" end diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 9f6c42945f..2601765065 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -2,14 +2,18 @@ # so fixtures are loaded to the right database silence_warnings { RAILS_ENV = "test" } -require 'rubygems' -gem "rack", "~> 1.0.0" -gem "rack-test", "~> 0.5.0" +require 'rack' +require 'rack/test' require 'test/unit' require 'active_support/core_ext/kernel/requires' + +# AP is always present +require 'action_controller/test_case' require 'action_view/test_case' + require 'action_mailer/test_case' if defined?(ActionMailer) +require 'active_model/test_case' if defined?(ActiveModel) if defined?(ActiveRecord) require 'active_record/test_case' diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb deleted file mode 100644 index 885230fac4..0000000000 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Thor - VERSION = "0.11.8".freeze -end diff --git a/railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc b/railties/lib/rails/vendor/thor-0.12.3/CHANGELOG.rdoc index adedfeca9d..d02fc43e84 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc +++ b/railties/lib/rails/vendor/thor-0.12.3/CHANGELOG.rdoc @@ -1,9 +1,7 @@ -== TODO - -* Improve spec coverage for Thor::Runner - -== 0.12, released 2009-11-06 +== 0.12, released 2010-01-02 +* Removed rr in favor to rspec mock framework +* Improved output for thor -T * [#7] Do not force white color on status * [#8] Yield a block with the filename on directory diff --git a/railties/lib/rails/vendor/thor-0.12.0/LICENSE b/railties/lib/rails/vendor/thor-0.12.3/LICENSE index 98722da459..98722da459 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/LICENSE +++ b/railties/lib/rails/vendor/thor-0.12.3/LICENSE diff --git a/railties/lib/rails/vendor/thor-0.12.0/README.rdoc b/railties/lib/rails/vendor/thor-0.12.3/README.rdoc index f1106f02b6..ee545f3d97 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/README.rdoc +++ b/railties/lib/rails/vendor/thor-0.12.3/README.rdoc @@ -7,7 +7,7 @@ Example: class App < Thor # [1] map "-L" => :list # [2] - + desc "install APP_NAME", "install one of the available apps" # [3] method_options :force => :boolean, :alias => :string # [4] def install(name) @@ -17,7 +17,7 @@ Example: end # other code end - + desc "list [SEARCH]", "list all of the available apps, limited by SEARCH" def list(search="") # list everything @@ -126,13 +126,13 @@ invoked only once. For example: invoke :two invoke :three end - + desc "two", "Prints 2, 3" def two puts 2 invoke :three end - + desc "three", "Prints 3" def three puts 3 @@ -155,15 +155,15 @@ Thor::Group as this: class Counter < Thor::Group desc "Prints 1, 2, 3" - + def one puts 1 end - + def two puts 2 end - + def three puts 3 end @@ -184,15 +184,15 @@ Besides, Thor::Group can parse arguments and options as Thor tasks: # number will be available as attr_accessor argument :number, :type => :numeric, :desc => "The number to start counting" desc "Prints the 'number' given upto 'number+2'" - + def one puts number + 0 end - + def two puts number + 1 end - + def three puts number + 2 end diff --git a/railties/lib/rails/vendor/thor-0.12.0/Thorfile b/railties/lib/rails/vendor/thor-0.12.3/Thorfile index f71a1e57e2..ff1cb4498a 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/Thorfile +++ b/railties/lib/rails/vendor/thor-0.12.3/Thorfile @@ -56,7 +56,7 @@ class Default < Thor s.test_files.exclude 'spec/sandbox/**/*' end - Jeweler::RubyforgeTasks.new + Jeweler::GemcutterTasks.new rescue LoadError puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor.rb index 68944f140d..d4d8fbd64d 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor.rb @@ -78,14 +78,14 @@ class Thor @method_options end - # Adds an option to the set of class options. If :for is given as option, + # Adds an option to the set of method options. If :for is given as option, # it allows you to change the options from a previous defined task. # # def previous_task # # magic # end # - # method_options :foo => :bar, :for => :previous_task + # method_option :foo => :bar, :for => :previous_task # # def next_task # # magic @@ -101,7 +101,6 @@ class Thor # :default - Default value for this argument. It cannot be required and have default values. # :aliases - Aliases for this option. # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. - # :group - The group for this options. Use by class options to output options in different levels. # :banner - String to show on usage notes. # def method_option(name, options={}) @@ -140,49 +139,48 @@ class Thor end end - # Prints help information. If a task name is given, it shows information - # only about the specific task. + # Prints help information for the given task. # # ==== Parameters - # meth<String>:: An optional task name to print usage information about. + # shell<Thor::Shell> + # task_name<String> + # + def task_help(shell, task_name) + task = all_tasks[task_name] + raise UndefinedTaskError, "task '#{task_name}' could not be found in namespace '#{self.namespace}'" unless task + + shell.say "Usage:" + shell.say " #{banner(task)}" + shell.say + class_options_help(shell, nil => task.options.map { |_, o| o }) + shell.say task.description + end + + # Prints help information for this class. # - # ==== Options - # namespace:: When true, shows the namespace in the output before the usage. - # skip_inherited:: When true, does not show tasks from superclass. + # ==== Parameters + # shell<Thor::Shell> # - def help(shell, meth=nil, options={}) - meth, options = nil, meth if meth.is_a?(Hash) - - if meth - task = all_tasks[meth] - raise UndefinedTaskError, "task '#{meth}' could not be found in namespace '#{self.namespace}'" unless task - - shell.say "Usage:" - shell.say " #{banner(task, options[:namespace], false)}" - shell.say - class_options_help(shell, "Class", :Method => task.options.map { |_, o| o }) - shell.say task.description - else - list = (options[:short] ? tasks : all_tasks).map do |_, task| - item = [ banner(task, options[:namespace]) ] - item << "# #{task.short_description}" if task.short_description - item << " " - end - - options[:ident] ||= 2 - if options[:short] - shell.print_list(list, :ident => options[:ident]) - else - shell.say "Tasks:" - shell.print_list(list, :ident => options[:ident]) - end + def help(shell) + list = printable_tasks + Thor::Util.thor_classes_in(self).each do |klass| + list += klass.printable_tasks(false) + end + list.sort!{ |a,b| a[0] <=> b[0] } - Thor::Util.thor_classes_in(self).each do |subclass| - namespace = options[:namespace] == true || subclass.namespace.gsub(/^#{self.namespace}:/, '') - subclass.help(shell, options.merge(:short => true, :namespace => namespace)) - end + shell.say "Tasks:" + shell.print_table(list, :ident => 2, :truncate => true) + shell.say + class_options_help(shell) + end - class_options_help(shell, "Class") unless options[:short] + # Returns tasks ready to be printed. + def printable_tasks(all=true) + (all ? all_tasks : tasks).map do |_, task| + item = [] + item << banner(task) + item << (task.description ? "# #{task.description.gsub(/\s+/m,' ')}" : "") + item end end @@ -193,8 +191,8 @@ class Thor # the task that is going to be invoked and a boolean which indicates if # the namespace should be displayed as arguments. # - def banner(task, namespace=true, show_options=true) - task.formatted_usage(self, namespace, show_options) + def banner(task) + "thor " + task.formatted_usage(self) end def baseclass #:nodoc: @@ -237,6 +235,6 @@ class Thor desc "help [TASK]", "Describe available tasks or one specific task" def help(task=nil) - self.class.help(shell, task, :namespace => task && task.include?(?:)) + task ? self.class.task_help(shell, task) : self.class.help(shell) end end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions.rb index d561ccb2aa..da98444bf2 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions.rb @@ -1,4 +1,5 @@ require 'fileutils' +require 'thor/core_ext/file_binary_read' Dir[File.join(File.dirname(__FILE__), "actions", "*.rb")].each do |action| require action @@ -38,17 +39,17 @@ class Thor # Add runtime options that help actions execution. # def add_runtime_options! - class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime, - :desc => "Run but do not make any changes" - class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime, :desc => "Overwrite files that already exist" - class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime, - :desc => "Skip files that already exist" + class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime, + :desc => "Run but do not make any changes" class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime, :desc => "Supress status output" + + class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime, + :desc => "Skip files that already exist" end end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/create_file.rb index a3d9296823..6e0eeb43e2 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/create_file.rb @@ -42,7 +42,7 @@ class Thor # Boolean:: true if it is identical, false otherwise. # def identical? - exists? && File.read(destination) == render + exists? && File.binread(destination) == render end # Holds the content to be added to the file. @@ -58,7 +58,7 @@ class Thor def invoke! invoke_with_conflict_check do FileUtils.mkdir_p(File.dirname(destination)) - File.open(destination, 'w'){ |f| f.write render } + File.open(destination, 'wb') { |f| f.write render } end given_destination end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/directory.rb index 467e63732a..2e0b459fa3 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/directory.rb @@ -79,11 +79,9 @@ class Thor next if dirname == given_destination base.empty_directory(dirname, config) when /\.tt$/ - destination = base.template(file_source, file_destination[0..-4], config) - @block.call(destination) if @block + destination = base.template(file_source, file_destination[0..-4], config, &@block) else - destination = base.copy_file(file_source, file_destination, config) - @block.call(destination) if @block + destination = base.copy_file(file_source, file_destination, config, &@block) end end end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/empty_directory.rb index 484cb820f8..484cb820f8 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/empty_directory.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/file_manipulation.rb index d77d90d448..44d6836c10 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/file_manipulation.rb @@ -18,12 +18,14 @@ class Thor # # copy_file "doc/README" # - def copy_file(source, destination=nil, config={}) + def copy_file(source, destination=nil, config={}, &block) destination ||= source source = File.expand_path(find_in_source_paths(source.to_s)) create_file destination, nil, config do - File.read(source) + content = File.binread(source) + content = block.call(content) if block + content end end @@ -46,7 +48,7 @@ class Thor # def get(source, destination=nil, config={}, &block) source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^http\:\/\// - render = open(source).read + render = File.binread(source) destination ||= if block_given? block.arity == 1 ? block.call(render) : block.call @@ -72,13 +74,15 @@ class Thor # # template "doc/README" # - def template(source, destination=nil, config={}) + def template(source, destination=nil, config={}, &block) destination ||= source source = File.expand_path(find_in_source_paths(source.to_s)) context = instance_eval('binding') create_file destination, nil, config do - ERB.new(::File.read(source), nil, '-').result(context) + content = ERB.new(::File.binread(source), nil, '-').result(context) + content = block.call(content) if block + content end end @@ -189,7 +193,7 @@ class Thor say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) unless options[:pretend] - content = File.read(path) + content = File.binread(path) content.gsub!(flag, *args, &block) File.open(path, 'wb') { |file| file.write(content) } end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/inject_into_file.rb index 0636ec6591..350ab73862 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/actions/inject_into_file.rb @@ -90,7 +90,7 @@ class Thor # def replace!(regexp, string) unless base.options[:pretend] - content = File.read(destination) + content = File.binread(destination) content.gsub!(regexp, string) File.open(destination, 'wb') { |file| file.write(content) } end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/base.rb index 700d794123..aae4cdb89c 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/base.rb @@ -92,6 +92,8 @@ class Thor end module ClassMethods + attr_accessor :debugging + # Adds an argument to the class and creates an attr_accessor for it. # # Arguments are different from options in several aspects. The first one @@ -347,10 +349,11 @@ class Thor # Default way to start generators from the command line. # def start(given_args=ARGV, config={}) + self.debugging = given_args.include?("--debug") config[:shell] ||= Thor::Base.shell.new yield rescue Thor::Error => e - if given_args.include?("--debug") + if debugging raise e else config[:shell].error e.message @@ -361,48 +364,43 @@ class Thor protected # Prints the class options per group. If an option does not belong to - # any group, it uses the ungrouped name value. This method provide to - # hooks to add extra options, one of them if the third argument called - # extra_group that should be a hash in the format :group => Array[Options]. - # - # The second is by returning a lambda used to print values. The lambda - # requires two options: the group name and the array of options. + # any group, it's printed as Class option. # - def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc: - groups = {} - + def class_options_help(shell, groups={}) #:nodoc: + # Group options by group class_options.each do |_, value| groups[value.group] ||= [] groups[value.group] << value end - printer = proc do |group_name, options| - list = [] - padding = options.collect{ |o| o.aliases.size }.max.to_i * 4 + # Deal with default group + global_options = groups.delete(nil) || [] + print_options(shell, global_options) + + # Print all others + groups.each do |group_name, options| + print_options(shell, options, group_name) + end + end + + # Receives a set of options and print them. + def print_options(shell, options, group_name=nil) + return if options.empty? - options.each do |option| - item = [ option.usage(padding) ] - item.push(option.description ? "# #{option.description}" : "") + list = [] + padding = options.collect{ |o| o.aliases.size }.max.to_i * 4 - list << item - list << [ "", "# Default: #{option.default}" ] if option.show_default? - end + options.each do |option| + item = [ option.usage(padding) ] + item.push(option.description ? "# #{option.description}" : "") - unless list.empty? - shell.say(group_name ? "#{group_name} options:" : "Options:") - shell.print_table(list, :ident => 2) - shell.say "" - end + list << item + list << [ "", "# Default: #{option.default}" ] if option.show_default? end - # Deal with default group - global_options = groups.delete(nil) || [] - printer.call(ungrouped_name, global_options) if global_options - - # Print all others - groups = extra_group.merge(groups) if extra_group - groups.each(&printer) - printer + shell.say(group_name ? "#{group_name} options:" : "Options:") + shell.print_table(list, :ident => 2) + shell.say "" end # Raises an error if the word given is a Thor reserved word. diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/file_binary_read.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/file_binary_read.rb new file mode 100644 index 0000000000..d6af7e44b0 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/file_binary_read.rb @@ -0,0 +1,9 @@ +class File #:nodoc: + + unless File.respond_to?(:binread) + def self.binread(file) + File.open(file, 'rb') { |f| f.read } + end + end + +end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/hash_with_indifferent_access.rb index 78bc5cf4bf..78bc5cf4bf 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/hash_with_indifferent_access.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/ordered_hash.rb index 27fea5bb35..27fea5bb35 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/core_ext/ordered_hash.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/error.rb index f9b31a35d1..f9b31a35d1 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/error.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/group.rb index 0964a9667a..a585b37b73 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/group.rb @@ -41,16 +41,12 @@ class Thor::Group # ==== Options # short:: When true, shows only usage. # - def help(shell, options={}) - if options[:short] - shell.say banner - else - shell.say "Usage:" - shell.say " #{banner}" - shell.say - class_options_help(shell) - shell.say self.desc if self.desc - end + def help(shell) + shell.say "Usage:" + shell.say " #{banner}\n" + shell.say + class_options_help(shell) + shell.say self.desc if self.desc end # Stores invocations for this class merging with superclass values. @@ -177,15 +173,11 @@ class Thor::Group # Overwrite class options help to allow invoked generators options to be # shown recursively when invoking a generator. # - def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc: - group_options = {} - - get_options_from_invocations(group_options, class_options) do |klass| - klass.send(:get_options_from_invocations, group_options, class_options) + def class_options_help(shell, groups={}) #:nodoc: + get_options_from_invocations(groups, class_options) do |klass| + klass.send(:get_options_from_invocations, groups, class_options) end - - group_options.merge!(extra_group) if extra_group - super(shell, ungrouped_name, group_options) + super(shell, groups) end # Get invocations array and merge options from invocations. Those @@ -218,13 +210,26 @@ class Thor::Group end end + # Returns tasks ready to be printed. + def printable_tasks(*) + item = [] + item << banner + item << (desc ? "# #{desc.gsub(/\s+/m,' ')}" : "") + [item] + end + protected # The banner for this class. You can customize it if you are invoking the # thor class by another ways which is not the Thor::Runner. # def banner - "#{self.namespace} #{self.arguments.map {|a| a.usage }.join(' ')}" + "thor #{self_task.formatted_usage(self, false)}" + end + + # Represents the whole class as a task. + def self_task #:nodoc: + Thor::Task::Dynamic.new(self.namespace, class_options) end def baseclass #:nodoc: @@ -243,7 +248,6 @@ class Thor::Group # Shortcut to invoke with padding and block handling. Use internally by # invoke and invoke_from_option class methods. - # def _invoke_for_class_method(klass, task=nil, *args, &block) #:nodoc: shell.padding += 1 diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/invocation.rb index 32e6a72454..32e6a72454 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/invocation.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser.rb index 57a3f6e1a5..57a3f6e1a5 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/argument.rb index aa8ace4719..aa8ace4719 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/argument.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/arguments.rb index fb5d965e06..fb5d965e06 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/arguments.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/option.rb index 9e40ec73fa..9e40ec73fa 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/option.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/options.rb index 75092308b5..75092308b5 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/parser/options.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/rake_compat.rb index 0d0757fdda..0d0757fdda 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/rake_compat.rb diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/runner.rb index 9dc70ea069..f197081e3f 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/runner.rb @@ -124,11 +124,7 @@ class Thor::Runner < Thor #:nodoc: method_options :internal => :boolean def installed initialize_thorfiles(nil, true) - - klasses = Thor::Base.subclasses - klasses -= [Thor, Thor::Runner] unless options["internal"] - - display_klasses(true, klasses) + display_klasses(true, options["internal"]) end desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)" @@ -144,11 +140,15 @@ class Thor::Runner < Thor #:nodoc: (options[:all] || k.group == group) && k.namespace =~ search end - display_klasses(false, klasses) + display_klasses(false, false, klasses) end private + def self.banner(task) + "thor " + task.formatted_usage(self, false) + end + def thor_root Thor::Util.thor_root end @@ -156,7 +156,7 @@ class Thor::Runner < Thor #:nodoc: def thor_yaml @thor_yaml ||= begin yaml_file = File.join(thor_root, "thor.yml") - yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file) + yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file) yaml || {} end end @@ -215,9 +215,6 @@ class Thor::Runner < Thor #:nodoc: # 5. c:\ <-- no Thorfiles found! # def thorfiles(relevant_to=nil, skip_lookup=false) - # TODO Remove this dealing with deprecated thor when :namespaces: is available as constants - save_yaml(thor_yaml) if Thor::Util.convert_constants_to_namespaces(thor_yaml) - thorfiles = [] unless skip_lookup @@ -253,47 +250,54 @@ class Thor::Runner < Thor #:nodoc: # Display information about the given klasses. If with_module is given, # it shows a table with information extracted from the yaml file. # - def display_klasses(with_modules=false, klasses=Thor.subclasses) - klasses -= [Thor, Thor::Runner] unless with_modules + def display_klasses(with_modules=false, show_internal=false, klasses=Thor::Base.subclasses) + klasses -= [Thor, Thor::Runner, Thor::Group] unless show_internal + raise Error, "No Thor tasks available" if klasses.empty? + show_modules if with_modules && !thor_yaml.empty? - if with_modules && !thor_yaml.empty? - info = [] - labels = ["Modules", "Namespaces"] + # Remove subclasses + klasses.dup.each do |klass| + klasses -= Thor::Util.thor_classes_in(klass) + end - info << labels - info << [ "-" * labels[0].size, "-" * labels[1].size ] + list = Hash.new { |h,k| h[k] = [] } + groups = klasses.select { |k| k.ancestors.include?(Thor::Group) } - thor_yaml.each do |name, hash| - info << [ name, hash[:namespaces].join(", ") ] - end + # Get classes which inherit from Thor + (klasses - groups).each { |k| list[k.namespace] += k.printable_tasks(false) } - print_table info - say "" - end + # Get classes which inherit from Thor::Base + groups.map! { |k| k.printable_tasks(false).first } + list["root"] = groups - unless klasses.empty? - klasses.dup.each do |klass| - klasses -= Thor::Util.thor_classes_in(klass) - end + # Order namespaces with default coming first + list = list.sort{ |a,b| a[0].sub(/^default/, '') <=> b[0].sub(/^default/, '') } + list.each { |n, tasks| display_tasks(n, tasks) unless tasks.empty? } + end - klasses.each { |k| display_tasks(k) } - else - say "\033[1;34mNo Thor tasks available\033[0m" - end + def display_tasks(namespace, list) #:nodoc: + list.sort!{ |a,b| a[0] <=> b[0] } + + say shell.set_color(namespace, :blue, true) + say "-" * namespace.size + + print_table(list, :truncate => true) + say end - # Display tasks from the given Thor class. - # - def display_tasks(klass) - unless klass.tasks.empty? - base = klass.namespace + def show_modules #:nodoc: + info = [] + labels = ["Modules", "Namespaces"] - color = base == "default" ? :magenta : :blue - say shell.set_color(base, color, true) - say "-" * base.length + info << labels + info << [ "-" * labels[0].size, "-" * labels[1].size ] - klass.help(shell, :short => true, :ident => 0, :namespace => true) + thor_yaml.each do |name, hash| + info << [ name, hash[:namespaces].join(", ") ] end + + print_table info + say "" end end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell.rb index 1dc8f0e5b4..64a173de83 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell.rb @@ -22,7 +22,7 @@ class Thor end module Shell - SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_list, :print_table] + SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_table] # Add shell to initialize config values. # diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/basic.rb index ea9665380b..a11f45b4e9 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/basic.rb @@ -75,30 +75,6 @@ class Thor !yes?(statement, color) end - # Prints a list of items. - # - # ==== Parameters - # list<Array[String, String, ...]> - # - # ==== Options - # mode:: Can be :rows or :inline. Defaults to :rows. - # ident:: Ident each item with the value given. - # - def print_list(list, options={}) - return if list.empty? - - ident = " " * (options[:ident] || 0) - content = case options[:mode] - when :inline - last = list.pop - "#{list.join(", ")}, and #{last}" - else # rows - ident + list.join("\n#{ident}") - end - - $stdout.puts content - end - # Prints a table. # # ==== Parameters @@ -110,20 +86,26 @@ class Thor def print_table(table, options={}) return if table.empty? - formats = [] + formats, ident = [], options[:ident].to_i + options[:truncate] = terminal_width if options[:truncate] == true + 0.upto(table.first.length - 2) do |i| maxima = table.max{ |a,b| a[i].size <=> b[i].size }[i].size formats << "%-#{maxima + 2}s" end - formats[0] = formats[0].insert(0, " " * options[:ident]) if options[:ident] + formats[0] = formats[0].insert(0, " " * ident) formats << "%s" table.each do |row| + sentence = "" + row.each_with_index do |column, i| - $stdout.print formats[i] % column.to_s + sentence << formats[i] % column.to_s end - $stdout.puts + + sentence = truncate(sentence, options[:truncate]) if options[:truncate] + $stdout.puts sentence end end @@ -143,7 +125,7 @@ class Thor answer = ask %[Overwrite #{destination}? (enter "h" for help) #{options}] case answer - when is?(:yes), is?(:force) + when is?(:yes), is?(:force), "" return true when is?(:no), is?(:skip) return false @@ -214,6 +196,44 @@ HELP base && base.options[:quiet] end + # This code was copied from Rake, available under MIT-LICENSE + # Copyright (c) 2003, 2004 Jim Weirich + def terminal_width + if ENV['THOR_COLUMNS'] + result = ENV['THOR_COLUMNS'].to_i + else + result = unix? ? dynamic_width : 80 + end + (result < 10) ? 80 : result + rescue + 80 + end + + # Calculate the dynamic width of the terminal + def dynamic_width + @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) + end + + def dynamic_width_stty + %x{stty size 2>/dev/null}.split[1].to_i + end + + def dynamic_width_tput + %x{tput cols 2>/dev/null}.to_i + end + + def unix? + RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i + end + + def truncate(string, width) + if string.length <= width + string + else + ( string[0, width-3] || "" ) + "..." + end + end + end end end diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/color.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/color.rb index 24704f7885..b2bc66dfba 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/color.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/shell/color.rb @@ -63,7 +63,7 @@ class Thor # def show_diff(destination, content) #:nodoc: if diff_lcs_loaded? && ENV['THOR_DIFF'].nil? && ENV['RAILS_DIFF'].nil? - actual = File.read(destination).to_s.split("\n") + actual = File.binread(destination).to_s.split("\n") content = content.to_s.split("\n") Diff::LCS.sdiff(actual, content).each do |diff| diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/task.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/task.rb index 91c7564d3f..5c8877591b 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/task.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/task.rb @@ -1,11 +1,11 @@ class Thor class Task < Struct.new(:name, :description, :usage, :options) + FILE_REGEXP = /^#{Regexp.escape(File.expand_path(__FILE__))}:[\w:]+ `run'$/ # A dynamic task that handles method missing scenarios. - # class Dynamic < Task - def initialize(name) - super(name.to_s, "A dynamically-generated task", name.to_s) + def initialize(name, options=nil) + super(name.to_s, "A dynamically-generated task", name.to_s, options) end def run(instance, args=[]) @@ -25,84 +25,73 @@ class Thor self.options = other.options.dup if other.options end - def short_description - description.split("\n").first if description - end - # By default, a task invokes a method in the thor class. You can change this # implementation to create custom tasks. - # def run(instance, args=[]) raise UndefinedTaskError, "the '#{name}' task of #{instance.class} is private" unless public_method?(instance) instance.send(name, *args) rescue ArgumentError => e + raise e if instance.class.respond_to?(:debugging) && instance.class.debugging parse_argument_error(instance, e, caller) rescue NoMethodError => e + raise e if instance.class.respond_to?(:debugging) && instance.class.debugging parse_no_method_error(instance, e) end - # Returns the formatted usage. If a class is given, the class arguments are - # injected in the usage. - # - def formatted_usage(klass=nil, namespace=false, show_options=true) - formatted = if namespace.is_a?(String) - "#{namespace}:" - elsif klass && namespace - "#{klass.namespace.gsub(/^default/,'')}:" + # Returns the formatted usage by injecting given required arguments + # and required options into the given usage. + def formatted_usage(klass, namespace=nil) + namespace = klass.namespace if namespace.nil? + + # Add namespace + formatted = if namespace + "#{namespace.gsub(/^(default|thor:runner:)/,'')}:" else "" end - formatted << formatted_arguments(klass) - formatted << " #{formatted_options}" if show_options - formatted.strip! - formatted - end - - # Injects the class arguments into the task usage. - # - def formatted_arguments(klass) - if klass && !klass.arguments.empty? + # Add usage with required arguments + formatted << if klass && !klass.arguments.empty? usage.to_s.gsub(/^#{name}/) do |match| - match << " " << klass.arguments.map{ |a| a.usage }.join(' ') + match << " " << klass.arguments.map{ |a| a.usage }.compact.join(' ') end else usage.to_s end - end - # Returns the options usage for this task. - # - def formatted_options - @formatted_options ||= options.map{ |_, o| o.usage }.sort.join(" ") + # Add required options + formatted << " #{required_options}" + + # Strip and go! + formatted.strip end protected + def required_options + @required_options ||= options.map{ |_, o| o.usage if o.required? }.compact.sort.join(" ") + end + # Given a target, checks if this class name is not a private/protected method. - # def public_method?(instance) #:nodoc: collection = instance.private_methods + instance.protected_methods (collection & [name.to_s, name.to_sym]).empty? end - # Clean everything that comes from the Thor gempath and remove the caller. - # - def sans_backtrace(backtrace, caller) #:nodoc: - dirname = /^#{Regexp.escape(File.dirname(__FILE__))}/ - saned = backtrace.reject { |frame| frame =~ dirname } - saned -= caller + # For Ruby <= 1.8.7, we have to match the method name that we are trying to call. + # In Ruby >= 1.9.1, we have to match the method run in this file. + def backtrace_match?(backtrace) #:nodoc: + method_name = /`#{Regexp.escape(name.split(':').last)}'/ + backtrace =~ method_name || backtrace =~ FILE_REGEXP end def parse_argument_error(instance, e, caller) #:nodoc: - backtrace = sans_backtrace(e.backtrace, caller) - - if backtrace.empty? && e.message =~ /wrong number of arguments/ + if e.message =~ /wrong number of arguments/ && backtrace_match?(e.backtrace.first.to_s) if instance.is_a?(Thor::Group) raise e, "'#{name}' was called incorrectly. Are you sure it has arity equals to 0?" else raise InvocationError, "'#{name}' was called incorrectly. Call as " << - "'#{formatted_usage(instance.class, true)}'" + "'#{formatted_usage(instance.class)}'" end else raise e diff --git a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/util.rb index ebae0a3193..c2aed89ccf 100644 --- a/railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/util.rb @@ -76,8 +76,10 @@ class Thor # Returns the thor classes declared inside the given class. # def self.thor_classes_in(klass) + stringfied_constants = klass.constants.map { |c| c.to_s } Thor::Base.subclasses.select do |subclass| - klass.constants.include?(subclass.name.gsub("#{klass.name}::", '')) + next unless subclass.name + stringfied_constants.include?(subclass.name.gsub("#{klass.name}::", '')) end end @@ -155,7 +157,7 @@ class Thor # inside the sandbox to avoid namespacing conflicts. # def self.load_thorfile(path, content=nil) - content ||= File.read(path) + content ||= File.binread(path) begin Thor::Sandbox.class_eval(content, path) @@ -164,26 +166,6 @@ class Thor end end - # Receives a yaml (hash) and updates all constants entries to namespace. - # This was added to deal with deprecated versions of Thor. - # - # TODO Deprecate this method in the future. - # - # ==== Returns - # TrueClass|FalseClass:: Returns true if any change to the yaml file was made. - # - def self.convert_constants_to_namespaces(yaml) - yaml_changed = false - - yaml.each do |k, v| - next unless v[:constants] && v[:namespaces].nil? - yaml_changed = true - yaml[k][:namespaces] = v[:constants].map{|c| Thor::Util.namespace_from_thor_class(c)} - end - - yaml_changed - end - def self.user_home @@user_home ||= if ENV["HOME"] ENV["HOME"] diff --git a/railties/lib/rails/vendor/thor-0.12.3/lib/thor/version.rb b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/version.rb new file mode 100644 index 0000000000..3c9dd6f808 --- /dev/null +++ b/railties/lib/rails/vendor/thor-0.12.3/lib/thor/version.rb @@ -0,0 +1,3 @@ +class Thor + VERSION = "0.12.3".freeze +end |