diff options
14 files changed, 133 insertions, 74 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 4e770c37da..3eb81b0dfa 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -442,12 +442,14 @@ module ActiveRecord end end - def assume_migrated_upto_version(version, migrations_path = ActiveRecord::Migrator.migrations_path) + def assume_migrated_upto_version(version, migrations_paths = ActiveRecord::Migrator.migrations_paths) + migrations_paths = [migrations_paths] unless migrations_paths.kind_of?(Array) version = version.to_i sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name) migrated = select_values("SELECT version FROM #{sm_table}").map { |v| v.to_i } - versions = Dir["#{migrations_path}/[0-9]*_*.rb"].map do |filename| + paths = migrations_paths.map {|p| "#{p}/[0-9]*_*.rb" } + versions = Dir[*paths].map do |filename| filename.split('/').last.split('_').first.to_i end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 4dc67a0905..130b43cc15 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -511,39 +511,40 @@ module ActiveRecord class Migrator#:nodoc: class << self - attr_writer :migrations_path + attr_writer :migrations_paths + alias :migrations_path= :migrations_paths= - def migrate(migrations_path, target_version = nil) + def migrate(migrations_paths, target_version = nil) case when target_version.nil? - up(migrations_path, target_version) + up(migrations_paths, target_version) when current_version == 0 && target_version == 0 [] when current_version > target_version - down(migrations_path, target_version) + down(migrations_paths, target_version) else - up(migrations_path, target_version) + up(migrations_paths, target_version) end end - def rollback(migrations_path, steps=1) - move(:down, migrations_path, steps) + def rollback(migrations_paths, steps=1) + move(:down, migrations_paths, steps) end - def forward(migrations_path, steps=1) - move(:up, migrations_path, steps) + def forward(migrations_paths, steps=1) + move(:up, migrations_paths, steps) end - def up(migrations_path, target_version = nil) - self.new(:up, migrations_path, target_version).migrate + def up(migrations_paths, target_version = nil) + self.new(:up, migrations_paths, target_version).migrate end - def down(migrations_path, target_version = nil) - self.new(:down, migrations_path, target_version).migrate + def down(migrations_paths, target_version = nil) + self.new(:down, migrations_paths, target_version).migrate end - def run(direction, migrations_path, target_version) - self.new(direction, migrations_path, target_version).run + def run(direction, migrations_paths, target_version) + self.new(direction, migrations_paths, target_version).run end def schema_migrations_table_name @@ -569,12 +570,20 @@ module ActiveRecord name.table_name rescue "#{ActiveRecord::Base.table_name_prefix}#{name}#{ActiveRecord::Base.table_name_suffix}" end + def migrations_paths + @migrations_paths ||= ['db/migrate'] + # just to not break things if someone uses: migration_path = some_string + @migrations_paths.kind_of?(Array) ? @migrations_paths : [@migrations_paths] + end + def migrations_path - @migrations_path ||= 'db/migrate' + migrations_paths.first end - def migrations(path) - files = Dir["#{path}/[0-9]*_*.rb"] + def migrations(paths) + paths = [paths] unless paths.kind_of?(Array) + + files = Dir[*paths.map { |p| "#{p}/[0-9]*_*.rb" }] seen = Hash.new false @@ -598,22 +607,22 @@ module ActiveRecord private - def move(direction, migrations_path, steps) - migrator = self.new(direction, migrations_path) + def move(direction, migrations_paths, steps) + migrator = self.new(direction, migrations_paths) start_index = migrator.migrations.index(migrator.current_migration) if start_index finish = migrator.migrations[start_index + steps] version = finish ? finish.version : 0 - send(direction, migrations_path, version) + send(direction, migrations_paths, version) end end end - def initialize(direction, migrations_path, target_version = nil) + def initialize(direction, migrations_paths, target_version = nil) raise StandardError.new("This database does not yet support migrations") unless Base.connection.supports_migrations? Base.connection.initialize_schema_migrations_table - @direction, @migrations_path, @target_version = direction, migrations_path, target_version + @direction, @migrations_paths, @target_version = direction, migrations_paths, target_version end def current_version @@ -679,7 +688,7 @@ module ActiveRecord def migrations @migrations ||= begin - migrations = self.class.migrations(@migrations_path) + migrations = self.class.migrations(@migrations_paths) down? ? migrations.reverse : migrations end end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 1fbc8a1d32..a4fc18148e 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -1,8 +1,14 @@ -namespace :db do +db_namespace = namespace :db do task :load_config => :rails_env do require 'active_record' ActiveRecord::Base.configurations = Rails.application.config.database_configuration - ActiveRecord::Migrator.migrations_path = Rails.application.paths["db/migrate"].first + ActiveRecord::Migrator.migrations_paths = Rails.application.paths["db/migrate"].to_a + + if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH) + if engine.paths["db/migrate"].existent + ActiveRecord::Migrator.migrations_paths += engine.paths["db/migrate"].to_a + end + end end namespace :create do @@ -138,21 +144,21 @@ namespace :db do desc "Migrate the database (options: VERSION=x, VERBOSE=false)." - task :migrate => :environment do + task :migrate => [:environment, :load_config] do ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true - ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_path, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) + db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end namespace :migrate do # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).' - task :redo => :environment do + task :redo => [:environment, :load_config] do if ENV["VERSION"] - Rake::Task["db:migrate:down"].invoke - Rake::Task["db:migrate:up"].invoke + db_namespace["migrate:down"].invoke + db_namespace["migrate:up"].invoke else - Rake::Task["db:rollback"].invoke - Rake::Task["db:migrate"].invoke + db_namespace["rollback"].invoke + db_namespace["migrate"].invoke end end @@ -160,23 +166,23 @@ namespace :db do task :reset => ["db:drop", "db:create", "db:migrate"] # desc 'Runs the "up" for a given migration VERSION.' - task :up => :environment do + task :up => [:environment, :load_config] do version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_path, version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, version) + db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end # desc 'Runs the "down" for a given migration VERSION.' - task :down => :environment do + task :down => [:environment, :load_config] do version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_path, version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version) + db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end desc "Display status of migrations" - task :status => :environment do + task :status => [:environment, :load_config] do config = ActiveRecord::Base.configurations[Rails.env || 'development'] ActiveRecord::Base.establish_connection(config) unless ActiveRecord::Base.connection.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name) @@ -207,17 +213,17 @@ namespace :db do end desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).' - task :rollback => :environment do + task :rollback => [:environment, :load_config] do step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_path, step) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step) + db_namespace["schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).' - task :forward => :environment do + task :forward => [:environment, :load_config] do step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_path, step) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step) + db_namespace["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.' @@ -261,7 +267,7 @@ namespace :db do # 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, ActiveRecord::Migrator.migrations_path).pending_migrations + pending_migrations = ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations_paths).pending_migrations if pending_migrations.any? puts "You have #{pending_migrations.size} pending migrations:" @@ -321,12 +327,12 @@ namespace :db do 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 + task :dump => :load_config 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 + db_namespace["schema:dump"].reenable end desc "Load a schema.rb file into the database" @@ -383,7 +389,7 @@ namespace :db do task :load => 'db:test:purge' do ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) ActiveRecord::Schema.verbose = false - Rake::Task["db:schema:load"].invoke + db_namespace["schema:load"].invoke end # desc "Recreate the test database from the current environment's database schema" @@ -457,7 +463,7 @@ namespace :db do # 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 + db_namespace[{ :sql => "test:clone_structure", :ruby => "test:load" }[ActiveRecord::Base.schema_format]].invoke end end end @@ -501,7 +507,7 @@ namespace :railties do puts "Copied migration #{migration.basename} from #{name}" end - ActiveRecord::Migration.copy( ActiveRecord::Migrator.migrations_path, railties, + ActiveRecord::Migration.copy( ActiveRecord::Migrator.migrations_paths.first, railties, :on_skip => on_skip, :on_copy => on_copy) end end diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index c6bb5c1961..d815ab05ac 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -30,8 +30,8 @@ module ActiveRecord # ActiveRecord::Schema is only supported by database adapters that also # support migrations, the two features being very similar. class Schema < Migration - def migrations_path - ActiveRecord::Migrator.migrations_path + def migrations_paths + ActiveRecord::Migrator.migrations_paths end # Eval the given block. All methods available to the current connection @@ -51,7 +51,7 @@ module ActiveRecord unless info[:version].blank? initialize_schema_migrations_table - assume_migrated_upto_version(info[:version], schema.migrations_path) + assume_migrated_upto_version(info[:version], schema.migrations_paths) end end end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 96da3be655..95b7ce9f34 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -1275,6 +1275,18 @@ if ActiveRecord::Base.connection.supports_migrations? end end + def test_finds_migrations_from_two_directories + directories = [MIGRATIONS_ROOT + '/valid_with_timestamps', MIGRATIONS_ROOT + '/to_copy_with_timestamps'] + migrations = ActiveRecord::Migrator.new(:up, directories).migrations + + [[20090101010101, "PeopleHaveHobbies"], [20090101010202, "PeopleHaveDescriptions"], + [20100101010101, "PeopleHaveLastNames"], [20100201010101, "WeNeedReminders"], + [20100301010101, "InnocentJointable"]].each_with_index do |pair, i| + assert_equal migrations[i].version, pair.first + assert_equal migrations[i].name, pair.last + end + end + def test_finds_pending_migrations ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1) migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations diff --git a/railties/lib/rails/application/railties.rb b/railties/lib/rails/application/railties.rb index c1d2de571f..4fc5e92837 100644 --- a/railties/lib/rails/application/railties.rb +++ b/railties/lib/rails/application/railties.rb @@ -8,14 +8,6 @@ module Rails @all.each(&block) if block @all end - - def railties - @railties ||= ::Rails::Railtie.subclasses.map(&:instance) - end - - def engines - @engines ||= ::Rails::Engine.subclasses.map(&:instance) - end end end end diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 338565247f..46363d7921 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -18,8 +18,7 @@ when 'generate', 'destroy', 'plugin' require APP_PATH Rails.application.require_environment! - if defined?(ENGINE_PATH) - engine = Rails.application.railties.engines.find { |r| r.root.to_s == ENGINE_PATH } + if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH) Rails.application = engine end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 85fa4424c4..b188fdfca1 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -371,6 +371,11 @@ module Rails end end end + + # Finds engine with given path + def find(path) + Rails::Engine::Railties.engines.find { |r| File.expand_path(r.root.to_s) == File.expand_path(path.to_s) } + end end delegate :middleware, :root, :paths, :to => :config diff --git a/railties/lib/rails/engine/railties.rb b/railties/lib/rails/engine/railties.rb index e91bdbf1e5..d5ecd2e48d 100644 --- a/railties/lib/rails/engine/railties.rb +++ b/railties/lib/rails/engine/railties.rb @@ -18,6 +18,16 @@ module Rails Plugin.all(plugin_names, @config.paths["vendor/plugins"].existent) end end + + def self.railties + @railties ||= ::Rails::Railtie.subclasses.map(&:instance) + end + + def self.engines + @engines ||= ::Rails::Engine.subclasses.map(&:instance) + end + + delegate :railties, :engines, :to => "self.class" end end end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile index 12350309bf..25292f59ad 100755 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile @@ -14,3 +14,11 @@ Rake::RDocTask.new(:rdoc) do |rdoc| rdoc.rdoc_files.include('README.rdoc') rdoc.rdoc_files.include('lib/**/*.rb') end + +<% if full? && !options[:skip_active_record] -%> +namespace :app do + ENGINE_PATH = File.expand_path("..", __FILE__) + load File.expand_path("../<%= dummy_path -%>/Rakefile", __FILE__) +end +<% end -%> + diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb index d06fe7cbd0..dd4d2da4eb 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb @@ -1,7 +1,9 @@ require 'test_helper' class NavigationTest < ActionDispatch::IntegrationTest +<% unless options[:skip_active_record] -%> fixtures :all +<% end -%> # Replace this with your real tests. test "the truth" do diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb index 7b61047e77..791b901593 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb @@ -6,10 +6,5 @@ require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! -<% if full? && !options[:skip_active_record] -%> -# Run any available migration from application -ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__) -<% end -%> - # Load support files Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 2105585272..0d24821ff6 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -114,7 +114,7 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase end def test_ensure_that_tests_works_in_full_mode - run_generator [destination_root, "--full"] + run_generator [destination_root, "--full", "--skip_active_record"] FileUtils.cd destination_root `bundle install` assert_match /2 tests, 2 assertions, 0 failures, 0 errors/, `bundle exec rake test` diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 7548c6318e..05bd0c36cd 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -702,5 +702,24 @@ module RailtiesTest assert_equal "foo", Bukkits.table_name_prefix end + + test "fetching engine by path" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + end + end + RUBY + + boot_rails + require "#{rails_root}/config/environment" + + assert_equal Bukkits::Engine.instance, Rails::Engine.find(@plugin.path) + + # check expanding paths + engine_dir = @plugin.path.chomp("/").split("/").last + engine_path = File.join(@plugin.path, '..', engine_dir) + assert_equal Bukkits::Engine.instance, Rails::Engine.find(engine_path) + end end end |