mirror of
https://github.com/discourse/discourse.git
synced 2024-12-03 16:26:28 +08:00
b1495884eb
Why this change? When creating a new theme setting that does not have a corresponding row in the `theme_settings` table, we end up writing to the database twice because `ActiveRecord::Base#save!` is called once before the `value` or `json_value` column is updated again with another database query with another call to `ActiveRecord::Base#save!`. What does this change do? Adds the column to be updated to argument for the `ActiveRecord::Base#create!` method call so that we only have one write query to the database.
102 lines
2.3 KiB
Ruby
102 lines
2.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class ThemeSettingsManager
|
|
attr_reader :name, :theme, :default
|
|
|
|
def self.types
|
|
ThemeSetting.types
|
|
end
|
|
|
|
def self.cast_row_value(row)
|
|
type_name = self.types.invert[row.data_type].downcase.capitalize
|
|
klass = "ThemeSettingsManager::#{type_name}".constantize
|
|
klass.cast(row.value)
|
|
end
|
|
|
|
def self.create(name, default, type, theme, opts = {})
|
|
type_name = self.types.invert[type].downcase.capitalize
|
|
klass = "ThemeSettingsManager::#{type_name}".constantize
|
|
klass.new(name, default, theme, opts)
|
|
end
|
|
|
|
def self.cast(value)
|
|
value
|
|
end
|
|
|
|
def initialize(name, default, theme, opts = {})
|
|
@name = name.to_sym
|
|
@default = default
|
|
@theme = theme
|
|
@opts = opts
|
|
@types = self.class.types
|
|
end
|
|
|
|
def value
|
|
has_record? ? db_record.value : default
|
|
end
|
|
|
|
def type_name
|
|
self.class.name.demodulize.downcase.to_sym
|
|
end
|
|
|
|
def type
|
|
@types[type_name]
|
|
end
|
|
|
|
def description
|
|
@opts[:description] # Old method of specifying description. Is now overridden by locale file
|
|
end
|
|
|
|
def requests_refresh?
|
|
@opts[:refresh]
|
|
end
|
|
|
|
def value=(new_value)
|
|
ensure_is_valid_value!(new_value)
|
|
value = new_value.to_s
|
|
|
|
record = has_record? ? update_record!(value:) : create_record!(value:)
|
|
|
|
record.value
|
|
end
|
|
|
|
def db_record
|
|
# theme.theme_settings will already be preloaded, so it is better to use
|
|
# `find` on an array, rather than make a round trip to the database
|
|
theme.theme_settings.to_a.find do |i|
|
|
i.name.to_s == @name.to_s && i.data_type.to_s == type.to_s
|
|
end
|
|
end
|
|
|
|
def update_record!(args)
|
|
db_record.tap { |instance| instance.update!(args) }
|
|
end
|
|
|
|
def create_record!(args)
|
|
record = ThemeSetting.new(name: @name, data_type: type, theme: @theme, **args)
|
|
record.save!
|
|
record
|
|
end
|
|
|
|
def has_record?
|
|
db_record.present?
|
|
end
|
|
|
|
def ensure_is_valid_value!(new_value)
|
|
return if new_value.nil?
|
|
|
|
error_messages = ThemeSettingsValidator.validate_value(new_value, type, @opts)
|
|
raise Discourse::InvalidParameters.new error_messages.join(" ") if error_messages.present?
|
|
end
|
|
|
|
def has_min?
|
|
min = @opts[:min]
|
|
(min.is_a?(::Integer) || min.is_a?(::Float)) && min != -::Float::INFINITY
|
|
end
|
|
|
|
def has_max?
|
|
max = @opts[:max]
|
|
(max.is_a?(::Integer) || max.is_a?(::Float)) && max != ::Float::INFINITY
|
|
end
|
|
end
|