Repository: Shopify/ruby-lsp-rails (Ruby)

Issue:
"Migrations are pending" popup is too aggressive
I often am running `bin/rails g migration SomeMigration` to get a blank migration and then writing it my editor instead of the generator. When I do this, the "Migrations are pending" popup immediately displays and asks me to run the (empty) migration.

From my perspective:
- I would like this popup to ignore empty migrations that I just created
- I would like the ability to disable this particular popup -- I wasn't able to find out how to do this in the list of "features enabled" in the main LSP

I think this has the potential for people to run the empty migration without realizing it ("I just click that button always") and then write the actual migration code and be confused why the changes don't seem to work (migration was marked as run so it doesnt re-run)


Discussion: Hi Matt, thank you for the suggestion. We will consider some options for this.
@swanson We discussed as a team and are considering this approach:

We won't prompt to run the migrations if the most recent migration is empty.

A migration would be considered empty if it has no methods:

```
class CreateFoo < ActiveRecord::Migration[8.0]
end
```

or if it contains _only_ a timestamp column (which the generator may add by default).

```
class CreateFoo < ActiveRecord::Migration[8.0]
  def change
    create_table :foos do |t|
      t.timestamps
    end
  end
end
```

If were were do this, I don't think we wouldn't need an option to disable the popup.

The only downside I can think of is if you save the migration mid-way through writing it, then it would trigger the popup.

Any thoughts?
If I run `bin/rails g migration ThisIsEmpty`

the output is

```
class ThisIsEmpty < ActiveRecord::Migration[8.0]
  def change
  end
end
```

so I don't think that would solve my particular issue because the LSP would not consider that empty, correct?
Maybe "smart detection of empty migrations" is not the right solution, but it does seem like people (myself included) will want a way to turn off this popup, as it is pretty invasive if you aren't using it. The Rails "run pending migration" button is also an option so I don't believe this functionality is novel enough to be "always on".
> so I don't think that would solve my particular issue because the LSP would not consider that empty, correct?

We can have it treat that as empty too.
@swanson we're considering [this](https://github.com/Shopify/ruby-lsp-rails/pull/553) as an alternative.
> [@swanson](https://github.com/swanson) we're considering [this](https://github.com/Shopify/ruby-lsp-rails/pull/553) as an alternative.

Thanks but I'd really just like a way to disable this specific feature at this point!
This is also an annoyance for me. #553 is an improvement I suppose, but it still seems like a half measure. What if the popup also included a button to open/edit the pending migration files?

That would actually be useful immediately after running `rails generate migration`, as it currently takes several clicks to open the newly generated file.
@swanson do you think that would be helpful? I would also prefer that over checking timestamps.
I use https://marketplace.visualstudio.com/items?itemName=tmikoss.rails-latest-migration so it wouldn't be something I would use. I can currently (without the LSP at all), run `bin/rails g migration` and then use this addon to quickly jump to the generated migration.

Personally, I still think an option to completely disable this would be my preference. I've not used it once, I use the built-in Rails "run pending migrations" button if there are new migrations from a merge that I am missing. And every time I generate a migration, it is popping up and I have to dismiss.
Hi, I appreciate the intension with the migration pending popup, but as @swanson mentioned it's really aggressive to the point that it's getting in the way of development. Also adding that rails in development mode errors and reminds you that there are pending migration, so it would be ideal to have this configurable to be disabled.
As an additional thought, having to an option to dismiss and don't be reminded of migrations for the latest pending migration would be a decent step in the right direction. However this should be in addition to being able to disable the reminder all together. 
We discussed among the team and decided to allow disabling the dialog https://github.com/Shopify/ruby-lsp-rails/pull/570. It's easier than trying to detect what the user intention or preference is.

> having to an option to dismiss and don't be reminded of migrations for the latest pending migration would be a decent step in the right direction

The server can't modify the user's settings, so that would require the Ruby LSP to start allowing settings to be stored in some file database. That would also create an extra level of setting hierarchy, since editors like VS Code allow for user and workspace settings, but then we would additionally have the Ruby LSP's own setting store, which starts getting overly complicated.

If the LSP specification were to formalize a way for servers to suggest or prompt users to modify their settings, that would lead to a better experience and significantly less complicated implementation.



Fix (patch):
diff --git a/lib/ruby_lsp/ruby_lsp_rails/addon.rb b/lib/ruby_lsp/ruby_lsp_rails/addon.rb
index 6f137c6f..0a31d353 100644
--- a/lib/ruby_lsp/ruby_lsp_rails/addon.rb
+++ b/lib/ruby_lsp/ruby_lsp_rails/addon.rb
@@ -32,6 +32,12 @@ def initialize
         @rails_runner_client = T.let(NullClient.new, RunnerClient)
         @global_state = T.let(nil, T.nilable(GlobalState))
         @outgoing_queue = T.let(nil, T.nilable(Thread::Queue))
+        @settings = T.let(
+          {
+            enablePendingMigrationsPrompt: true,
+          },
+          T::Hash[Symbol, T.untyped],
+        )
         @addon_mutex = T.let(Mutex.new, Mutex)
         @client_mutex = T.let(Mutex.new, Mutex)
         @client_mutex.lock
@@ -58,6 +64,9 @@ def activate(global_state, outgoing_queue)
         @outgoing_queue = outgoing_queue
         @outgoing_queue << Notification.window_log_message("Activating Ruby LSP Rails add-on v#{VERSION}")
 
+        addon_settings = @global_state.settings_for_addon(name)
+        @settings.merge!(addon_settings) if addon_settings
+
         register_additional_file_watchers(global_state: global_state, outgoing_queue: outgoing_queue)
 
         # Start booting the real client in a background thread. Until this completes, the client will be a NullClient
@@ -258,6 +267,7 @@ def fixture_file_watcher
       def offer_to_run_pending_migrations
         return unless @outgoing_queue
         return unless @global_state&.client_capabilities&.window_show_message_supports_extra_properties
+        return unless @settings[:enablePendingMigrationsPrompt]
 
         migration_message = @rails_runner_client.pending_migrations_message
         return unless migration_message