Class: LeanCms::PageContent

Inherits:
ApplicationRecord
  • Object
show all
Defined in:
app/models/lean_cms/page_content.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.field_value(page, section, key, default: nil) ⇒ Object

Get a single field value



98
99
100
101
102
103
104
# File 'app/models/lean_cms/page_content.rb', line 98

def field_value(page, section, key, default: nil)
  if page.is_a?(LeanCms::Page)
    find_by(page_id: page.id, section: section, key: key)&.display_value || default
  else
    find_by("page = ? AND section = ? AND key = ?", page.to_s, section.to_s, key.to_s)&.display_value || default
  end
end

.find_or_initialize_content(page:, section:, key:) ⇒ Object

Look up a content record by its (page-slug, section, key) triple, or build a new one — bypassing the :page association setter so the string ‘page` column gets the slug instead of an AssociationTypeMismatch. `belongs_to :page` shadows the `page` varchar column for mass-assignment; this helper is the seam every internal write goes through during the in-progress migration to the normalized LeanCms::Page model.



16
17
18
19
20
21
22
23
# File 'app/models/lean_cms/page_content.rb', line 16

def self.find_or_initialize_content(page:, section:, key:)
  # Look up against the `page` varchar column explicitly. `where(page: ...)`
  # would resolve `:page` to the `belongs_to :page` association and emit
  # `WHERE page_id = NULL`, missing every existing record — which made
  # re-running load_structure crash on the SQLite unique index.
  where("page = ? AND section = ? AND key = ?", page.to_s, section.to_s, key.to_s).first ||
    new(section: section, key: key).tap { |record| record[:page] = page }
end

.page_structure(page) ⇒ Object

Get all content for a page grouped by section



86
87
88
89
90
# File 'app/models/lean_cms/page_content.rb', line 86

def page_structure(page)
  for_page(page).ordered.group_by(&:section).transform_values do |contents|
    contents.index_by(&:key).transform_values(&:display_value)
  end
end

.section_content(page, section) ⇒ Object

Get all content for a specific section as a hash



93
94
95
# File 'app/models/lean_cms/page_content.rb', line 93

def section_content(page, section)
  for_section(page, section).ordered.index_by(&:key).transform_values(&:display_value)
end

Instance Method Details

#card_image(image_id) ⇒ Object

Get image attachment for a specific card by image_id



153
154
155
156
# File 'app/models/lean_cms/page_content.rb', line 153

def card_image(image_id)
  return nil unless image_id.present? && card_images.attached?
  card_images.find { |img| img.blob.id.to_s == image_id.to_s }
end

#display_valueObject

Get the display value based on content type



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
# File 'app/models/lean_cms/page_content.rb', line 108

def display_value
  case content_type.to_sym
  when :text
    value.presence || content
  when :rich_text
    rich_content.present? ? rich_content.to_s : value.presence || content
  when :image
    image_file.attached? ? image_file : (value.presence || content)
  when :boolean
    # Store as string "true"/"false", return as boolean
    value == "true" || value == true || value == "1"
  when :url
    value.presence || content
  when :color
    value.presence || content
  when :dropdown
    value.presence || content
  when :cards
    # Cards are stored as JSON in the value field
    parse_cards_json
  when :bullets
    # Bullets are stored as JSON array
    parse_bullets_json
  else
    value.presence || content
  end
end

#max_lengthObject

Get max_length from options (for text fields)



201
202
203
204
# File 'app/models/lean_cms/page_content.rb', line 201

def max_length
  return nil unless options.is_a?(Hash)
  options['max_length']&.to_i
end

#page_slugObject



40
41
42
# File 'app/models/lean_cms/page_content.rb', line 40

def page_slug
  read_attribute(:page)
end

#parse_bullets_jsonObject

Parse bullets JSON data (similar to cards)



159
160
161
162
163
164
165
166
167
168
169
# File 'app/models/lean_cms/page_content.rb', line 159

def parse_bullets_json
  return [] unless bullets?

  if value.present?
    JSON.parse(value) rescue []
  elsif content.present?
    JSON.parse(content) rescue []
  else
    []
  end
end

#parse_cards_jsonObject

Parse cards JSON data



137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'app/models/lean_cms/page_content.rb', line 137

def parse_cards_json
  return [] unless cards?

  cards_data = if value.present?
    JSON.parse(value) rescue []
  elsif content.present?
    JSON.parse(content) rescue []
  else
    []
  end

  # Return cards data as-is, image attachments will be looked up separately when needed
  cards_data.map { |card| card.with_indifferent_access }
end

#parsed_optionsObject

Get parsed options for dropdown fields



188
189
190
191
192
193
194
195
196
197
198
# File 'app/models/lean_cms/page_content.rb', line 188

def parsed_options
  return [] unless dropdown?

  if options.is_a?(Array)
    options
  elsif options.is_a?(Hash)
    options['options'] || []
  else
    []
  end
end

#set_value(new_value) ⇒ Object

Set the value based on content type



172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'app/models/lean_cms/page_content.rb', line 172

def set_value(new_value)
  case content_type.to_sym
  when :boolean
    self.value = new_value.to_s
  when :rich_text
    self.rich_content = new_value
    self.value = new_value.to_s if new_value.present?
  when :cards
    # Store cards as JSON
    self.value = new_value.is_a?(String) ? new_value : new_value.to_json
  else
    self.value = new_value.to_s
  end
end