-
Notifications
You must be signed in to change notification settings - Fork 30
Use middleware instead Rails controller for model query #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# typed: strict | ||
# frozen_string_literal: true | ||
|
||
module RubyLsp | ||
module Rails | ||
class Middleware | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might later want to consider extracting some of this into There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO, we don't want to encourage extension authors doing this kind of work themselves. It's the same as we don't want them to implement their own visitor, but a listener to a specific request. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's what I mean. Things like the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But if we won't want them to do this, what's the point of extracting them to This is Rack/Rails specific pattern and not what There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with Stan here, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there could be other neat extensions powered by a similar mechanism, but I agree with not trying to optimize for that until we actually have more real-world examples. |
||
extend T::Sig | ||
|
||
PATH_REGEXP = %r{/ruby_lsp_rails/models/(?<model_name>.+)} | ||
|
||
sig { params(app: T.untyped).void } | ||
def initialize(app) | ||
@app = app | ||
end | ||
|
||
sig { params(env: T::Hash[T.untyped, T.untyped]).returns(T::Array[T.untyped]) } | ||
def call(env) | ||
request = ActionDispatch::Request.new(env) | ||
# TODO: improve the model name regex | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is fine for now. Once we add support for namespaces it may need adjusted. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that we can keep it for the time being. In the future, we may need a simple router just to make the codebase maintainable. Something like return @app.call(env) unless request.path.start_with?("/ruby_lsp_rails/")
endpoint, argument = request.path.delete_prefix("/ruby_lsp_rails/").split("/")
case endpoint
when "models"
# ...
when "jobs"
# ...
end |
||
match = request.path.match(PATH_REGEXP) | ||
|
||
if match | ||
resolve_database_info_from_model(match[:model_name]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: We could return early here, then change There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think def foo
1 / 0
ensure
"bar"
end
puts foo
Even if it works, I think it only reduces one But I will see if I can reduce the number of conditions here. |
||
else | ||
@app.call(env) | ||
end | ||
rescue | ||
@app.call(env) | ||
end | ||
|
||
private | ||
|
||
sig { params(model_name: String).returns(T::Array[T.untyped]) } | ||
def resolve_database_info_from_model(model_name) | ||
const = ActiveSupport::Inflector.safe_constantize(model_name) | ||
|
||
if const && const < ActiveRecord::Base | ||
begin | ||
schema_file = ActiveRecord::Tasks::DatabaseTasks.schema_dump_path(const.connection.pool.db_config) | ||
rescue => e | ||
warn("Could not locate schema: #{e.message}") | ||
end | ||
|
||
body = JSON.dump({ | ||
columns: const.columns.map { |column| [column.name, column.type] }, | ||
schema_file: schema_file, | ||
}) | ||
|
||
[200, { "Content-Type" => "application/json" }, [body]] | ||
else | ||
not_found | ||
end | ||
end | ||
|
||
sig { returns(T::Array[T.untyped]) } | ||
def not_found | ||
[404, { "Content-Type" => "text/plain" }, ["Not Found"]] | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# typed: strict | ||
# frozen_string_literal: true | ||
|
||
require "ruby_lsp_rails/middleware" | ||
|
||
module RubyLsp | ||
module Rails | ||
class Railtie < ::Rails::Railtie | ||
initializer "ruby_lsp_rails.setup" do |app| | ||
app.config.middleware.insert_after(ActionDispatch::ShowExceptions, RubyLsp::Rails::Middleware) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, what happens if the application doesn't have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It'll raise an exception saying there's no But this is one of the key middlewares in Rails. If someone removes it, that's probably not something we'd want to support. |
||
|
||
config.after_initialize do |_app| | ||
if defined?(::Rails::Server) | ||
ssl_enable, host, port = ::Rails::Server::Options.new.parse!(ARGV).values_at(:SSLEnable, :Host, :Port) | ||
app_uri = "#{ssl_enable ? "https" : "http"}://#{host}:#{port}" | ||
File.write("#{::Rails.root}/tmp/app_uri.txt", app_uri) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why the
Gemfile.lock
was 'out of sync' but I was seeing these same changes locally so 👍 to this.