Class: Mbeditor::Rack::PendingMigrationBypass
- Inherits:
-
Object
- Object
- Mbeditor::Rack::PendingMigrationBypass
- Defined in:
- lib/mbeditor/rack/pending_migration_bypass.rb
Overview
Wraps ActiveRecord::Migration::CheckPending so a pending migration cannot lock the developer out of the one tool they need to fix it.
Rails inserts CheckPending after ActionDispatch::Callbacks whenever
config.active_record.migration_error is :page_load — the default a real
rails new app carries in development. From then until the migration is
run, EVERY request raises PendingMigrationError, and that included all of
mbeditor's: the file tree, opening a file, and saving one. The editor was
unusable in precisely the situation it exists to get you out of, and the
migration could not be edited to fix it.
An earlier attempt rescued the error above CheckPending and answered mbeditor's own paths with a fallback shell and a 503 for every XHR. That left the shell without its stylesheets or JavaScript — those live under /assets, which is not an mbeditor path, so they still 500'd — and even once loaded every API call was a 503. Rescuing after the fact was the wrong shape; the check simply must not apply to this traffic.
So the check still runs (it is file-watcher backed and cheap after the first call, and non-editor traffic must keep Rails' behaviour exactly), but for editor traffic the error is recorded and swallowed rather than raised, and the request proceeds. CheckPending raises before it calls anything downstream, so dispatching afterwards runs the request once, not twice.
The recorded message is what surfaces the warning banner, so the developer is still told to migrate — they are just no longer prevented from working.
Constant Summary collapse
- DEFAULT_ASSET_PREFIX =
"/assets"- PENDING_HEADER =
Announced on every bypassed response so the editor can warn about a migration created mid-session, not only one that existed at page load.
"X-Mbeditor-Pending-Migration"
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, file_watcher: nil) ⇒ PendingMigrationBypass
constructor
A new instance of PendingMigrationBypass.
Constructor Details
#initialize(app, file_watcher: nil) ⇒ PendingMigrationBypass
Returns a new instance of PendingMigrationBypass.
37 38 39 40 41 42 43 44 45 |
# File 'lib/mbeditor/rack/pending_migration_bypass.rb', line 37 def initialize(app, file_watcher: nil) @app = app @checked = if file_watcher ActiveRecord::Migration::CheckPending.new(app, file_watcher: file_watcher) else ActiveRecord::Migration::CheckPending.new(app) end end |
Instance Method Details
#call(env) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/mbeditor/rack/pending_migration_bypass.rb', line 51 def call(env) return @checked.call(env) unless editor_traffic?(env) begin result = @checked.call(env) # The check passed, so anything recorded earlier is stale. Mbeditor::PendingMigrations.clear result rescue StandardError => e raise unless pending_migration_error?(e) Mbeditor::PendingMigrations.note(e.) status, headers, body = @app.call(env) headers[PENDING_HEADER] = header_safe(e.) [status, headers, body] end end |