Skip to content
This repository
Browse code

raise error for pending migration

can be configured by setting config.active_record.migration. Setting to :page_load will raise an error on each page refresh if there are migrations that are pending. Setting to :page_load is defaulted in development for new applications.
  • Loading branch information...
commit 96f19f6cf62fb4705a75cf4a81e4e2f145a4cee2 1 parent e5b3986
Richard Schneeman authored June 05, 2012
28  activerecord/lib/active_record/migration.rb
@@ -32,6 +32,12 @@ def initialize(name)
32 32
     end
33 33
   end
34 34
 
  35
+  class PendingMigrationError < ActiveRecordError#:nodoc:
  36
+    def initialize
  37
+      super("Migrations are pending run 'bundle exec rake db:migrate RAILS_ENV=#{ENV['RAILS_ENV']}' to resolve the issue")
  38
+    end
  39
+  end
  40
+
35 41
   # = Active Record Migrations
36 42
   #
37 43
   # Migrations can manage the evolution of a schema used by several physical
@@ -326,10 +332,28 @@ def initialize(name)
326 332
   class Migration
327 333
     autoload :CommandRecorder, 'active_record/migration/command_recorder'
328 334
 
  335
+
  336
+    # This class is used to verify that all migrations have been run before
  337
+    # loading a web page if config.active_record.migration_error is set to :page_load
  338
+    class CheckPending
  339
+      def initialize(app)
  340
+        @app = app
  341
+      end
  342
+
  343
+      def call(env)
  344
+        ActiveRecord::Migration.check_pending!
  345
+        status, headers, body = @app.call(env)
  346
+      end
  347
+    end
  348
+
329 349
     class << self
330 350
       attr_accessor :delegate # :nodoc:
331 351
     end
332 352
 
  353
+    def self.check_pending!
  354
+      raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator::needs_migrations?
  355
+    end
  356
+
333 357
     def self.method_missing(name, *args, &block) # :nodoc:
334 358
       (delegate || superclass.delegate).send(name, *args, &block)
335 359
     end
@@ -605,8 +629,8 @@ def current_version
605 629
         end
606 630
       end
607 631
 
608  
-      def needs_migration?
609  
-        current_version != last_version
  632
+      def needs_migrations?
  633
+        current_version < last_version
610 634
       end
611 635
 
612 636
       def last_version
7  activerecord/lib/active_record/railtie.rb
@@ -59,6 +59,13 @@ class Railtie < Rails::Railtie
59 59
       ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger }
60 60
     end
61 61
 
  62
+    initializer "active_record.migration_error" do |app|
  63
+      if config.active_record.delete(:migration_error) == :page_load
  64
+        config.app_middleware.insert_after "::ActionDispatch::Callbacks",
  65
+          "ActiveRecord::Migration::CheckPending"
  66
+      end
  67
+    end
  68
+
62 69
     initializer "active_record.set_configs" do |app|
63 70
       ActiveSupport.on_load(:active_record) do
64 71
         if app.config.active_record.delete(:whitelist_attributes)
4  activerecord/test/cases/migration_test.rb
@@ -63,12 +63,12 @@ def test_migrator_versions
63 63
     ActiveRecord::Migrator.up(migrations_path)
64 64
     assert_equal 3, ActiveRecord::Migrator.current_version
65 65
     assert_equal 3, ActiveRecord::Migrator.last_version
66  
-    assert_equal false, ActiveRecord::Migrator.needs_migration?
  66
+    assert_equal false, ActiveRecord::Migrator.needs_migrations?
67 67
 
68 68
     ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
69 69
     assert_equal 0, ActiveRecord::Migrator.current_version
70 70
     assert_equal 3, ActiveRecord::Migrator.last_version
71  
-    assert_equal true, ActiveRecord::Migrator.needs_migration?
  71
+    assert_equal true, ActiveRecord::Migrator.needs_migrations?
72 72
   end
73 73
 
74 74
   def test_create_table_with_force_true_does_not_drop_nonexisting_table
3  railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
@@ -26,6 +26,9 @@
26 26
   # Log the query plan for queries taking more than this (works
27 27
   # with SQLite, MySQL, and PostgreSQL).
28 28
   config.active_record.auto_explain_threshold_in_seconds = 0.5
  29
+
  30
+  # Raise an error on page load if there are pending migrations
  31
+  config.active_record.migration_error = :page_load
29 32
   <%- end -%>
30 33
 
31 34
   <%- unless options.skip_sprockets? -%>
2  railties/lib/rails/generators/rails/app/templates/test/test_helper.rb
@@ -4,6 +4,8 @@
4 4
 
5 5
 class ActiveSupport::TestCase
6 6
 <% unless options[:skip_active_record] -%>
  7
+  ActiveRecord::Migration.check_pending!
  8
+
7 9
   # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
8 10
   #
9 11
   # Note: You'll currently still have to declare fixtures explicitly in integration tests

0 notes on commit 96f19f6

Please sign in to comment.
Something went wrong with that request. Please try again.