Exception: ModelSchema::SchemaError

Inherits:
StandardError
  • Object
show all
Defined in:
lib/model_schema/schema_error.rb

Overview

Tracks differences between the expected schema and database table schema.

Constant Summary collapse

TYPE_EXTRA =
:extra
TYPE_MISSING =
:missing
TYPE_MISMATCH =
:mismatch

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(table_name, schema_diffs) ⇒ SchemaError

Creates a SchemaError for the given table with an array of schema differences. Each element of schema_diffs should be a hash of the following form:

:field => if a column is different, use FIELD_COLUMNS;

if an index is different, use FIELD_INDEXES

:type => if there’s an extra column/index, use TYPE_EXTRA;

if there's a missing column/index, use TYPE_MISSING;
if there's a mismatched column/index, use TYPE_MISMATCH

For TYPE_EXTRA and TYPE_MISSING: :generator => the table generator that contains the extra/missing index/column :elem => the missing index/column, as a hash from the table generator

For TYPE_MISMATCH: :db_generator => the db table generator :exp_generator => the expected table generator :db_elem => the index/column in the db table generator as a hash :exp_elem => the index/column in the exp table generator as a hash



29
30
31
32
# File 'lib/model_schema/schema_error.rb', line 29

def initialize(table_name, schema_diffs)
  @table_name = table_name
  @schema_diffs = schema_diffs
end

Instance Attribute Details

#schema_diffsObject (readonly)

Returns the value of attribute schema_diffs.



8
9
10
# File 'lib/model_schema/schema_error.rb', line 8

def schema_diffs
  @schema_diffs
end

Instance Method Details

#diffs_by_field_type(field, type) ⇒ Object

Returns the diffs in schema_diffs that have the given field and type.



49
50
51
# File 'lib/model_schema/schema_error.rb', line 49

def diffs_by_field_type(field, type)
  @schema_diffs.select {|diff| diff[:field] == field && diff[:type] == type}
end

#dump_extra_diffs(field) ⇒ Object

Dumps all diffs that have the given field and are of TYPE_EXTRA.



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/model_schema/schema_error.rb', line 54

def dump_extra_diffs(field)
  extra_diffs = diffs_by_field_type(field, TYPE_EXTRA)

  if extra_diffs.length > 0
    header = "Table #{@table_name} has extra #{field}:\n"
    diff_str = extra_diffs.map do |diff|
      dump_single(field, diff[:generator], diff[:elem])
    end.join("\n\t")

    "#{header}\n\t#{diff_str}\n"
  end
end

#dump_mismatch_diffs(field) ⇒ Object

Dumps all diffs that have the given field and are of TYPE_MISMATCH.



82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/model_schema/schema_error.rb', line 82

def dump_mismatch_diffs(field)
  mismatch_diffs = diffs_by_field_type(field, TYPE_MISMATCH)

  if mismatch_diffs.length > 0
    header = "Table #{@table_name} has mismatched #{field}:\n"
    diff_str = mismatch_diffs.map do |diff|
      "actual:    #{dump_single(field, diff[:db_generator], diff[:db_elem])}\n\t" +
      "expected:  #{dump_single(field, diff[:exp_generator], diff[:exp_elem])}"
    end.join("\n\n\t")

    "#{header}\n\t#{diff_str}\n"
  end
end

#dump_missing_diffs(field) ⇒ Object

Dumps all diffs that have the given field and are of TYPE_MISSING.



68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/model_schema/schema_error.rb', line 68

def dump_missing_diffs(field)
  missing_diffs = diffs_by_field_type(field, TYPE_MISSING)

  if missing_diffs.length > 0
    header = "Table #{@table_name} is missing #{field}:\n"
    diff_str = missing_diffs.map do |diff|
      dump_single(field, diff[:generator], diff[:elem])
    end.join("\n\t")

    "#{header}\n\t#{diff_str}\n"
  end
end

#dump_single(field, generator, elem) ⇒ Object

Dumps a single column/index from the generator to its string representation.

field: FIELD_COLUMNS for a column or FIELD_INDEXES for an index generator: the table generator elem: the index/column in the generator as a hash



39
40
41
42
43
44
45
46
# File 'lib/model_schema/schema_error.rb', line 39

def dump_single(field, generator, elem)
  array = generator.send(field)
  index = array.find_index(elem)
  fail ArgumentError, "#{elem.inspect} not part of #{array.inspect}" if !index

  lines = generator.send(:"dump_#{field}").lines.map(&:strip)
  lines[index]
end

#to_sObject

Combines all dumps into one cohesive error message.



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/model_schema/schema_error.rb', line 97

def to_s
  parts = FIELDS.flat_map do |field|
    [dump_extra_diffs(field),
     dump_missing_diffs(field),
     dump_mismatch_diffs(field)]
  end

  [
    "Table #{@table_name} does not match the expected schema.\n\n",
    parts.compact.join("\n"),
    "\nYou may disable schema checks by passing :disable => true to model_",
    "schema or by setting the ENV variable #{DISABLE_MODEL_SCHEMA_KEY}=1.\n"
  ].join
end