Skip to content

Commit

Permalink
#67: Add json style field to content items
Browse files Browse the repository at this point in the history
This field is intended for storing item-specific content styling
attributes that do not need to be referenced in migrations or
database queries. Items should take responsibility for initialising
and upgrading their own attributes.
  • Loading branch information
sfnelson committed Aug 26, 2024
1 parent d6761a7 commit 1f80fef
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 1 deletion.
37 changes: 37 additions & 0 deletions app/models/concerns/katalyst/content/has_style.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

module Katalyst
module Content
module HasStyle
extend ActiveSupport::Concern

# Style attribute allows items to define their own attributes for use in
# content styles. These attribute will be automatically mapped to json
# data which is stored and deserialized without needing to add columns.
class_methods do
def style_attributes(&)
style_class = Class.new(Katalyst::Content::HasStyle::StyleBase, &)
const_set(:Style, style_class)
attribute(:style, Katalyst::Content::Types::StyleType.new(style_class), default: -> { style_class.new })

style_class.attribute_names.each do |name|
define_method(name) { style.public_send(name) }
define_method(:"#{name}=") { |value| style.public_send(:"#{name}=", value) }
end

validate do
style.validate(validation_context)
style.errors.each do |error|
errors.add(error.attribute, error.type)
end
end
end
end

class StyleBase
include ActiveModel::Model
include ActiveModel::Attributes
end
end
end
end
2 changes: 2 additions & 0 deletions app/models/katalyst/content/item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module Katalyst
module Content
# STI base class for content items
class Item < ApplicationRecord
include HasStyle

def self.config
Katalyst::Content.config
end
Expand Down
32 changes: 32 additions & 0 deletions app/models/katalyst/content/types/style_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module Katalyst
module Content
module Types
# Data serialization/deserialization for Katalyst::Content::Item style data
class StyleType < ActiveRecord::Type::Json
def initialize(type)
super()

@type = type
end

def serialize(value)
super(value.attributes)
end

def deserialize(value)
case value
when String
decoded = super
@type.new(**decoded) unless decoded.nil?
when Hash
@type.new(**value)
when HasStyle::StyleBase
value
end
end
end
end
end
end
7 changes: 7 additions & 0 deletions db/migrate/20240826042004_add_style_to_content_items.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddStyleToContentItems < ActiveRecord::Migration[7.1]
def change
add_column :katalyst_content_items, :style, :json, null: false, default: {}
end
end
3 changes: 2 additions & 1 deletion spec/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2023_05_15_151440) do
ActiveRecord::Schema[7.1].define(version: 2024_08_26_042004) do
create_table "action_text_rich_texts", force: :cascade do |t|
t.string "name", null: false
t.text "body"
Expand Down Expand Up @@ -60,6 +60,7 @@
t.datetime "updated_at", null: false
t.string "caption"
t.integer "heading_style", default: 0, null: false
t.json "style", default: {}, null: false
t.index ["container_type", "container_id"], name: "index_katalyst_content_items_on_container"
end

Expand Down

0 comments on commit 1f80fef

Please sign in to comment.