Module: ActiveAdmin::PrimaryKey

Defined in:
lib/active_admin/primary_key.rb

Class Method Summary collapse

Class Method Details

.columns(model) ⇒ Object



20
21
22
# File 'lib/active_admin/primary_key.rb', line 20

def columns(model)
  ordered_columns(model)
end

.composite?(model) ⇒ Boolean

Returns:

  • (Boolean)


11
12
13
14
# File 'lib/active_admin/primary_key.rb', line 11

def composite?(model)
  pk = model.primary_key
  pk.is_a?(Array) && pk.size > 1
end

.composite_attribute_hash(model, id_param) ⇒ Object



24
25
26
27
28
29
# File 'lib/active_admin/primary_key.rb', line 24

def composite_attribute_hash(model, id_param)
  cols = ordered_columns(model)
  hash = normalize_composite_input(cols, id_param)
  validate_composite_keys!(cols, hash)
  hash
end

.composite_field_hash(model, cols, id, kw) ⇒ Object

Raises:

  • (ArgumentError)


129
130
131
132
133
134
135
136
# File 'lib/active_admin/primary_key.rb', line 129

def composite_field_hash(model, cols, id, kw)
  return find_attributes(model, id).stringify_keys if id.present?

  out = cols.to_h { |c| [c, kw[c.to_sym] || kw[c]] }
  return out.transform_values(&:to_s) if cols.all? { |c| !out[c].nil? }

  raise ArgumentError, "composite id requires id (JSON) or all primary key fields as arguments"
end

.composite_member_param(model, blob, cols) ⇒ Object

Raises:

  • (ArgumentError)


107
108
109
110
111
112
# File 'lib/active_admin/primary_key.rb', line 107

def composite_member_param(model, blob, cols)
  return find_attributes(model, blob["id"]).stringify_keys if blob["id"].present?
  return cols.to_h { |c| [c, blob[c]] } if cols.all? { |c| blob.key?(c) && blob[c].present? }

  raise ArgumentError, "composite id requires id (JSON) or all primary key columns"
end

.dataloader_tuple(model, raw) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/active_admin/primary_key.rb', line 78

def dataloader_tuple(model, raw)
  cols = ordered_columns(model)
  return raw if cols.size == 1

  h = composite_attribute_hash(model, raw)
  cols.map { |c| h[c] }
end

.dataloader_tuple_from_record(record) ⇒ Object



86
87
88
# File 'lib/active_admin/primary_key.rb', line 86

def dataloader_tuple_from_record(record)
  ordered_columns(record.class).map { |c| record.read_attribute(c) }
end

.extract_composite_json(cols, payload) ⇒ Object

Raises:

  • (ArgumentError)


44
45
46
47
48
49
# File 'lib/active_admin/primary_key.rb', line 44

def extract_composite_json(cols, payload)
  parsed = JSON.parse(payload)
  raise ArgumentError, "composite id must be a JSON object" unless parsed.is_a?(Hash)

  parsed.stringify_keys.slice(*cols)
end

.field_kw_to_param_hash(model, id:, **kw) ⇒ Object



114
115
116
117
118
119
120
121
# File 'lib/active_admin/primary_key.rb', line 114

def field_kw_to_param_hash(model, id:, **kw)
  cols = ordered_columns(model)
  if cols.size == 1
    single_field_hash(id)
  else
    composite_field_hash(model, cols, id, kw)
  end
end

.find_attributes(model, id_param) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/active_admin/primary_key.rb', line 59

def find_attributes(model, id_param)
  cols = ordered_columns(model)
  if cols.size == 1
    {cols.first => id_param}
  else
    composite_attribute_hash(model, id_param)
  end
end

.graphql_id_value(record) ⇒ Object



68
69
70
71
72
73
74
75
76
# File 'lib/active_admin/primary_key.rb', line 68

def graphql_id_value(record)
  cols = ordered_columns(record.class)
  if cols.size == 1
    record.public_send(cols.first).to_s
  else
    payload = cols.each_with_object({}) { |c, m| m[c] = record.read_attribute(c) }
    JSON.generate(payload)
  end
end

.member_param_hash(model, blob) ⇒ Object



90
91
92
93
94
95
96
97
98
# File 'lib/active_admin/primary_key.rb', line 90

def member_param_hash(model, blob)
  blob = blob.stringify_keys
  cols = ordered_columns(model)
  if cols.size == 1
    single_member_param(blob)
  else
    composite_member_param(model, blob, cols)
  end
end

.normalize_composite_input(cols, id_param) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/active_admin/primary_key.rb', line 31

def normalize_composite_input(cols, id_param)
  case id_param
  when Hash
    id_param.stringify_keys.slice(*cols)
  when String
    extract_composite_json(cols, id_param)
  when Array
    cols.zip(id_param).to_h
  else
    raise ArgumentError, "unsupported composite id type"
  end
end

.ordered_columns(model) ⇒ Object



16
17
18
# File 'lib/active_admin/primary_key.rb', line 16

def ordered_columns(model)
  Array(model.primary_key).map(&:to_s)
end

.single_field_hash(id) ⇒ Object

Raises:

  • (ArgumentError)


123
124
125
126
127
# File 'lib/active_admin/primary_key.rb', line 123

def single_field_hash(id)
  raise ArgumentError, "id is required" if id.blank?

  {"id" => id.to_s}
end

.single_member_param(blob) ⇒ Object

Raises:

  • (ArgumentError)


100
101
102
103
104
105
# File 'lib/active_admin/primary_key.rb', line 100

def single_member_param(blob)
  id = blob["id"]
  raise ArgumentError, "id is required" if id.blank?

  {"id" => id.to_s}
end

.validate_composite_keys!(cols, hash) ⇒ Object

Raises:

  • (ArgumentError)


51
52
53
54
55
56
57
# File 'lib/active_admin/primary_key.rb', line 51

def validate_composite_keys!(cols, hash)
  missing = cols - hash.keys
  raise ArgumentError, "composite id missing keys: #{missing.join(", ")}" if missing.any?

  absent = cols.select { |c| hash[c].nil? }
  raise ArgumentError, "composite id missing values for: #{absent.join(", ")}" if absent.any?
end