Class: LatoCms::PageField

Inherits:
ApplicationRecord
  • Object
show all
Defined in:
app/models/lato_cms/page_field.rb

Constant Summary collapse

REPEATER_ORDER_FIELD_ID =
"__repeater_order".freeze

Instance Method Summary collapse

Instance Method Details

#as_json(_options = {}) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'app/models/lato_cms/page_field.rb', line 110

def as_json(_options = {})
  result = {
    id: id,
    persisted_field_id: field_id,
    field_id: base_field_id,
    field_type: field_type,
    field_name: field_name,
    required: field_required?,
    value: nil,
    attachments: []
  }

  case field_type
  when 'file'
    result[:attachments] = files.map { |f| attachment_as_json(f) }
  when 'image'
    attached = files.first
    result[:attachments] = attached ? [attachment_as_json(attached, with_variants: true)] : []
  when 'video'
    attached = video_attachment
    result[:attachments] = attached ? [video_attachment_as_json(attached)] : []
  when 'gallery'
    order = value ? (JSON.parse(value) rescue []) : []
    all_files = files.to_a
    ordered = order.any? ? all_files.sort_by { |f| order.index(f.id.to_s) || Float::INFINITY } : all_files
    result[:attachments] = ordered.map { |f| attachment_as_json(f, with_variants: true) }
  else
    result[:value] = parsed_value
  end

  result
end

#base_field_idObject



56
57
58
59
60
# File 'app/models/lato_cms/page_field.rb', line 56

def base_field_id
  return field_id unless repeater_item_id

  field_id.to_s.split('.', 2).last
end

#field_configObject



38
39
40
41
42
43
44
# File 'app/models/lato_cms/page_field.rb', line 38

def field_config
  return nil if repeater_order?

  component = LatoCms::TemplateManager.find_component(component_id)
  return nil unless component
  component.dig('fields', base_field_id)
end

#field_nameObject



66
67
68
# File 'app/models/lato_cms/page_field.rb', line 66

def field_name
  field_config&.dig('name') || field_id.to_s.humanize
end

#field_required?Boolean

Returns:

  • (Boolean)


70
71
72
# File 'app/models/lato_cms/page_field.rb', line 70

def field_required?
  field_config&.dig('required') == true
end

#field_settingsObject



74
75
76
# File 'app/models/lato_cms/page_field.rb', line 74

def field_settings
  field_config&.dig('settings') || {}
end

#field_typeObject



62
63
64
# File 'app/models/lato_cms/page_field.rb', line 62

def field_type
  field_config&.dig('type') || 'string'
end

#generate_video_poster!Object

Generates a poster image from the video via Active Storage previews (ffmpeg) and attaches it alongside the video. Best effort: any failure is logged and the video keeps working without a poster.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'app/models/lato_cms/page_field.rb', line 92

def generate_video_poster!
  video = video_attachment
  return unless video
  return if poster_attachment

  unless video.previewable?
    Rails.logger.warn("LatoCms: video preview unavailable (ffmpeg missing?) for attachment #{video.id}, skipping poster generation")
    return
  end

  preview = video.preview(resize_to_limit: [1280, 720]).processed
  preview.image.blob.open do |file|
    files.attach(io: file, filename: "#{video.filename.base}_poster.jpg", content_type: preview.image.blob.content_type)
  end
rescue StandardError => e
  Rails.logger.warn("LatoCms: failed to generate video poster for field #{id}: #{e.message}")
end

#parsed_valueObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'app/models/lato_cms/page_field.rb', line 17

def parsed_value
  return nil if value.blank?

  case field_type
  when 'number'
    value.include?('.') ? value.to_f : value.to_i
  when 'boolean'
    value == 'true'
  when 'json'
    JSON.parse(value) rescue value
  when 'date'
    Date.parse(value) rescue value
  when 'datetime'
    DateTime.parse(value) rescue value
  when 'multiselect'
    JSON.parse(value) rescue [value]
  else
    value
  end
end

#poster_attachmentObject



85
86
87
# File 'app/models/lato_cms/page_field.rb', line 85

def poster_attachment
  files.find { |file| file.content_type.to_s.start_with?("image/") }
end

#repeater_item_idObject



50
51
52
53
54
# File 'app/models/lato_cms/page_field.rb', line 50

def repeater_item_id
  return nil unless field_id.to_s.include?('.')

  field_id.to_s.split('.', 2).first
end

#repeater_order?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'app/models/lato_cms/page_field.rb', line 46

def repeater_order?
  field_id == REPEATER_ORDER_FIELD_ID
end

#video_attachmentObject

A video field stores two attachments in files: the video itself and an optional auto-generated poster image. Content type is the discriminator, so no extra column or naming convention is needed.



81
82
83
# File 'app/models/lato_cms/page_field.rb', line 81

def video_attachment
  files.find { |file| file.content_type.to_s.start_with?("video/") }
end