class ViewModel::DeserializationError::UniqueViolation

Constants

DETAIL_INFIX
DETAIL_PREFIX
DETAIL_SUFFIX
PG_ERROR_FIELD_CONSTRAINT_NAME
QUOTED_IDENTIFIER
UNQUOTED_IDENTIFIER

Attributes

columns[R]
constraint[R]
detail[R]
values[R]

Public Class Methods

from_postgres_error(err, nodes) click to toggle source
# File lib/view_model/deserialization_error.rb, line 363
def self.from_postgres_error(err, nodes)
  result         = err.result
  constraint     = result.error_field(PG_ERROR_FIELD_CONSTRAINT_NAME)
  message_detail = result.error_field(PG::Result::PG_DIAG_MESSAGE_DETAIL)

  columns, values = parse_message_detail(message_detail)

  unless columns
    # Couldn't parse the detail message, fall back on an unparsed error
    return DatabaseConstraint.new(err.message, nodes)
  end

  self.new(err.message, constraint, columns, values, nodes)
end
new(detail, constraint, columns, values, nodes = []) click to toggle source
Calls superclass method ViewModel::AbstractErrorWithBlame::new
# File lib/view_model/deserialization_error.rb, line 427
def initialize(detail, constraint, columns, values, nodes = [])
  @detail     = detail
  @constraint = constraint
  @columns    = columns
  @values     = values
  super(nodes)
end
parse_message_detail(detail) click to toggle source
# File lib/view_model/deserialization_error.rb, line 382
def parse_message_detail(detail)
  stream = detail.dup

  return nil unless stream.delete_prefix!(DETAIL_PREFIX)
  return nil unless stream.delete_suffix!(DETAIL_SUFFIX)

  # The message should start with an identifier list: pop off identifier
  # tokens while we can.
  identifiers = []

  identifier = parse_identifier(stream)
  return nil unless identifier

  identifiers << identifier

  while stream.delete_prefix!(', ')
    identifier = parse_identifier(stream)
    return nil unless identifier

    identifiers << identifier
  end

  # The message should now contain ")=(" followed by the (unparseable)
  # value list.
  return nil unless stream.delete_prefix!(DETAIL_INFIX)

  [identifiers, stream]
end

Private Class Methods

parse_identifier(stream) click to toggle source
# File lib/view_model/deserialization_error.rb, line 416
def parse_identifier(stream)
  if (identifier = stream.slice!(UNQUOTED_IDENTIFIER))
    identifier
  elsif (quoted_identifier = stream.slice!(QUOTED_IDENTIFIER))
    quoted_identifier[1..-2].gsub('""', '"')
  else
    nil
  end
end

Public Instance Methods

meta() click to toggle source
Calls superclass method ViewModel::AbstractErrorWithBlame#meta
# File lib/view_model/deserialization_error.rb, line 435
def meta
  super.merge(constraint: @constraint, columns: @columns, values: @values)
end