Class: HasGeoLookup::IndexChecker
- Inherits:
-
Object
- Object
- HasGeoLookup::IndexChecker
- Defined in:
- lib/has_geo_lookup/index_checker.rb
Overview
Utility class for checking and recommending database indexes for optimal performance
This class analyzes models that include HasGeoLookup and provides recommendations for database indexes to optimize geographic queries. It can detect missing indexes and optionally create them automatically.
Constant Summary collapse
- REQUIRED_COLUMNS =
Required columns for HasGeoLookup functionality
[ { name: :latitude, type: :decimal, precision: 10, scale: 6 }, { name: :longitude, type: :decimal, precision: 10, scale: 6 } ].freeze
- RECOMMENDED_INDEXES =
Recommended indexes for models using HasGeoLookup functionality
{ coordinate_indexes: [ { columns: [:latitude, :longitude], name: 'coordinates' }, { columns: [:latitude], name: 'latitude' }, { columns: [:longitude], name: 'longitude' } ], geo_attribute_indexes: [ { columns: [:country], name: 'country' }, { columns: [:state_or_province], name: 'state_or_province' }, { columns: [:city], name: 'city' }, { columns: [:postal_code], name: 'postal_code' } ] }.freeze
Class Method Summary collapse
-
.analyze_all_models ⇒ Hash
Analyze all models that include HasGeoLookup.
-
.check_missing_columns(model) ⇒ Array<Hash>
Check for missing required columns in a model.
-
.check_model(model) ⇒ Hash
Check index coverage for a specific model.
-
.generate_index_migration(model = nil) ⇒ String
Generate a Rails migration file for creating missing columns and indexes.
-
.performance_report ⇒ String
Generate a performance report for HasGeoLookup usage.
Class Method Details
.analyze_all_models ⇒ Hash
Analyze all models that include HasGeoLookup
Scans the application for models that include HasGeoLookup and analyzes their index coverage for geographic operations.
58 59 60 61 62 63 64 65 66 67 |
# File 'lib/has_geo_lookup/index_checker.rb', line 58 def analyze_all_models results = {} # Find all models that include HasGeoLookup models_with_geo_lookup.each do |model| results[model.name] = check_model(model) end results end |
.check_missing_columns(model) ⇒ Array<Hash>
Check for missing required columns in a model
132 133 134 135 136 |
# File 'lib/has_geo_lookup/index_checker.rb', line 132 def check_missing_columns(model) REQUIRED_COLUMNS.reject do |col_def| model.column_names.include?(col_def[:name].to_s) end end |
.check_model(model) ⇒ Hash
Check index coverage for a specific model
Analyzes the database indexes for a model and compares them against the recommended indexes for HasGeoLookup functionality.
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 |
# File 'lib/has_geo_lookup/index_checker.rb', line 81 def check_model(model) return { error: "Model does not include HasGeoLookup" } unless model.include?(HasGeoLookup) table_name = model.table_name existing_indexes = get_existing_indexes(table_name) missing_columns = check_missing_columns(model) missing_indexes = [] recommendations = [] # Check coordinate indexes (always recommended, but only if columns exist or will be created) RECOMMENDED_INDEXES[:coordinate_indexes].each do |index_def| # Check if all required columns exist or will be added columns_available = index_def[:columns].all? do |col| model.column_names.include?(col.to_s) || missing_columns.any? { |mc| mc[:name] == col } end next unless columns_available unless has_index?(existing_indexes, index_def[:columns]) missing_indexes << index_def recommendations << generate_index_command(table_name, index_def) end end # Check geo attribute indexes (only for columns that exist) RECOMMENDED_INDEXES[:geo_attribute_indexes].each do |index_def| columns = index_def[:columns].select { |col| model.column_names.include?(col.to_s) } next if columns.empty? unless has_index?(existing_indexes, columns) index_def_with_existing_cols = index_def.merge(columns: columns) missing_indexes << index_def_with_existing_cols recommendations << generate_index_command(table_name, index_def_with_existing_cols) end end { table_name: table_name, missing_columns: missing_columns.length, missing_column_details: missing_columns, missing_indexes: missing_indexes.length, missing_index_details: missing_indexes, recommendations: recommendations, existing_indexes: existing_indexes.map { |idx| idx.columns.sort } } end |
.generate_index_migration(model = nil) ⇒ String
Generate a Rails migration file for creating missing columns and indexes
Creates a timestamped migration file containing all missing columns and indexes for optimal HasGeoLookup performance. This is the recommended approach for production use as it maintains proper migration history and version control.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/has_geo_lookup/index_checker.rb', line 153 def generate_index_migration(model = nil) if model models_to_check = { model.name => check_model(model) } else models_to_check = analyze_all_models end models_with_missing = models_to_check.select do |_, analysis| (analysis[:missing_columns] || 0) > 0 || (analysis[:missing_indexes] || 0) > 0 end if models_with_missing.empty? puts "✓ All models have optimal columns and indexes for HasGeoLookup" return nil end # Generate migration content migration_name = "add_has_geo_lookup_setup" migration_name += "_for_#{model.name.underscore}" if model migration_content = generate_migration_content(models_with_missing) migration_path = create_migration_file(migration_name, migration_content) puts "✓ Generated migration: #{migration_path}" puts "Run 'rails db:migrate' to apply the columns and indexes" migration_path end |
.performance_report ⇒ String
Generate a performance report for HasGeoLookup usage
Creates a comprehensive report showing index coverage across all models that use HasGeoLookup functionality.
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 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/has_geo_lookup/index_checker.rb', line 188 def performance_report results = analyze_all_models if results.empty? return "No models found that include HasGeoLookup" end report = [] report << "=" * 80 report << "HasGeoLookup Performance Analysis" report << "=" * 80 total_missing = 0 results.each do |model_name, analysis| report << "\n#{model_name} (table: #{analysis[:table_name]})" report << "-" * 40 missing_columns = analysis[:missing_columns] || 0 missing_indexes = analysis[:missing_indexes] || 0 if missing_columns.zero? && missing_indexes.zero? report << "✓ All recommended columns and indexes present" else if missing_columns > 0 total_missing += missing_columns report << "⚠ #{missing_columns} missing column#{'s' if missing_columns > 1}: #{analysis[:missing_column_details].map { |c| c[:name] }.join(', ')}" end if missing_indexes > 0 total_missing += missing_indexes report << "⚠ #{missing_indexes} missing index#{'es' if missing_indexes > 1}" report << "\nRecommendations:" analysis[:recommendations].each do |rec| report << " #{rec}" end end end report << "\nExisting indexes: #{analysis[:existing_indexes].join(', ')}" if analysis[:existing_indexes].any? end report << "\n" + "=" * 80 report << "Summary: #{total_missing} missing columns/indexes across #{results.length} model#{'s' if results.length != 1}" if total_missing > 0 report << "\nTo create missing columns and indexes, run:" report << " rake has_geo_lookup:create_setup" end report << "=" * 80 report.join("\n") end |