Class: RailsAiBridge::Generators::InstallGenerator
- Inherits:
-
Rails::Generators::Base
- Object
- Rails::Generators::Base
- RailsAiBridge::Generators::InstallGenerator
- Defined in:
- lib/generators/rails_ai_bridge/install/install_generator.rb
Instance Method Summary collapse
-
#add_to_gitignore ⇒ void
Appends rails-ai-bridge-specific entries to .gitignore when the file exists and the entries are not already present.
-
#create_assistant_overrides_template ⇒ void
Creates the config/rails_ai_bridge/ directory with an overrides.md stub and an overrides.md.example reference file.
-
#create_initializer ⇒ void
Creates config/initializers/rails_ai_bridge.rb containing a commented configuration guide for rails-ai-bridge.
-
#create_mcp_config ⇒ void
Creates a
.mcp.jsonMCP server definition named "rails-ai-bridge". -
#generate_context_files ⇒ void
Calls RailsAiBridge.generate_context to write initial bridge files (CLAUDE.md, .cursorrules, etc.) according to the selected install profile.
-
#show_instructions ⇒ void
Prints post-install usage instructions to stdout: available rake tasks, generated file locations per AI assistant, MCP auto-discovery notes, and bridge mode options.
Instance Method Details
#add_to_gitignore ⇒ void
This method returns an undefined value.
Appends rails-ai-bridge-specific entries to .gitignore when the file exists and the entries are not already present. Does nothing if .gitignore is absent. Uses Thor's #append_to_file so the operation respects +--pretend+ (dry-run).
163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 163 def add_to_gitignore gitignore_path = '.gitignore' gitignore_full = File.join(destination_root, gitignore_path) return unless File.exist?(gitignore_full) content = File.read(gitignore_full) append = [] append << '.ai-context.json' unless content.include?('.ai-context.json') return unless append.any? append_to_file gitignore_path, "\n# rails-ai-bridge (JSON cache — markdown files should be committed)\n#{append.join("\n")}\n" say 'Updated .gitignore', :green end |
#create_assistant_overrides_template ⇒ void
This method returns an undefined value.
Creates the config/rails_ai_bridge/ directory with an overrides.md stub and an overrides.md.example reference file. Skips each file if it already exists so the method is safe to re-run (idempotent).
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 137 def create_assistant_overrides_template dir = 'config/rails_ai_bridge' empty_directory dir stub = File.join(destination_root, dir, 'overrides.md') unless File.exist?(stub) create_file "#{dir}/overrides.md", <<~MD <!-- rails-ai-bridge:omit-merge --> MD say "Created #{dir}/overrides.md (stub — remove omit-merge line when adding real rules)", :green end example = File.join(destination_root, dir, 'overrides.md.example') return if File.exist?(example) copy_file 'overrides.md.example', "#{dir}/overrides.md.example" say "Created #{dir}/overrides.md.example (reference outline, not merged)", :green end |
#create_initializer ⇒ void
This method returns an undefined value.
Creates config/initializers/rails_ai_bridge.rb containing a commented configuration guide for rails-ai-bridge. The generated initializer documents introspector presets (with interpolated counts), options for enabling/disabling introspectors, security exclusions (tables, models, paths), primary domain model hints, context/output controls, assistant override guidance, and a SECURITY CRITICAL HTTP MCP / auto_mount section with recommended authentication approaches.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 45 def create_initializer standard_count = RailsAiBridge::Configuration::PRESETS[:standard].size full_count = RailsAiBridge::Configuration::PRESETS[:full].size regulated_count = RailsAiBridge::Configuration::PRESETS[:regulated].size create_file 'config/initializers/rails_ai_bridge.rb', <<~RUBY # frozen_string_literal: true RailsAiBridge.configure do |config| # --- Introspector preset --- # :standard — #{standard_count} core introspectors (schema, models, routes, jobs, gems, conventions, controllers, tests, migrations) # :full — all #{full_count} introspectors (adds views, turbo, auth, API, config, assets, devops, etc.) # :regulated — #{regulated_count} introspectors — no schema/models/migrations (for apps with strict data governance) # config.preset = :standard # Or cherry-pick individual introspectors: # config.introspectors += %i[non_ar_models views turbo auth api] # Disable whole product categories at runtime (schema + models + migrations, optional :non_ar_models, api, views/turbo/i18n): # config.disabled_introspection_categories << :domain_metadata # --- Security exclusions --- # Tables to hide from schema + model introspection (exact name or glob, e.g. "pii_*"): # config.excluded_tables += %w[secrets audit_logs pii_*] # Models to exclude from introspection: # config.excluded_models += %w[AdminUser InternalThing] # Primary domain models (semantic tier: core_entity in introspection & Claude rules): # config.core_models += %w[User Order Project] # Paths excluded from rails_search_code: # config.excluded_paths += %w[vendor/bundle] # --- Context output --- # :compact — ≤150 lines, references MCP tools for details (default) # :full — full dump (good for small apps) # config.context_mode = :compact # config.claude_max_lines = 150 # config.max_tool_response_chars = 120_000 # Team rules merged into compact Copilot/Codex output (remove omit-merge line when ready): # config.assistant_overrides_path = "config/rails_ai_bridge/overrides.md" # Compact model list caps (0 = MCP pointer only, no names listed): # config.copilot_compact_model_list_limit = 5 # config.codex_compact_model_list_limit = 3 # ========================================================================== # HTTP MCP / auto_mount — SECURITY CRITICAL # ========================================================================== # Exposes read-only MCP tools over HTTP. Still reveals routes, schema, and # code layout — treat as sensitive. Prefer stdio (`rails ai:serve`) for local # AI clients. # # In production you MUST configure one auth mechanism AND set # allow_auto_mount_in_production = true. Options (highest priority first): # # 1. JWT decoder (no JWT gem required — supply your own lambda): # config.mcp_jwt_decoder = ->(token) { # JWT.decode(token, credentials.jwt_secret, true, algorithm: "HS256").first # rescue JWT::DecodeError, JWT::ExpiredSignature, JWT::ImmatureSignature # nil # } # # 2. Token resolver (Devise, database lookup, etc.): # config.mcp_token_resolver = ->(token) { User.find_by(mcp_api_token: token) } # # 3. Static shared secret: # config.http_mcp_token = "generate-a-long-random-secret" # # ENV["RAILS_AI_BRIDGE_MCP_TOKEN"] overrides this when set # # IMPORTANT: Token comparison is timing-safe but does NOT prevent # brute-force guessing. Add rate limiting on the MCP endpoint in # production (e.g. Rack::Attack throttle on config.http_path). # # config.auto_mount = false # config.allow_auto_mount_in_production = false # config.http_path = "/mcp" # config.http_port = 6029 end RUBY say 'Created config/initializers/rails_ai_bridge.rb', :green end |
#create_mcp_config ⇒ void
This method returns an undefined value.
Creates a .mcp.json MCP server definition named "rails-ai-bridge".
The created file configures an MCP server that runs bundle exec rails ai:serve and is intended
for auto-discovery by tools such as Claude Code and Cursor.
23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 23 def create_mcp_config mcp_config = { mcpServers: { 'rails-ai-bridge' => { command: 'bundle', args: ['exec', 'rails', 'ai:serve'] } } } create_file '.mcp.json', "#{JSON.pretty_generate(mcp_config)}\n" say 'Created .mcp.json (auto-discovered by Claude Code, Cursor, etc.)', :green end |
#generate_context_files ⇒ void
This method returns an undefined value.
Calls RailsAiBridge.generate_context to write initial bridge files (CLAUDE.md, .cursorrules, etc.) according to the selected install profile. Skipped when +Rails.application+ is not available. Any StandardError is rescued and reported with the error class only — no raw message or sensitive path/credential details are printed or logged. +Rails.logger.debug+ receives only the exception class name and a short 12-character fingerprint derived from it, never the raw exception message.
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 187 def generate_context_files say '' say 'Generating AI bridge files...', :yellow return handle_skip_context if [:skip_context] return handle_no_rails_app unless Rails.application begin profile = resolve_profile rescue ArgumentError say ' Run `rails generate rails_ai_bridge:install --profile=minimal` (or full/custom/mcp).', :yellow return end @selected_profile = profile case profile when 'mcp' say ' Skipped (MCP-only profile). Run `rails ai:bridge` to generate context files later.', :yellow return when 'minimal', 'full' formats = ProfileResolver.formats_for(profile) split_rules = ProfileResolver.split_rules_for(profile) return generate_context_for_formats(formats, split_rules: split_rules) end return say(' Skipped. Run `rails ai:bridge` to generate context files later.', :yellow) unless yes?('Generate AI assistant context files? (y/n)') formats = collect_selected_formats return say(' No formats selected. Run `rails ai:bridge` to generate context files later.', :yellow) if formats.empty? generate_context_for_formats(formats, split_rules: true) end |
#show_instructions ⇒ void
This method returns an undefined value.
Prints post-install usage instructions to stdout: available rake tasks, generated file locations per AI assistant, MCP auto-discovery notes, and bridge mode options.
225 226 227 228 229 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 225 def show_instructions return show_skip_context_instructions if [:skip_context] show_full_instructions end |