DEV: Refactor subclasses in `ThemeSettingsManager` to individual files (#25605)

Why this change?

One Ruby class per file improves readability
This commit is contained in:
Alan Guo Xiang Tan 2024-02-08 12:59:52 +08:00 committed by GitHub
parent 7ce76143ac
commit fb0e656cb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 197 additions and 185 deletions

View File

@ -112,155 +112,4 @@ class ThemeSettingsManager
max = @opts[:max]
(max.is_a?(::Integer) || max.is_a?(::Float)) && max != ::Float::INFINITY
end
class Objects < self
def value
has_record? ? db_record.json_value : default.map!(&:deep_stringify_keys)
end
def value=(objects)
# TODO: Validate the objects against the schema
record = has_record? ? db_record : create_record!
record.json_value = objects
record.save!
record.json_value
end
end
class List < self
def list_type
@opts[:list_type]
end
end
class String < self
def is_valid_value?(new_value)
(@opts[:min]..@opts[:max]).include? new_value.to_s.length
end
def textarea
@opts[:textarea]
end
def json_schema
begin
JSON.parse(@opts[:json_schema])
rescue StandardError
false
end
end
end
class Bool < self
def self.cast(value)
[true, "true"].include?(value)
end
def value
self.class.cast(super)
end
def value=(new_value)
new_value = (self.class.cast(new_value)).to_s
super(new_value)
end
end
class Integer < self
def self.cast(value)
value.to_i
end
def value
self.class.cast(super)
end
def value=(new_value)
super(self.class.cast(new_value))
end
def is_valid_value?(new_value)
(@opts[:min]..@opts[:max]).include? new_value.to_i
end
end
class Float < self
def self.cast(value)
value.to_f
end
def value
self.class.cast(super)
end
def value=(new_value)
super(self.class.cast(new_value))
end
def is_valid_value?(new_value)
(@opts[:min]..@opts[:max]).include? new_value.to_f
end
end
class Enum < self
def value
val = super
match = choices.find { |choice| choice == val || choice.to_s == val }
match || val
end
def is_valid_value?(new_value)
choices.include?(new_value) || choices.map(&:to_s).include?(new_value)
end
def choices
@opts[:choices]
end
end
class Upload < self
def value
has_record? ? cdn_url(db_record.value) : default
end
def default
upload_id = default_upload_id
return if upload_id.blank?
cdn_url(upload_id)
end
def value=(new_value)
if new_value.present?
if new_value == default
new_value = default_upload_id
else
upload = ::Upload.find_by(url: new_value)
new_value = upload.id if upload.present?
end
end
super(new_value)
end
private
def cdn_url(upload_id)
return if upload_id.blank?
upload = ::Upload.find_by_id(upload_id.to_i)
return if upload.blank?
Discourse.store.cdn_url(upload.url)
end
def default_upload_id
theme_field =
theme.theme_fields.find_by(name: @default, type_id: ThemeField.types[:theme_upload_var])
return if theme_field.blank?
theme_field.upload_id
end
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class ThemeSettingsManager::Bool < ThemeSettingsManager
def self.cast(value)
[true, "true"].include?(value)
end
def value
self.class.cast(super)
end
def value=(new_value)
new_value = (self.class.cast(new_value)).to_s
super(new_value)
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class ThemeSettingsManager::Enum < ThemeSettingsManager
def value
val = super
match = choices.find { |choice| choice == val || choice.to_s == val }
match || val
end
def is_valid_value?(new_value)
choices.include?(new_value) || choices.map(&:to_s).include?(new_value)
end
def choices
@opts[:choices]
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class ThemeSettingsManager::Float < ThemeSettingsManager
def self.cast(value)
value.to_f
end
def value
self.class.cast(super)
end
def value=(new_value)
super(self.class.cast(new_value))
end
def is_valid_value?(new_value)
(@opts[:min]..@opts[:max]).include? new_value.to_f
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class ThemeSettingsManager::Integer < ThemeSettingsManager
def self.cast(value)
value.to_i
end
def value
self.class.cast(super)
end
def value=(new_value)
super(self.class.cast(new_value))
end
def is_valid_value?(new_value)
(@opts[:min]..@opts[:max]).include? new_value.to_i
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class ThemeSettingsManager::List < ThemeSettingsManager
def list_type
@opts[:list_type]
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class ThemeSettingsManager::Objects < ThemeSettingsManager
def value
has_record? ? db_record.json_value : default.map!(&:deep_stringify_keys)
end
def value=(objects)
# TODO: Validate the objects against the schema
record = has_record? ? db_record : create_record!
record.json_value = objects
record.save!
theme.reload
record.json_value
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class ThemeSettingsManager::String < ThemeSettingsManager
def is_valid_value?(new_value)
(@opts[:min]..@opts[:max]).include? new_value.to_s.length
end
def textarea
@opts[:textarea]
end
def json_schema
begin
JSON.parse(@opts[:json_schema])
rescue StandardError
false
end
end
end

View File

@ -0,0 +1,46 @@
# frozen_string_literal: true
class ThemeSettingsManager::Upload < ThemeSettingsManager
def value
has_record? ? cdn_url(db_record.value) : default
end
def default
upload_id = default_upload_id
return if upload_id.blank?
cdn_url(upload_id)
end
def value=(new_value)
if new_value.present?
if new_value == default
new_value = default_upload_id
else
upload = ::Upload.find_by(url: new_value)
new_value = upload.id if upload.present?
end
end
super(new_value)
end
private
def cdn_url(upload_id)
return if upload_id.blank?
upload = ::Upload.find_by_id(upload_id.to_i)
return if upload.blank?
Discourse.store.cdn_url(upload.url)
end
def default_upload_id
theme_field =
theme.theme_fields.find_by(name: @default, type_id: ThemeField.types[:theme_upload_var])
return if theme_field.blank?
theme_field.upload_id
end
end

View File

@ -84,16 +84,3 @@ valid_json_schema_setting:
causes_refresh:
default: ""
refresh: true
valid_objects_setting:
type: objects
default:
- title: "Some title"
description: "Some description"
schema:
name: "Some Object"
fields:
title:
type: string
description:
type: string

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
RSpec.describe ThemeSettingsManager::Objects do
fab!(:theme)
before { SiteSetting.experimental_objects_type_for_theme_settings = true }
it "can store a list of objects" do
objects_setting =
described_class.new(
"some_objects_setting",
[{ "title" => "Some title", "description" => "Some description" }],
theme,
schema: {
name: "Some Object",
fields: {
title: {
type: "string",
},
description: {
type: "string",
},
},
},
)
expect(objects_setting.value).to eq(
[{ "title" => "Some title", "description" => "Some description" }],
)
objects_setting.value = [{ title: "title 1", description: "description 1" }]
expect(objects_setting.value).to eq(
[{ "title" => "title 1", "description" => "description 1" }],
)
end
end

View File

@ -1,7 +1,5 @@
# frozen_string_literal: true
require "theme_settings_manager"
RSpec.describe ThemeSettingsManager do
let!(:theme) { Fabricate(:theme) }
@ -12,8 +10,6 @@ RSpec.describe ThemeSettingsManager do
theme.settings
end
before { SiteSetting.experimental_objects_type_for_theme_settings = true }
describe "Enum" do
it "only accepts values from its choices" do
enum_setting = theme_settings[:enum_setting]
@ -186,21 +182,4 @@ RSpec.describe ThemeSettingsManager do
end
end
end
describe ThemeSettingsManager::Objects do
it "can store a list of objects" do
objects_setting = theme_settings[:valid_objects_setting]
expect(objects_setting.value).to eq(
[{ "title" => "Some title", "description" => "Some description" }],
)
objects_setting.value = [{ title: "title 1", description: "description 1" }]
objects_setting = theme.reload.settings[:valid_objects_setting]
expect(objects_setting.value).to eq(
[{ "title" => "title 1", "description" => "description 1" }],
)
end
end
end