class ModelSchema::SchemaError

Tracks differences between the expected schema and database table schema.

Constants

TYPE_EXTRA
TYPE_MISMATCH
TYPE_MISSING

Attributes

schema_diffs[R]

Public Class Methods

new(table_name, schema_diffs) click to toggle source

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

# File lib/model_schema/schema_error.rb, line 29
def initialize(table_name, schema_diffs)
  @table_name = table_name
  @schema_diffs = schema_diffs
end

Public Instance Methods

diffs_by_field_type(field, type) click to toggle source

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

# 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) click to toggle source

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

# 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) click to toggle source

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

# 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) click to toggle source

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

# 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) click to toggle source

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

# 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_s() click to toggle source

Combines all dumps into one cohesive error message.

# 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