Module: RailsAiContext::SchemaAdapter
- Defined in:
- lib/rails_ai_context/schema_adapter.rb
Overview
One answer to "which database is this app on", for every surface that asks.
SchemaIntrospector writes static_parse when it read db/schema.rb
instead of the connection. That is an internal detail: printed raw it names
a database that does not exist. Four call sites each grew their own
substitute and gave three different answers for one app - the generated
CLAUDE.md said PostgreSQL, rails_get_schema said unknown, rails ai:inspect
said static_parse. This is the seam they share.
Constant Summary collapse
- PLACEHOLDERS =
Values that mean "no adapter was observed", not "the adapter is X".
%w[static_parse unknown].freeze
- GEM_ADAPTERS =
Gemfile display names, only as the last resort.
{ "pg" => "PostgreSQL", "mysql2" => "MySQL", "trilogy" => "MySQL", "sqlite3" => "SQLite" }.freeze
- DIALECTS =
structure.sql dialects, as SchemaIntrospector records them.
{ "postgresql" => "PostgreSQL", "mysql" => "MySQL", "sqlite" => "SQLite" }.freeze
Class Method Summary collapse
- .from_configurations(context) ⇒ Object
- .from_dialect(schema) ⇒ Object
-
.from_gems(context) ⇒ Object
Last, and order-independent: an app with both
pgandsqlite3gets the same answer here as anywhere else, rather than depending on which match a loop happened to see last. -
.label(context) ⇒ String
The adapter to show, never an internal placeholder.
- .placeholder?(adapter) ⇒ Boolean
Class Method Details
.from_configurations(context) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/rails_ai_context/schema_adapter.rb', line 51 def from_configurations(context) multi = context[:multi_database] return nil unless Serializers::SectionGuard.usable?(multi) primary = Array(multi[:databases]).find { |db| db[:name].to_s == "primary" } || Array(multi[:databases]).first adapter = primary&.dig(:adapter) return nil if placeholder?(adapter) # These are ActiveRecord adapter names (`postgresql`, `sqlite3`), not gem # names. The two overlap by accident at sqlite3/mysql2/trilogy, so # reading only GEM_ADAPTERS let `postgresql` fall through raw - a Postgres # app rendered "Database: postgresql" beside a SQLite app's "SQLite". DIALECTS[adapter.to_s] || GEM_ADAPTERS[adapter.to_s] || adapter end |
.from_dialect(schema) ⇒ Object
67 68 69 70 71 |
# File 'lib/rails_ai_context/schema_adapter.rb', line 67 def from_dialect(schema) return nil unless schema.is_a?(Hash) DIALECTS[schema[:dialect].to_s] end |
.from_gems(context) ⇒ Object
Last, and order-independent: an app with both pg and sqlite3 gets the
same answer here as anywhere else, rather than depending on which match
a loop happened to see last.
76 77 78 79 80 81 82 83 |
# File 'lib/rails_ai_context/schema_adapter.rb', line 76 def from_gems(context) gems = context[:gems] return nil unless Serializers::SectionGuard.usable?(gems) names = Array(gems[:notable_gems]).map { |g| g[:name].to_s } GEM_ADAPTERS.each_key { |gem_name| return GEM_ADAPTERS[gem_name] if names.include?(gem_name) } nil end |
.label(context) ⇒ String
Returns the adapter to show, never an internal placeholder.
35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/rails_ai_context/schema_adapter.rb', line 35 def label(context) context = {} unless context.is_a?(Hash) schema = context[:schema] observed = schema.is_a?(Hash) ? schema[:adapter] : nil return observed unless placeholder?(observed) # Best first: the app's own database config, which needs no connection. # Then the dialect parsed out of structure.sql. Only then the Gemfile, # which is a guess - an app can carry two adapter gems. from_configurations(context) || from_dialect(schema) || from_gems(context) || "unknown" end |
.placeholder?(adapter) ⇒ Boolean
47 48 49 |
# File 'lib/rails_ai_context/schema_adapter.rb', line 47 def placeholder?(adapter) adapter.nil? || PLACEHOLDERS.include?(adapter.to_s) end |