Class: Iry::Constraint::Unique

Inherits:
Object
  • Object
show all
Defined in:
lib/iry/constraint/unique.rb

Constant Summary collapse

MAX_INFER_NAME_BYTE_SIZE =
62

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(keys, name:, error_key:, message: :taken) ⇒ Unique

Returns a new instance of Unique.

Parameters:

  • keys (<Symbol>)

    array of keys to track the uniqueness constraint of

  • message (Symbol, String) (defaults to: :taken)

    the validation error message

  • name (String)

    constraint name

  • error_key (Symbol)

    key to which the validation error will be applied to



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/iry/constraint/unique.rb', line 45

def initialize(
  keys,
  name:,
  error_key:,
  message: :taken
)
  @keys = keys
  @message = message
  @name = name
  @error_key = error_key
end

Instance Attribute Details

#error_keySymbol

Returns:

  • (Symbol)


39
40
41
# File 'lib/iry/constraint/unique.rb', line 39

def error_key
  @error_key
end

#keys<Symbol>

Returns:

  • (<Symbol>)


33
34
35
# File 'lib/iry/constraint/unique.rb', line 33

def keys
  @keys
end

#messageSymbol, String

Returns:

  • (Symbol, String)


35
36
37
# File 'lib/iry/constraint/unique.rb', line 35

def message
  @message
end

#nameString

Returns:

  • (String)


37
38
39
# File 'lib/iry/constraint/unique.rb', line 37

def name
  @name
end

Class Method Details

.infer_name(keys, table_name) ⇒ String

Infers the unique constraint name based on keys and table name

Parameters:

  • keys (<Symbol>)
  • table_name (String)

Returns:

  • (String)


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/iry/constraint/unique.rb', line 10

def self.infer_name(keys, table_name)
  # PostgreSQL convention:
  # "#{table_name}_#{keys.join("_")}_key"

  # Rails convention:
  # index_trip_hikers_on_trip_id_and_hiker_card_id
  # index_TABLENAME_on_COLUMN1_and_COLUMN2
  name = "index_#{table_name}_on_#{keys.join("_and_")}"
  if name.bytesize <= MAX_INFER_NAME_BYTE_SIZE
    return name
  end

  digest = OpenSSL::Digest::SHA256.hexdigest(name)[0..9]
  hashed_id = "_#{digest}"
  name = "idx_on_#{keys.join("_")}"

  short_limit = MAX_INFER_NAME_BYTE_SIZE - hashed_id.bytesize
  short_name = name.mb_chars.limit(short_limit).to_s

  "#{short_name}#{hashed_id}"
end

Instance Method Details

#apply(model) ⇒ ActiveModel::Error

Parameters:

Returns:

  • (ActiveModel::Error)


59
60
61
# File 'lib/iry/constraint/unique.rb', line 59

def apply(model)
  model.errors.add(error_key, message)
end