Class: CrudComponents::Presenters::Cells

Inherits:
Object
  • Object
show all
Defined in:
lib/crud_components/presenters/cells.rb

Overview

Fast inline cell renderers — Ruby equivalents of the crud_components/fields/_*.html.erb partials, built with the tag/link helpers so a big table skips one partial render per cell (the dominant cost: a partial cell is ~200µs, this is ~10–20µs). Output matches the partials (same elements, classes, links, escaping).

Used only when the renderer is one of these built-ins AND the host hasn’t overridden its partial (Base#render_cell checks both). markdown/asciidoc and any custom ‘as:` renderer keep using their partials.

Constant Summary collapse

BUILTINS =
%i[string text number boolean date datetime enum
association association_list json attachment].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(view) ⇒ Cells

Returns a new instance of Cells.



18
19
20
# File 'lib/crud_components/presenters/cells.rb', line 18

def initialize(view)
  @v = view
end

Class Method Details

.handles?(renderer) ⇒ Boolean

Returns:

  • (Boolean)


16
# File 'lib/crud_components/presenters/cells.rb', line 16

def self.handles?(renderer) = BUILTINS.include?(renderer)

Instance Method Details

#association(value, record, field, _surface, _cc) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/crud_components/presenters/cells.rb', line 72

def association(value, record, field, _surface, _cc)
  return dash if value.nil?

  label = @v.crud_association_label(field, value)
  path = @v.crud_record_path(value, owner: record)
  path ? @v.link_to(label, path, data: { turbo_action: 'advance' }) : esc(label)
end

#association_list(value, record, field, surface, _cc) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/crud_components/presenters/cells.rb', line 80

def association_list(value, record, field, surface, _cc)
  items = value.to_a
  return dash if items.empty?

  shown = surface == :collection ? items.first(3) : items
  links = @v.safe_join(shown.map { |item| association_item(field, item, record) }, ', ')
  return links if items.size <= shown.size

  more = @v.t('crud_components.more', count: items.size - shown.size, default: '+%{count} more')
  index_path = @v.crud_association_index_path(record, field)
  more_html = index_path ? @v.link_to(more, index_path, class: css.muted, data: { turbo_action: 'advance' })
                         : @v.tag.span(more, class: css.muted)
  @v.safe_join([links, ' ', more_html])
end

#attachment(value, _record, field, surface, _cc) ⇒ Object



105
106
107
108
109
110
111
112
113
114
# File 'lib/crud_components/presenters/cells.rb', line 105

def attachment(value, _record, field, surface, _cc)
  return dash unless value.respond_to?(:attached?) && value.attached?

  if field.respond_to?(:many?) && field.many?
    thumbs = value.map { |a| attachment_thumb(a, surface) }
    @v.tag.span(@v.safe_join(thumbs), class: 'd-inline-flex flex-wrap gap-1')
  else
    attachment_thumb(value, surface)
  end
end

#boolean(value, _record, field, _surface, cc) ⇒ Object



48
49
50
51
52
53
# File 'lib/crud_components/presenters/cells.rb', line 48

def boolean(value, _record, field, _surface, cc)
  return dash if value.nil?

  icon = @v.tag.span(value ? '' : '', class: value ? css.boolean_true : css.boolean_false)
  filter_link(cc, field, value, icon) { icon }
end

#date(value, _record, _field, _surface, _cc) ⇒ Object



55
56
57
# File 'lib/crud_components/presenters/cells.rb', line 55

def date(value, _record, _field, _surface, _cc)
  value.nil? ? dash : esc(@v.l(value.to_date))
end

#datetime(value, _record, _field, _surface, _cc) ⇒ Object



59
60
61
# File 'lib/crud_components/presenters/cells.rb', line 59

def datetime(value, _record, _field, _surface, _cc)
  value.nil? ? dash : esc(@v.l(value, format: :short))
end

#enum(value, _record, field, _surface, cc) ⇒ Object



63
64
65
66
67
68
69
70
# File 'lib/crud_components/presenters/cells.rb', line 63

def enum(value, _record, field, _surface, cc)
  return dash if value.nil?

  label = field.respond_to?(:human_value) ? field.human_value(value) : value
  badge = @v.tag.span(label, class: css.badge)
  filter_link(cc, field, value, badge,
              title: @v.t('crud_components.filter_by', name: label, default: "Filter by #{label}")) { badge }
end

#json(value, _record, _field, surface, _cc) ⇒ Object



95
96
97
98
99
100
101
102
103
# File 'lib/crud_components/presenters/cells.rb', line 95

def json(value, _record, _field, surface, _cc)
  return dash if value.nil?

  pretty = value.is_a?(String) ? value : JSON.pretty_generate(value)
  pretty = @v.truncate(pretty, length: 120) if surface == :collection
  highlighted = CrudComponents::Markup.highlight_json(pretty)
  inner = highlighted ? @v.raw(highlighted) : pretty
  @v.tag.pre(@v.tag.code(inner), class: 'crud-json mb-0')
end

#number(value, _record, field, _surface, _cc) ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/crud_components/presenters/cells.rb', line 39

def number(value, _record, field, _surface, _cc)
  return dash if value.nil?

  o = field.renderer_options
  formatted = o[:digits] ? @v.number_with_precision(value, precision: o[:digits], delimiter: ',')
                         : @v.number_with_delimiter(value)
  o[:unit] ? @v.safe_join([formatted, " #{o[:unit]}"]) : @v.safe_join([formatted])
end

#render(renderer, value:, record:, field:, surface:, cell_context:) ⇒ Object



22
23
24
# File 'lib/crud_components/presenters/cells.rb', line 22

def render(renderer, value:, record:, field:, surface:, cell_context:)
  public_send(renderer, value, record, field, surface, cell_context)
end

#string(value, _record, _field, surface, _cc) ⇒ Object



26
27
28
29
30
# File 'lib/crud_components/presenters/cells.rb', line 26

def string(value, _record, _field, surface, _cc)
  return dash if blank?(value)

  surface == :collection ? @v.truncate(value.to_s, length: 120) : esc(value)
end

#text(value, _record, _field, surface, _cc) ⇒ Object



32
33
34
35
36
37
# File 'lib/crud_components/presenters/cells.rb', line 32

def text(value, _record, _field, surface, _cc)
  return dash if blank?(value)
  return @v.truncate(value.to_s, length: 120) if surface == :collection

  @v.tag.div(esc(value), class: 'crud-text', style: 'white-space: pre-line')
end