FIX: Pass values of objects typed settings to theme migrations (#26751)

This commit fixes a bug in theme settings migrations where values of `objects` typed theme settings aren't passed to migrations even when there are overriding values for those settings. What causes this bug is that, when creating the hash that contains all the overridden settings and will be passed to migrations, the values of `objects` typed settings are incorrectly retrieved from the `value` column (which is always nil for `objects` type) instead of `json_value`. `objects` settings are different from all other types in that they store their values in the `json_value` column and they need to be special-cased when retrieving their values.
This commit is contained in:
Osama Sayegh
2024-04-25 16:39:22 +03:00
committed by GitHub
parent 9d3ab91517
commit 2215fa0c8e
3 changed files with 63 additions and 1 deletions

View File

@@ -10,7 +10,7 @@ class ThemeSettingsManager
def self.cast_row_value(row) def self.cast_row_value(row)
type_name = self.types.invert[row.data_type].downcase.capitalize type_name = self.types.invert[row.data_type].downcase.capitalize
klass = "ThemeSettingsManager::#{type_name}".constantize klass = "ThemeSettingsManager::#{type_name}".constantize
klass.cast(row.value) klass.cast(klass.extract_value_from_row(row))
end end
def self.create(name, default, type, theme, opts = {}) def self.create(name, default, type, theme, opts = {})
@@ -23,6 +23,10 @@ class ThemeSettingsManager
value value
end end
def self.extract_value_from_row(row)
row.value
end
def initialize(name, default, theme, opts = {}) def initialize(name, default, theme, opts = {})
@name = name.to_sym @name = name.to_sym
@default = default @default = default

View File

@@ -1,6 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
class ThemeSettingsManager::Objects < ThemeSettingsManager class ThemeSettingsManager::Objects < ThemeSettingsManager
def self.extract_value_from_row(row)
row.json_value
end
def value def value
has_record? ? db_record.json_value : default.map!(&:deep_stringify_keys) has_record? ? db_record.json_value : default.map!(&:deep_stringify_keys)
end end

View File

@@ -36,6 +36,60 @@ describe ThemeSettingsMigrationsRunner do
) )
end end
it "passes values of `objects` typed settings to migrations and the values are parsed (not json string)" do
settings_field.update!(value: <<~YAML)
objects_setting:
type: objects
default:
- text: "hello, default link"
url: "https://google.com"
- text: "hi, another default link"
url: "https://discourse.org"
schema:
name: link
properties:
text:
type: string
url:
type: string
YAML
theme.update_setting(
:objects_setting,
[{ text: "custom link 1", url: "https://meta.discourse.org" }],
)
theme.save!
migration_field.update!(value: <<~JS)
export default function migrate(settings) {
settings.get("objects_setting").push(
{
text: "another custom link",
url: "https://try.discourse.org"
}
)
return settings;
}
JS
results = described_class.new(theme).run
expect(results.first[:settings_before]).to eq(
{
"objects_setting" => [
{ "url" => "https://meta.discourse.org", "text" => "custom link 1" },
],
},
)
expect(results.first[:settings_after]).to eq(
{
"objects_setting" => [
{ "url" => "https://meta.discourse.org", "text" => "custom link 1" },
{ "url" => "https://try.discourse.org", "text" => "another custom link" },
],
},
)
end
it "passes the output of the previous migration as input to the next one" do it "passes the output of the previous migration as input to the next one" do
theme.update_setting(:integer_setting, 1) theme.update_setting(:integer_setting, 1)