Class: LatoCms::PageField

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

Constant Summary collapse

ATTACHMENT_FIELD_TYPES =
%w[file image video gallery].freeze
TRANSLATABLE_FIELD_TYPES =

Field types that hold free-form text, used to decide what a "clone & translate" (see PagesController#clone_component_fields) sends to the LLM. Everything else (select/multiselect options, booleans, numbers, dates, colors, json, custom) is either a fixed choice or structured data that translation would corrupt.

%w[string textarea text].freeze
REPEATER_ORDER_FIELD_ID =
"__repeater_order".freeze

Instance Method Summary collapse

Instance Method Details

#as_json(_options = {}) ⇒ Object



107
108
109
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
# File 'app/models/lato_cms/page_field.rb', line 107

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] = media.map { |m| media_as_json(m) }
  when 'image'
    attached = media.first
    result[:attachments] = attached ? [media_as_json(attached, with_variants: true)] : []
  when 'video'
    attached = media.first
    result[:attachments] = attached ? [video_media_as_json(attached)] : []
  when 'gallery'
    result[:attachments] = media.map { |m| media_as_json(m, with_variants: true) }
  else
    result[:value] = parsed_value
  end

  result
end

#base_field_idObject



67
68
69
70
71
# File 'app/models/lato_cms/page_field.rb', line 67

def base_field_id
  return field_id unless repeater_item_id

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

#field_configObject



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

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



77
78
79
# File 'app/models/lato_cms/page_field.rb', line 77

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

#field_required?Boolean

Returns:

  • (Boolean)


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

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

#field_settingsObject



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

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

#field_typeObject



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

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

#parsed_valueObject



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'app/models/lato_cms/page_field.rb', line 28

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

#repeater_item_idObject



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

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)


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

def repeater_order?
  field_id == REPEATER_ORDER_FIELD_ID
end

#replace_media!(media_ids) ⇒ Object

Reconciles this field's media references to match the given ordered list of media ids: creates missing join rows, destroys removed ones, and updates position to match the given order. Callers must tenant-scope ids before calling this (see PagesController#assign_media_field).



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

def replace_media!(media_ids)
  ids = Array(media_ids).reject(&:blank?).map(&:to_s).uniq

  transaction do
    existing = page_field_media.index_by { |pfm| pfm.media_id.to_s }
    (existing.keys - ids).each { |stale_id| existing[stale_id].destroy }
    ids.each_with_index do |media_id, index|
      (existing[media_id] || page_field_media.build(media_id: media_id)).update!(position: index)
    end
  end

  page_field_media.reset
end