Module: LcpRuby::Presenter::LinkResolver

Defined in:
lib/lcp_ruby/presenter/link_resolver.rb

Overview

Pure service that resolves the link target for an enriched field/column entry. Walks link_chain on the record, guards nil / discarded / permission, and returns { target_record:, slug: } or nil when no link should be rendered.

Class Method Summary collapse

Class Method Details

.can_show?(target_model_name, current_user, evaluator_cache = nil) ⇒ Boolean

Returns true when the user may :show the target model. The check is model-level — depends only on current_user and target_model_name — so callers should pass a shared evaluator_cache to avoid per-row allocations.

Returns:

  • (Boolean)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/lcp_ruby/presenter/link_resolver.rb', line 41

def can_show?(target_model_name, current_user, evaluator_cache = nil)
  return true if target_model_name.blank?

  if evaluator_cache&.key?(target_model_name)
    evaluator = evaluator_cache[target_model_name]
    return true if evaluator.nil? # cached "no permission def" result

    return evaluator.can?(:show)
  end

  perm_def = LcpRuby.loader.permission_definitions[target_model_name]
  if perm_def.nil?
    evaluator_cache&.[]=(target_model_name, nil)
    return true
  end

  evaluator = Authorization::PermissionEvaluator.new(perm_def, current_user, target_model_name)
  evaluator_cache&.[]=(target_model_name, evaluator)
  evaluator.can?(:show)
rescue MetadataError
  true
end

.resolve(record:, entry:, current_user:, evaluator_cache: nil) ⇒ Hash{target_record:, slug:}

Returns or nil when no link should be rendered.

Parameters:

  • record (ActiveRecord::Base)

    the current row’s record

  • entry (Hash)

    enriched field/column hash (expects “link_chain”, “link_target_model” [String], “link_target_presenter_slug”)

  • current_user (Object, nil)
  • evaluator_cache (Hash, nil) (defaults to: nil)

    optional per-request cache keyed by target model name; avoids rebuilding PermissionEvaluator for every row

Returns:

  • (Hash{target_record:, slug:})

    or nil when no link should be rendered



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/lcp_ruby/presenter/link_resolver.rb', line 16

def resolve(record:, entry:, current_user:, evaluator_cache: nil)
  slug = entry["link_target_presenter_slug"]
  return nil unless slug

  chain = entry["link_chain"] || []
  target = walk_chain(record, chain)
  return nil if target.nil?
  return nil if target.respond_to?(:discarded?) && target.discarded?
  return nil unless can_show?(entry["link_target_model"], current_user, evaluator_cache)

  { target_record: target, slug: slug }
end

.walk_chain(record, chain) ⇒ Object



29
30
31
32
33
34
35
36
# File 'lib/lcp_ruby/presenter/link_resolver.rb', line 29

def walk_chain(record, chain)
  return record if chain.empty?

  chain.reduce(record) do |acc, seg|
    break nil if acc.nil?
    acc.respond_to?(seg) ? acc.public_send(seg) : nil
  end
end