Module: RailsConsolePro::ModelValidator

Extended by:
ModelValidator
Included in:
ModelValidator
Defined in:
lib/rails_console_pro/model_validator.rb

Overview

Utility module for validating ActiveRecord models and handling edge cases

Instance Method Summary collapse

Instance Method Details

#abstract_class?(model_class) ⇒ Boolean

Check if model is abstract

Returns:

  • (Boolean)


28
29
30
31
# File 'lib/rails_console_pro/model_validator.rb', line 28

def abstract_class?(model_class)
  return false unless valid_model?(model_class)
  !!model_class.abstract_class?
end

#has_table?(model_class) ⇒ Boolean

Check if model has a database table

Returns:

  • (Boolean)


16
17
18
19
20
21
22
23
24
25
# File 'lib/rails_console_pro/model_validator.rb', line 16

def has_table?(model_class)
  return false unless valid_model?(model_class)
  return false if abstract_class?(model_class)
  
  # Use ActiveRecord's table_exists? method
  model_class.table_exists?
rescue => e
  # If table_exists? fails, assume no table
  false
end

#has_timestamp_column?(model_class, column_name = 'created_at') ⇒ Boolean

Check if model has created_at column (for growth rate calculations)

Returns:

  • (Boolean)


43
44
45
46
47
48
# File 'lib/rails_console_pro/model_validator.rb', line 43

def has_timestamp_column?(model_class, column_name = 'created_at')
  return false unless valid_model?(model_class)
  return false unless has_table?(model_class)
  
  model_class.column_names.include?(column_name.to_s)
end

#large_table?(model_class, threshold: nil) ⇒ Boolean

Check if table is very large (for performance considerations)

Returns:

  • (Boolean)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/rails_console_pro/model_validator.rb', line 51

def large_table?(model_class, threshold: nil)
  return false unless valid_model?(model_class)
  return false unless has_table?(model_class)
  
  threshold ||= RailsConsolePro.config.stats_large_table_threshold
  
  begin
    count = model_class.count
    count > threshold
  rescue => e
    # If count fails, assume not large (safer)
    false
  end
end

#model_info(model_class) ⇒ Object

Get model type information



67
68
69
70
71
72
73
74
75
76
# File 'lib/rails_console_pro/model_validator.rb', line 67

def model_info(model_class)
  {
    valid: valid_model?(model_class),
    has_table: has_table?(model_class),
    abstract: abstract_class?(model_class),
    sti: sti_model?(model_class),
    has_created_at: has_timestamp_column?(model_class),
    large: large_table?(model_class)
  }
end

#safe_associations(model_class, macro = nil) ⇒ Object

Safely get associations



164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/rails_console_pro/model_validator.rb', line 164

def safe_associations(model_class, macro = nil)
  return [] unless valid_model?(model_class)
  
  begin
    if macro
      model_class.reflect_on_all_associations(macro)
    else
      model_class.reflect_on_all_associations
    end
  rescue => e
    []
  end
end

#safe_column_names(model_class) ⇒ Object

Safely get column names



125
126
127
128
129
130
131
132
133
134
# File 'lib/rails_console_pro/model_validator.rb', line 125

def safe_column_names(model_class)
  return [] unless valid_model?(model_class)
  return [] unless has_table?(model_class)
  
  begin
    model_class.column_names
  rescue => e
    []
  end
end

#safe_columns(model_class) ⇒ Object

Safely get columns



137
138
139
140
141
142
143
144
145
146
# File 'lib/rails_console_pro/model_validator.rb', line 137

def safe_columns(model_class)
  return [] unless valid_model?(model_class)
  return [] unless has_table?(model_class)
  
  begin
    model_class.columns
  rescue => e
    []
  end
end

#safe_indexes(model_class) ⇒ Object

Safely get indexes



149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/rails_console_pro/model_validator.rb', line 149

def safe_indexes(model_class)
  return [] unless valid_model?(model_class)
  return [] unless has_table?(model_class)
  
  begin
    table_name = safe_table_name(model_class)
    return [] unless table_name
    
    model_class.connection.indexes(table_name)
  rescue => e
    []
  end
end

#safe_table_name(model_class) ⇒ Object

Safely get table name



114
115
116
117
118
119
120
121
122
# File 'lib/rails_console_pro/model_validator.rb', line 114

def safe_table_name(model_class)
  return nil unless valid_model?(model_class)
  
  begin
    model_class.table_name
  rescue => e
    nil
  end
end

#sti_model?(model_class) ⇒ Boolean

Check if model uses Single Table Inheritance (STI)

Returns:

  • (Boolean)


34
35
36
37
38
39
40
# File 'lib/rails_console_pro/model_validator.rb', line 34

def sti_model?(model_class)
  return false unless valid_model?(model_class)
  return false unless has_table?(model_class)
  
  # Check if model has a type column (STI indicator)
  model_class.column_names.include?(model_class.inheritance_column)
end

#unusual_inheritance?(model_class) ⇒ Boolean

Check if model has unusual inheritance patterns

Returns:

  • (Boolean)


179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/rails_console_pro/model_validator.rb', line 179

def unusual_inheritance?(model_class)
  return false unless valid_model?(model_class)
  
  # Check for non-standard inheritance patterns
  # This is a heuristic - models that inherit from non-standard base classes
  base_class = model_class.superclass
  
  # If superclass is not ActiveRecord::Base and not abstract, it's unusual
  if base_class != ActiveRecord::Base && !base_class.abstract_class?
    # Check if it's a legitimate ActiveRecord model
    return true unless base_class < ActiveRecord::Base
  end
  
  false
rescue => e
  # If we can't determine, assume it's fine
  false
end

#valid_associations?(model_class, association_name) ⇒ Boolean

Check if associations are valid (not empty or broken)

Returns:

  • (Boolean)


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/rails_console_pro/model_validator.rb', line 96

def valid_associations?(model_class, association_name)
  return false unless valid_model?(model_class)
  
  begin
    association = model_class.reflect_on_association(association_name)
    return false unless association
    
    # Check if associated class exists
    associated_class = association.klass
    return false unless associated_class < ActiveRecord::Base
    
    true
  rescue => e
    false
  end
end

#valid_model?(model_class) ⇒ Boolean

Check if model is a valid ActiveRecord model

Returns:

  • (Boolean)


9
10
11
12
13
# File 'lib/rails_console_pro/model_validator.rb', line 9

def valid_model?(model_class)
  return false unless model_class.is_a?(Class)
  return false unless model_class < ActiveRecord::Base
  true
end

#validate_for_schema(model_class) ⇒ Object

Validate model and return error message if invalid



79
80
81
82
83
84
85
# File 'lib/rails_console_pro/model_validator.rb', line 79

def validate_for_schema(model_class)
  return "Not an ActiveRecord model" unless valid_model?(model_class)
  return "Abstract class - no database table" if abstract_class?(model_class)
  return "Model has no database table" unless has_table?(model_class)
  
  nil # Valid
end

#validate_for_stats(model_class) ⇒ Object

Validate model and return error message if invalid for stats



88
89
90
91
92
93
# File 'lib/rails_console_pro/model_validator.rb', line 88

def validate_for_stats(model_class)
  schema_error = validate_for_schema(model_class)
  return schema_error if schema_error
  
  nil # Valid
end

#validate_model!(model_class) ⇒ Object

Validate model and raise error if invalid (for use in initializers)



199
200
201
202
203
204
# File 'lib/rails_console_pro/model_validator.rb', line 199

def validate_model!(model_class)
  unless valid_model?(model_class)
    raise ArgumentError, "#{model_class} is not an ActiveRecord model"
  end
  model_class
end

#validate_model_for_schema!(model_class) ⇒ Object

Validate model for schema inspection and raise error if invalid



207
208
209
210
211
212
213
214
215
216
# File 'lib/rails_console_pro/model_validator.rb', line 207

def validate_model_for_schema!(model_class)
  validate_model!(model_class)
  if abstract_class?(model_class)
    raise ArgumentError, "#{model_class} is an abstract class and has no database table"
  end
  unless has_table?(model_class)
    raise ArgumentError, "#{model_class} has no database table"
  end
  model_class
end