Merge commit '9a73a7dcaf2e383b2ec105d71bfcea2c48cbea10' into glitch-soc/merge-upstream

Conflicts:
- `app/lib/settings/scoped_settings.rb`:
  Removed upstream, while glitch-soc had a change related to its theming system.
  Removed as well, as it's unused.
pull/2562/head
Claire 2024-01-11 12:59:27 +01:00
commit 630b245bb4
17 changed files with 207 additions and 326 deletions

View File

@ -75,7 +75,6 @@ gem 'premailer-rails'
gem 'rack-attack', '~> 6.6' gem 'rack-attack', '~> 6.6'
gem 'rack-cors', '~> 2.0', require: 'rack/cors' gem 'rack-cors', '~> 2.0', require: 'rack/cors'
gem 'rails-i18n', '~> 7.0' gem 'rails-i18n', '~> 7.0'
gem 'rails-settings-cached', '~> 0.6', git: 'https://github.com/mastodon/rails-settings-cached.git', branch: 'v0.6.6-aliases-true'
gem 'redcarpet', '~> 3.6' gem 'redcarpet', '~> 3.6'
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis'] gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'

View File

@ -18,14 +18,6 @@ GIT
sidekiq (>= 3.5) sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0) statsd-ruby (~> 1.4, >= 1.4.0)
GIT
remote: https://github.com/mastodon/rails-settings-cached.git
revision: 86328ef0bd04ce21cc0504ff5e334591e8c2ccab
branch: v0.6.6-aliases-true
specs:
rails-settings-cached (0.6.6)
rails (>= 4.2.0)
GIT GIT
remote: https://github.com/stanhu/omniauth-cas.git remote: https://github.com/stanhu/omniauth-cas.git
revision: 4211e6d05941b4a981f9a36b49ec166cecd0e271 revision: 4211e6d05941b4a981f9a36b49ec166cecd0e271
@ -272,7 +264,7 @@ GEM
erubi (1.12.0) erubi (1.12.0)
et-orbi (1.2.7) et-orbi (1.2.7)
tzinfo tzinfo
excon (0.104.0) excon (0.109.0)
fabrication (2.31.0) fabrication (2.31.0)
faker (3.2.2) faker (3.2.2)
i18n (>= 1.8.11, < 2) i18n (>= 1.8.11, < 2)
@ -307,7 +299,7 @@ GEM
ffi-compiler (1.0.1) ffi-compiler (1.0.1)
ffi (>= 1.0.0) ffi (>= 1.0.0)
rake rake
fog-core (2.3.0) fog-core (2.4.0)
builder builder
excon (~> 0.71) excon (~> 0.71)
formatador (>= 0.2, < 2.0) formatador (>= 0.2, < 2.0)
@ -378,9 +370,9 @@ GEM
terminal-table (>= 1.5.1) terminal-table (>= 1.5.1)
idn-ruby (0.1.5) idn-ruby (0.1.5)
io-console (0.7.1) io-console (0.7.1)
irb (1.11.0) irb (1.11.1)
rdoc rdoc
reline (>= 0.3.8) reline (>= 0.4.2)
jmespath (1.6.2) jmespath (1.6.2)
json (2.7.1) json (2.7.1)
json-canonicalization (1.0.0) json-canonicalization (1.0.0)
@ -624,7 +616,7 @@ GEM
redlock (1.3.2) redlock (1.3.2)
redis (>= 3.0.0, < 6.0) redis (>= 3.0.0, < 6.0)
regexp_parser (2.8.3) regexp_parser (2.8.3)
reline (0.4.1) reline (0.4.2)
io-console (~> 0.5) io-console (~> 0.5)
request_store (1.5.1) request_store (1.5.1)
rack (>= 1.4) rack (>= 1.4)
@ -692,7 +684,7 @@ GEM
rubocop (~> 1.40) rubocop (~> 1.40)
rubocop-capybara (~> 2.17) rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22) rubocop-factory_bot (~> 2.22)
ruby-prof (1.6.3) ruby-prof (1.7.0)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby-saml (1.15.0) ruby-saml (1.15.0)
nokogiri (>= 1.13.10) nokogiri (>= 1.13.10)
@ -922,7 +914,6 @@ DEPENDENCIES
rails (~> 7.1.1) rails (~> 7.1.1)
rails-controller-testing (~> 1.0) rails-controller-testing (~> 1.0)
rails-i18n (~> 7.0) rails-i18n (~> 7.0)
rails-settings-cached (~> 0.6)!
rdf-normalize (~> 0.5) rdf-normalize (~> 0.5)
redcarpet (~> 3.6) redcarpet (~> 3.6)
redis (~> 4.5) redis (~> 4.5)

View File

@ -224,7 +224,7 @@ module LanguagesHelper
'en-GB': 'English (British)', 'en-GB': 'English (British)',
'es-AR': 'Español (Argentina)', 'es-AR': 'Español (Argentina)',
'es-MX': 'Español (México)', 'es-MX': 'Español (México)',
'fr-QC': 'Français (Canadien)', 'fr-CA': 'Français (Canadien)',
'pt-BR': 'Português (Brasil)', 'pt-BR': 'Português (Brasil)',
'pt-PT': 'Português (Portugal)', 'pt-PT': 'Português (Portugal)',
'sr-Latn': 'Srpski (latinica)', 'sr-Latn': 'Srpski (latinica)',

View File

@ -1,80 +0,0 @@
# frozen_string_literal: true
module Settings
class ScopedSettings
DEFAULTING_TO_UNSCOPED = %w(
flavour
skin
noindex
).freeze
def initialize(object)
@object = object
end
def method_missing(method, *args)
method_name = method.to_s
# set a value for a variable
if method_name[-1] == '='
var_name = method_name.sub('=', '')
value = args.first
self[var_name] = value
else
# retrieve a value
self[method_name]
end
end
def respond_to_missing?(*)
true
end
def all_as_records
vars = thing_scoped
records = vars.index_by(&:var)
Setting.default_settings.each do |key, default_value|
next if records.key?(key) || default_value.is_a?(Hash)
records[key] = Setting.new(var: key, value: default_value)
end
records
end
def []=(key, value)
key = key.to_s
record = thing_scoped.find_or_initialize_by(var: key)
record.update!(value: value)
Rails.cache.write(Setting.cache_key(key, @object), value)
end
def [](key)
Rails.cache.fetch(Setting.cache_key(key, @object)) do
db_val = thing_scoped.find_by(var: key.to_s)
if db_val
default_value = ScopedSettings.default_settings[key]
return default_value.with_indifferent_access.merge!(db_val.value) if default_value.is_a?(Hash)
db_val.value
else
ScopedSettings.default_settings[key]
end
end
end
class << self
def default_settings
defaulting = DEFAULTING_TO_UNSCOPED.index_with { |k| Setting[k] }
Setting.default_settings.merge!(defaulting)
end
end
protected
def thing_scoped
Setting.unscoped.where(thing_type: @object.class.base_class.to_s, thing_id: @object.id)
end
end
end

View File

@ -13,49 +13,114 @@
# thing_id :bigint(8) # thing_id :bigint(8)
# #
class Setting < RailsSettings::Base # This file is derived from a fork of the `rails-settings-cached` gem available at
source Rails.root.join('config', 'settings.yml') # https://github.com/mastodon/rails-settings-cached/tree/v0.6.6-aliases-true, with
# the original available at:
# https://github.com/huacnlee/rails-settings-cached/tree/0.x
# It is licensed as follows:
# Copyright (c) 2006 Alex Wayne
# Some additional features added 2009 by Georg Ledermann
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND
# NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class Setting < ApplicationRecord
after_commit :rewrite_cache, on: %i(create update)
after_commit :expire_cache, on: %i(destroy)
# Settings are server-wide settings only, but they were previously
# used for users too. This can be dropped later with a database
# migration dropping any scoped setting.
default_scope { where(thing_type: nil, thing_id: nil) }
class << self
# get or set a variable with the variable as the called method
# rubocop:disable Style/MissingRespondToMissing
def method_missing(method, *args)
# set a value for a variable
if method.end_with?('=')
var_name = method.to_s.chomp('=')
value = args.first
self[var_name] = value
else
# retrieve a value
self[method.to_s]
end
end
# rubocop:enable Style/MissingRespondToMissing
def cache_prefix_by_startup
@cache_prefix_by_startup ||= Digest::MD5.hexdigest(default_settings.to_s)
end
def cache_key(var_name)
"rails_settings_cached/#{cache_prefix_by_startup}/#{var_name}"
end
def [](key)
Rails.cache.fetch(cache_key(key)) do
db_val = find_by(var: key)
db_val ? db_val.value : default_settings[key]
end
end
# set a setting value by [] notation
def []=(var_name, value)
record = find_or_initialize_by(var: var_name.to_s)
record.value = value
record.save!
end
def default_settings
return @default_settings if defined?(@default_settings)
content = Rails.root.join('config', 'settings.yml').read
hash = content.empty? ? {} : YAML.safe_load(ERB.new(content).result, aliases: true).to_hash
@default_settings = (hash[Rails.env] || {}).freeze
end
end
# get the value field, YAML decoded
def value
YAML.safe_load(self[:value], permitted_classes: [ActiveSupport::HashWithIndifferentAccess, Symbol]) if self[:value].present?
end
# set the value field, YAML encoded
def value=(new_value)
self[:value] = new_value.to_yaml
end
def rewrite_cache
Rails.cache.write(cache_key, value)
end
def expire_cache
Rails.cache.delete(cache_key)
end
def cache_key
self.class.cache_key(var)
end
def to_param def to_param
var var
end end
class << self
def [](key)
return super(key) unless rails_initialized?
Rails.cache.fetch(cache_key(key, nil)) do
db_val = object(key)
if db_val
default_value = default_settings[key]
return default_value.with_indifferent_access.merge!(db_val.value) if default_value.is_a?(Hash)
db_val.value
else
default_settings[key]
end
end
end
def all_as_records
vars = thing_scoped
records = vars.index_by(&:var)
default_settings.each do |key, default_value|
next if records.key?(key) || default_value.is_a?(Hash)
records[key] = Setting.new(var: key, value: default_value)
end
records
end
def default_settings
return {} unless RailsSettings::Default.enabled?
RailsSettings::Default.instance
end
end
end end

View File

@ -31,7 +31,7 @@ Rails.application.configure do
:fi, :fi,
:fo, :fo,
:fr, :fr,
:'fr-QC', :'fr-CA',
:fy, :fy,
:ga, :ga,
:gd, :gd,

View File

@ -29,7 +29,7 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# Do not treat an `ActionController::Parameters` instance # Do not treat an `ActionController::Parameters` instance
# as equal to an equivalent `Hash` by default. # as equal to an equivalent `Hash` by default.
# Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality = false Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality = false
# Active Record Encryption now uses SHA-256 as its hash digest algorithm. Important: If you have # Active Record Encryption now uses SHA-256 as its hash digest algorithm. Important: If you have
# data encrypted with previous Rails versions, there are two scenarios to consider: # data encrypted with previous Rails versions, there are two scenarios to consider:
@ -50,7 +50,7 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# Instead, run these callbacks on the instance most likely to have internal # Instead, run these callbacks on the instance most likely to have internal
# state which matches what was committed to the database, typically the last # state which matches what was committed to the database, typically the last
# instance to save. # instance to save.
# Rails.application.config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction = false Rails.application.config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction = false
# Configures SQLite with a strict strings mode, which disables double-quoted string literals. # Configures SQLite with a strict strings mode, which disables double-quoted string literals.
# #
@ -59,10 +59,10 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# it then considers them as string literals. Because of this, typos can silently go unnoticed. # it then considers them as string literals. Because of this, typos can silently go unnoticed.
# For example, it is possible to create an index for a non existing column. # For example, it is possible to create an index for a non existing column.
# See https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted for more details. # See https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted for more details.
# Rails.application.config.active_record.sqlite3_adapter_strict_strings_by_default = true Rails.application.config.active_record.sqlite3_adapter_strict_strings_by_default = true
# Disable deprecated singular associations names # Disable deprecated singular associations names
# Rails.application.config.active_record.allow_deprecated_singular_associations_name = false Rails.application.config.active_record.allow_deprecated_singular_associations_name = false
# Enable the Active Job `BigDecimal` argument serializer, which guarantees # Enable the Active Job `BigDecimal` argument serializer, which guarantees
# roundtripping. Without this serializer, some queue adapters may serialize # roundtripping. Without this serializer, some queue adapters may serialize
@ -78,12 +78,12 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# `write` are given an invalid `expires_at` or `expires_in` time. # `write` are given an invalid `expires_at` or `expires_in` time.
# Options are `true`, and `false`. If `false`, the exception will be reported # Options are `true`, and `false`. If `false`, the exception will be reported
# as `handled` and logged instead. # as `handled` and logged instead.
# Rails.application.config.active_support.raise_on_invalid_cache_expiration_time = true Rails.application.config.active_support.raise_on_invalid_cache_expiration_time = true
# Specify whether Query Logs will format tags using the SQLCommenter format # Specify whether Query Logs will format tags using the SQLCommenter format
# (https://open-telemetry.github.io/opentelemetry-sqlcommenter/), or using the legacy format. # (https://open-telemetry.github.io/opentelemetry-sqlcommenter/), or using the legacy format.
# Options are `:legacy` and `:sqlcommenter`. # Options are `:legacy` and `:sqlcommenter`.
# Rails.application.config.active_record.query_log_tags_format = :sqlcommenter Rails.application.config.active_record.query_log_tags_format = :sqlcommenter
# Specify the default serializer used by `MessageEncryptor` and `MessageVerifier` # Specify the default serializer used by `MessageEncryptor` and `MessageVerifier`
# instances. # instances.
@ -129,39 +129,37 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# `config.load_defaults 7.1` does not set this value for environments other than # `config.load_defaults 7.1` does not set this value for environments other than
# development and test. # development and test.
# #
# if Rails.env.local? Rails.application.config.log_file_size = 100 * 1024 * 1024 if Rails.env.local?
# Rails.application.config.log_file_size = 100 * 1024 * 1024
# end
# Enable raising on assignment to attr_readonly attributes. The previous # Enable raising on assignment to attr_readonly attributes. The previous
# behavior would allow assignment but silently not persist changes to the # behavior would allow assignment but silently not persist changes to the
# database. # database.
# Rails.application.config.active_record.raise_on_assign_to_attr_readonly = true Rails.application.config.active_record.raise_on_assign_to_attr_readonly = true
# Enable validating only parent-related columns for presence when the parent is mandatory. # Enable validating only parent-related columns for presence when the parent is mandatory.
# The previous behavior was to validate the presence of the parent record, which performed an extra query # The previous behavior was to validate the presence of the parent record, which performed an extra query
# to get the parent every time the child record was updated, even when parent has not changed. # to get the parent every time the child record was updated, even when parent has not changed.
# Rails.application.config.active_record.belongs_to_required_validates_foreign_key = false Rails.application.config.active_record.belongs_to_required_validates_foreign_key = false
# Enable precompilation of `config.filter_parameters`. Precompilation can # Enable precompilation of `config.filter_parameters`. Precompilation can
# improve filtering performance, depending on the quantity and types of filters. # improve filtering performance, depending on the quantity and types of filters.
# Rails.application.config.precompile_filter_parameters = true Rails.application.config.precompile_filter_parameters = true
# Enable before_committed! callbacks on all enrolled records in a transaction. # Enable before_committed! callbacks on all enrolled records in a transaction.
# The previous behavior was to only run the callbacks on the first copy of a record # The previous behavior was to only run the callbacks on the first copy of a record
# if there were multiple copies of the same record enrolled in the transaction. # if there were multiple copies of the same record enrolled in the transaction.
# Rails.application.config.active_record.before_committed_on_all_records = true Rails.application.config.active_record.before_committed_on_all_records = true
# Disable automatic column serialization into YAML. # Disable automatic column serialization into YAML.
# To keep the historic behavior, you can set it to `YAML`, however it is # To keep the historic behavior, you can set it to `YAML`, however it is
# recommended to explicitly define the serialization method for each column # recommended to explicitly define the serialization method for each column
# rather than to rely on a global default. # rather than to rely on a global default.
# Rails.application.config.active_record.default_column_serializer = nil Rails.application.config.active_record.default_column_serializer = nil
# Run `after_commit` and `after_*_commit` callbacks in the order they are defined in a model. # Run `after_commit` and `after_*_commit` callbacks in the order they are defined in a model.
# This matches the behaviour of all other callbacks. # This matches the behaviour of all other callbacks.
# In previous versions of Rails, they ran in the inverse order. # In previous versions of Rails, they ran in the inverse order.
# Rails.application.config.active_record.run_after_transaction_callbacks_in_order_defined = true Rails.application.config.active_record.run_after_transaction_callbacks_in_order_defined = true
# Whether a `transaction` block is committed or rolled back when exited via `return`, `break` or `throw`. # Whether a `transaction` block is committed or rolled back when exited via `return`, `break` or `throw`.
# #
@ -169,7 +167,7 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# Controls when to generate a value for <tt>has_secure_token</tt> declarations. # Controls when to generate a value for <tt>has_secure_token</tt> declarations.
# #
# Rails.application.config.active_record.generate_secure_token_on = :initialize Rails.application.config.active_record.generate_secure_token_on = :initialize
# ** Please read carefully, this must be configured in config/application.rb ** # ** Please read carefully, this must be configured in config/application.rb **
# Change the format of the cache entry. # Change the format of the cache entry.
@ -190,7 +188,7 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# #
# In previous versions of Rails, Action View always used `Rails::HTML4::Sanitizer` as its vendor. # In previous versions of Rails, Action View always used `Rails::HTML4::Sanitizer` as its vendor.
# #
# Rails.application.config.action_view.sanitizer_vendor = Rails::HTML::Sanitizer.best_supported_vendor Rails.application.config.action_view.sanitizer_vendor = Rails::HTML::Sanitizer.best_supported_vendor
# Configure Action Text to use an HTML5 standards-compliant sanitizer when it is supported on your # Configure Action Text to use an HTML5 standards-compliant sanitizer when it is supported on your
# platform. # platform.
@ -213,4 +211,4 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# #
# In previous versions of Rails, these test helpers always used an HTML4 parser. # In previous versions of Rails, these test helpers always used an HTML4 parser.
# #
# Rails.application.config.dom_testing_default_html_version = :html5 Rails.application.config.dom_testing_default_html_version = :html5

View File

@ -1,5 +1,5 @@
--- ---
fr-QC: fr-CA:
activerecord: activerecord:
attributes: attributes:
poll: poll:

View File

@ -1,5 +1,5 @@
--- ---
fr-QC: fr-CA:
devise: devise:
confirmations: confirmations:
confirmed: Votre adresse de courriel a été validée avec succès. confirmed: Votre adresse de courriel a été validée avec succès.
@ -20,8 +20,8 @@ fr-QC:
confirmation_instructions: confirmation_instructions:
action: Vérifier ladresse courriel action: Vérifier ladresse courriel
action_with_app: Confirmer et retourner à %{app} action_with_app: Confirmer et retourner à %{app}
explanation: Vous avez créé un compte sur %{host} avec cette adresse courriel. Vous êtes à un clic de lactiver. Si ce n'était pas vous, veuiller ignorer ce courriel. explanation: Vous avez créé un compte sur %{host} avec cette adresse courriel. Vous êtes à un clic de lactiver. Si ce n'était pas vous, veuillez ignorer ce courriel.
explanation_when_pending: Vous avez demandé à vous inscrire à %{host} avec cette adresse courriel. Une fois que vous aurez confirmé cette adresse, nous étudierons votre demande. Vous pouvez vous connecter pour changer vos détails ou supprimer votre compte, mais vous ne pouvez pas accéder à la plupart des fonctionalités du compte avant que votre compte ne soit approuvé. Si votre demande est rejetée, vos données seront supprimées, donc aucune action supplémentaire ne sera requise de votre part. Si ce n'était pas vous, veuiller ignorer ce courriel. explanation_when_pending: Vous avez demandé à vous inscrire à %{host} avec cette adresse courriel. Une fois que vous aurez confirmé cette adresse, nous étudierons votre demande. Vous pouvez vous connecter pour changer vos détails ou supprimer votre compte, mais vous ne pouvez pas accéder à la plupart des fonctionnalités du compte avant que votre compte ne soit approuvé. Si votre demande est rejetée, vos données seront supprimées, donc aucune action supplémentaire ne sera requise de votre part. Si ce n'était pas vous, veuillez ignorer ce courriel.
extra_html: Veuillez également consulter <a href="%{terms_path}">les règles du serveur</a> et <a href="%{policy_path}">nos conditions dutilisation</a>. extra_html: Veuillez également consulter <a href="%{terms_path}">les règles du serveur</a> et <a href="%{policy_path}">nos conditions dutilisation</a>.
subject: 'Mastodon: Instructions de confirmation pour %{instance}' subject: 'Mastodon: Instructions de confirmation pour %{instance}'
title: Vérifier ladresse courriel title: Vérifier ladresse courriel

View File

@ -1,5 +1,5 @@
--- ---
fr-QC: fr-CA:
activerecord: activerecord:
attributes: attributes:
doorkeeper/application: doorkeeper/application:

View File

@ -1,5 +1,5 @@
--- ---
fr-QC: fr-CA:
about: about:
about_mastodon_html: 'Le réseau social de l''avenir : pas de publicité, pas de surveillance institutionnelle, conception éthique et décentralisation ! Gardez le contrôle de vos données avec Mastodon !' about_mastodon_html: 'Le réseau social de l''avenir : pas de publicité, pas de surveillance institutionnelle, conception éthique et décentralisation ! Gardez le contrôle de vos données avec Mastodon !'
contact_missing: Non défini contact_missing: Non défini

View File

@ -1,5 +1,5 @@
--- ---
fr-QC: fr-CA:
simple_form: simple_form:
hints: hints:
account: account:

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class FixCanadianFrenchLocale < ActiveRecord::Migration[7.0]
class User < ApplicationRecord
# Dummy class, to make migration possible across version changes
end
disable_ddl_transaction!
def up
User.where(locale: 'fr-QC').in_batches do |users|
users.update_all(locale: 'fr-CA')
end
end
def down
User.where(locale: 'fr-CA').in_batches do |users|
users.update_all(locale: 'fr-QC')
end
end
end

View File

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.1].define(version: 2023_12_22_100226) do ActiveRecord::Schema[7.1].define(version: 2024_01_09_103012) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"

View File

@ -83,6 +83,11 @@ namespace :tests do
puts 'Default posting language not migrated as expected for kmr users' puts 'Default posting language not migrated as expected for kmr users'
exit(1) exit(1)
end end
unless Account.find_local('qcuser').user.locale == 'fr-CA'
puts 'Locale for fr-QC users not updated to fr-CA as expected'
exit(1)
end
end end
desc 'Populate the database with test data for 2.4.3' desc 'Populate the database with test data for 2.4.3'
@ -142,13 +147,19 @@ namespace :tests do
INSERT INTO "accounts" INSERT INTO "accounts"
(id, username, domain, private_key, public_key, created_at, updated_at) (id, username, domain, private_key, public_key, created_at, updated_at)
VALUES VALUES
(10, 'kmruser', NULL, #{user_private_key}, #{user_public_key}, now(), now()); (10, 'kmruser', NULL, #{user_private_key}, #{user_public_key}, now(), now()),
(11, 'qcuser', NULL, #{user_private_key}, #{user_public_key}, now(), now());
INSERT INTO "users" INSERT INTO "users"
(id, account_id, email, created_at, updated_at, admin, locale, chosen_languages) (id, account_id, email, created_at, updated_at, admin, locale, chosen_languages)
VALUES VALUES
(4, 10, 'kmruser@localhost', now(), now(), false, 'ku', '{en,kmr,ku,ckb}'); (4, 10, 'kmruser@localhost', now(), now(), false, 'ku', '{en,kmr,ku,ckb}');
INSERT INTO "users"
(id, account_id, email, created_at, updated_at, locale)
VALUES
(5, 11, 'qcuser@localhost', now(), now(), 'fr-QC');
INSERT INTO "settings" INSERT INTO "settings"
(id, thing_type, thing_id, var, value, created_at, updated_at) (id, thing_type, thing_id, var, value, created_at, updated_at)
VALUES VALUES

View File

@ -13,189 +13,65 @@ RSpec.describe Setting do
end end
describe '.[]' do describe '.[]' do
let(:key) { 'key' }
let(:cache_key) { 'cache-key' }
let(:cache_value) { 'cache-value' }
before do before do
allow(described_class).to receive(:rails_initialized?).and_return(rails_initialized) allow(described_class).to receive(:cache_key).with(key).and_return(cache_key)
end end
let(:key) { 'key' } context 'when Rails.cache does not exists' do
context 'when rails_initialized? is falsey' do
let(:rails_initialized) { false }
it 'calls RailsSettings::Base#[]' do
allow(RailsSettings::Base).to receive(:[]).with(key)
described_class[key]
expect(RailsSettings::Base).to have_received(:[]).with(key)
end
end
context 'when rails_initialized? is truthy' do
before do before do
allow(RailsSettings::Base).to receive(:cache_key).with(key, nil).and_return(cache_key) allow(described_class).to receive(:default_settings).and_return(default_settings)
Fabricate(:setting, var: key, value: 42) if save_setting
Rails.cache.delete(cache_key)
end end
let(:rails_initialized) { true } let(:default_value) { 'default_value' }
let(:cache_key) { 'cache-key' } let(:default_settings) { { key => default_value } }
let(:cache_value) { 'cache-value' } let(:save_setting) { true }
it 'calls not RailsSettings::Base#[]' do context 'when the setting has been saved to database' do
allow(RailsSettings::Base).to receive(:[]).with(key) it 'returns the value from database' do
described_class[key]
expect(RailsSettings::Base).to_not have_received(:[]).with(key)
end
context 'when Rails.cache does not exists' do
before do
allow(RailsSettings::Settings).to receive(:object).with(key).and_return(object)
allow(described_class).to receive(:default_settings).and_return(default_settings)
settings_double = instance_double(Settings::ScopedSettings, thing_scoped: records)
allow(Settings::ScopedSettings).to receive(:new).and_return(settings_double)
Rails.cache.delete(cache_key)
end
let(:object) { nil }
let(:default_value) { 'default_value' }
let(:default_settings) { { key => default_value } }
let(:records) { [Fabricate(:setting, var: key, value: nil)] }
it 'calls RailsSettings::Settings.object' do
allow(RailsSettings::Settings).to receive(:object).with(key)
described_class[key]
expect(RailsSettings::Settings).to have_received(:object).with(key)
end
context 'when RailsSettings::Settings.object returns truthy' do
let(:object) { db_val }
let(:db_val) { instance_double(described_class, value: 'db_val') }
context 'when default_value is a Hash' do
let(:default_value) { { default_value: 'default_value' } }
it 'calls default_value.with_indifferent_access.merge!' do
indifferent_hash = instance_double(Hash, merge!: nil)
allow(default_value).to receive(:with_indifferent_access).and_return(indifferent_hash)
described_class[key]
expect(default_value).to have_received(:with_indifferent_access)
expect(indifferent_hash).to have_received(:merge!).with(db_val.value)
end
end
context 'when default_value is not a Hash' do
let(:default_value) { 'default_value' }
it 'returns db_val.value' do
expect(described_class[key]).to be db_val.value
end
end
end
context 'when RailsSettings::Settings.object returns falsey' do
let(:object) { nil }
it 'returns default_settings[key]' do
expect(described_class[key]).to be default_settings[key]
end
end
end
context 'when Rails.cache exists' do
before do
Rails.cache.write(cache_key, cache_value)
end
it 'does not query the database' do
callback = double callback = double
allow(callback).to receive(:call) allow(callback).to receive(:call)
ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do
described_class[key] expect(described_class[key]).to eq 42
end end
expect(callback).to_not have_received(:call)
end
it 'returns the cached value' do expect(callback).to have_received(:call)
expect(described_class[key]).to eq cache_value
end
end
end
end
describe '.all_as_records' do
before do
settings_double = instance_double(Settings::ScopedSettings, thing_scoped: records)
allow(Settings::ScopedSettings).to receive(:new).and_return(settings_double)
allow(described_class).to receive(:default_settings).and_return(default_settings)
end
let(:key) { 'key' }
let(:default_value) { 'default_value' }
let(:default_settings) { { key => default_value } }
let(:original_setting) { Fabricate(:setting, var: key, value: nil) }
let(:records) { [original_setting] }
it 'returns a Hash' do
expect(described_class.all_as_records).to be_a Hash
end
context 'when records includes Setting with var as the key' do
let(:records) { [original_setting] }
it 'includes the original Setting' do
setting = described_class.all_as_records[key]
expect(setting).to eq original_setting
end
end
context 'when records includes nothing' do
let(:records) { [] }
context 'when default_value is not a Hash' do
it 'includes Setting with value of default_value' do
setting = described_class.all_as_records[key]
expect(setting).to be_a described_class
expect(setting).to have_attributes(var: key)
expect(setting).to have_attributes(value: 'default_value')
end end
end end
context 'when default_value is a Hash' do context 'when the setting has not been saved to database' do
let(:default_value) { { 'foo' => 'fuga' } } let(:save_setting) { false }
it 'returns {}' do it 'returns default_settings[key]' do
expect(described_class.all_as_records).to eq({}) expect(described_class[key]).to be default_settings[key]
end end
end end
end end
end
describe '.default_settings' do context 'when Rails.cache exists' do
subject { described_class.default_settings } before do
Rails.cache.write(cache_key, cache_value)
before do
allow(RailsSettings::Default).to receive(:enabled?).and_return(enabled)
end
context 'when RailsSettings::Default.enabled? is false' do
let(:enabled) { false }
it 'returns {}' do
expect(subject).to eq({})
end end
end
context 'when RailsSettings::Settings.enabled? is true' do it 'does not query the database' do
let(:enabled) { true } callback = double
allow(callback).to receive(:call)
ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do
described_class[key]
end
expect(callback).to_not have_received(:call)
end
it 'returns instance of RailsSettings::Default' do it 'returns the cached value' do
expect(subject).to be_a RailsSettings::Default expect(described_class[key]).to eq cache_value
end end
end end
end end