diff --git a/Gemfile b/Gemfile
index d65386dacf..6987114b5e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -75,7 +75,6 @@ gem 'premailer-rails'
gem 'rack-attack', '~> 6.6'
gem 'rack-cors', '~> 2.0', require: 'rack/cors'
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 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
diff --git a/Gemfile.lock b/Gemfile.lock
index 442022e81a..549781aed4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -18,14 +18,6 @@ GIT
sidekiq (>= 3.5)
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
remote: https://github.com/stanhu/omniauth-cas.git
revision: 4211e6d05941b4a981f9a36b49ec166cecd0e271
@@ -272,7 +264,7 @@ GEM
erubi (1.12.0)
et-orbi (1.2.7)
tzinfo
- excon (0.104.0)
+ excon (0.109.0)
fabrication (2.31.0)
faker (3.2.2)
i18n (>= 1.8.11, < 2)
@@ -307,7 +299,7 @@ GEM
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
rake
- fog-core (2.3.0)
+ fog-core (2.4.0)
builder
excon (~> 0.71)
formatador (>= 0.2, < 2.0)
@@ -378,9 +370,9 @@ GEM
terminal-table (>= 1.5.1)
idn-ruby (0.1.5)
io-console (0.7.1)
- irb (1.11.0)
+ irb (1.11.1)
rdoc
- reline (>= 0.3.8)
+ reline (>= 0.4.2)
jmespath (1.6.2)
json (2.7.1)
json-canonicalization (1.0.0)
@@ -624,7 +616,7 @@ GEM
redlock (1.3.2)
redis (>= 3.0.0, < 6.0)
regexp_parser (2.8.3)
- reline (0.4.1)
+ reline (0.4.2)
io-console (~> 0.5)
request_store (1.5.1)
rack (>= 1.4)
@@ -692,7 +684,7 @@ GEM
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
- ruby-prof (1.6.3)
+ ruby-prof (1.7.0)
ruby-progressbar (1.13.0)
ruby-saml (1.15.0)
nokogiri (>= 1.13.10)
@@ -922,7 +914,6 @@ DEPENDENCIES
rails (~> 7.1.1)
rails-controller-testing (~> 1.0)
rails-i18n (~> 7.0)
- rails-settings-cached (~> 0.6)!
rdf-normalize (~> 0.5)
redcarpet (~> 3.6)
redis (~> 4.5)
diff --git a/app/helpers/languages_helper.rb b/app/helpers/languages_helper.rb
index 0d4edceb7b..87f0f288d3 100644
--- a/app/helpers/languages_helper.rb
+++ b/app/helpers/languages_helper.rb
@@ -224,7 +224,7 @@ module LanguagesHelper
'en-GB': 'English (British)',
'es-AR': 'Español (Argentina)',
'es-MX': 'Español (México)',
- 'fr-QC': 'Français (Canadien)',
+ 'fr-CA': 'Français (Canadien)',
'pt-BR': 'Português (Brasil)',
'pt-PT': 'Português (Portugal)',
'sr-Latn': 'Srpski (latinica)',
diff --git a/app/javascript/mastodon/locales/fr-QC.json b/app/javascript/mastodon/locales/fr-CA.json
similarity index 100%
rename from app/javascript/mastodon/locales/fr-QC.json
rename to app/javascript/mastodon/locales/fr-CA.json
diff --git a/app/lib/settings/scoped_settings.rb b/app/lib/settings/scoped_settings.rb
deleted file mode 100644
index 983865a685..0000000000
--- a/app/lib/settings/scoped_settings.rb
+++ /dev/null
@@ -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
diff --git a/app/models/setting.rb b/app/models/setting.rb
index 3bdc6ffb40..6af7a98c6d 100644
--- a/app/models/setting.rb
+++ b/app/models/setting.rb
@@ -13,49 +13,114 @@
# thing_id :bigint(8)
#
-class Setting < RailsSettings::Base
- source Rails.root.join('config', 'settings.yml')
+# This file is derived from a fork of the `rails-settings-cached` gem available at
+# 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
var
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
diff --git a/config/initializers/i18n.rb b/config/initializers/i18n.rb
index 39b7a3cc40..1c1cea1b94 100644
--- a/config/initializers/i18n.rb
+++ b/config/initializers/i18n.rb
@@ -31,7 +31,7 @@ Rails.application.configure do
:fi,
:fo,
:fr,
- :'fr-QC',
+ :'fr-CA',
:fy,
:ga,
:gd,
diff --git a/config/initializers/new_framework_defaults_7_1.rb b/config/initializers/new_framework_defaults_7_1.rb
index 1475fe2fd9..bcc300c89f 100644
--- a/config/initializers/new_framework_defaults_7_1.rb
+++ b/config/initializers/new_framework_defaults_7_1.rb
@@ -29,7 +29,7 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# Do not treat an `ActionController::Parameters` instance
# 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
# 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
# state which matches what was committed to the database, typically the last
# 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.
#
@@ -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.
# 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.
-# 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
-# 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
# 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.
# Options are `true`, and `false`. If `false`, the exception will be reported
# 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
# (https://open-telemetry.github.io/opentelemetry-sqlcommenter/), or using the legacy format.
# 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`
# 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
# development and test.
#
-# if Rails.env.local?
-# Rails.application.config.log_file_size = 100 * 1024 * 1024
-# end
+Rails.application.config.log_file_size = 100 * 1024 * 1024 if Rails.env.local?
# Enable raising on assignment to attr_readonly attributes. The previous
# behavior would allow assignment but silently not persist changes to the
# 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.
# 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.
-# 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
# 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.
# 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.
-# 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.
# To keep the historic behavior, you can set it to `YAML`, however it is
# recommended to explicitly define the serialization method for each column
# 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.
# This matches the behaviour of all other callbacks.
# 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`.
#
@@ -169,7 +167,7 @@ Rails.application.config.add_autoload_paths_to_load_path = false
# Controls when to generate a value for has_secure_token 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 **
# 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.
#
-# 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
# 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.
#
-# Rails.application.config.dom_testing_default_html_version = :html5
+Rails.application.config.dom_testing_default_html_version = :html5
diff --git a/config/locales/activerecord.fr-QC.yml b/config/locales/activerecord.fr-CA.yml
similarity index 99%
rename from config/locales/activerecord.fr-QC.yml
rename to config/locales/activerecord.fr-CA.yml
index 607758add6..1a83a0e9e2 100644
--- a/config/locales/activerecord.fr-QC.yml
+++ b/config/locales/activerecord.fr-CA.yml
@@ -1,5 +1,5 @@
---
-fr-QC:
+fr-CA:
activerecord:
attributes:
poll:
diff --git a/config/locales/devise.fr-QC.yml b/config/locales/devise.fr-CA.yml
similarity index 96%
rename from config/locales/devise.fr-QC.yml
rename to config/locales/devise.fr-CA.yml
index 8c1a94dab6..e9f09a6980 100644
--- a/config/locales/devise.fr-QC.yml
+++ b/config/locales/devise.fr-CA.yml
@@ -1,5 +1,5 @@
---
-fr-QC:
+fr-CA:
devise:
confirmations:
confirmed: Votre adresse de courriel a été validée avec succès.
@@ -20,8 +20,8 @@ fr-QC:
confirmation_instructions:
action: Vérifier l’adresse courriel
action_with_app: Confirmer et retourner à %{app}
- explanation: Vous avez créé un compte sur %{host} avec cette adresse courriel. Vous êtes à un clic de l’activer. 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 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: Vous avez créé un compte sur %{host} avec cette adresse courriel. Vous êtes à un clic de l’activer. 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 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 les règles du serveur et nos conditions d’utilisation.
subject: 'Mastodon: Instructions de confirmation pour %{instance}'
title: Vérifier l’adresse courriel
diff --git a/config/locales/doorkeeper.fr-QC.yml b/config/locales/doorkeeper.fr-CA.yml
similarity index 99%
rename from config/locales/doorkeeper.fr-QC.yml
rename to config/locales/doorkeeper.fr-CA.yml
index 043b4a6cda..9d671569f5 100644
--- a/config/locales/doorkeeper.fr-QC.yml
+++ b/config/locales/doorkeeper.fr-CA.yml
@@ -1,5 +1,5 @@
---
-fr-QC:
+fr-CA:
activerecord:
attributes:
doorkeeper/application:
diff --git a/config/locales/fr-QC.yml b/config/locales/fr-CA.yml
similarity index 99%
rename from config/locales/fr-QC.yml
rename to config/locales/fr-CA.yml
index 3d85ced151..c43fa013c7 100644
--- a/config/locales/fr-QC.yml
+++ b/config/locales/fr-CA.yml
@@ -1,5 +1,5 @@
---
-fr-QC:
+fr-CA:
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 !'
contact_missing: Non défini
diff --git a/config/locales/simple_form.fr-QC.yml b/config/locales/simple_form.fr-CA.yml
similarity index 99%
rename from config/locales/simple_form.fr-QC.yml
rename to config/locales/simple_form.fr-CA.yml
index 7a95a1c882..f5a2a428e9 100644
--- a/config/locales/simple_form.fr-QC.yml
+++ b/config/locales/simple_form.fr-CA.yml
@@ -1,5 +1,5 @@
---
-fr-QC:
+fr-CA:
simple_form:
hints:
account:
diff --git a/db/migrate/20240109103012_fix_canadian_french_locale.rb b/db/migrate/20240109103012_fix_canadian_french_locale.rb
new file mode 100644
index 0000000000..1b8ef7a4af
--- /dev/null
+++ b/db/migrate/20240109103012_fix_canadian_french_locale.rb
@@ -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
diff --git a/db/schema.rb b/db/schema.rb
index 05db802b6e..18d51c8bf1 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -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_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
enable_extension "plpgsql"
diff --git a/lib/tasks/tests.rake b/lib/tasks/tests.rake
index 209a73efa5..c3a9dbfd73 100644
--- a/lib/tasks/tests.rake
+++ b/lib/tasks/tests.rake
@@ -83,6 +83,11 @@ namespace :tests do
puts 'Default posting language not migrated as expected for kmr users'
exit(1)
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
desc 'Populate the database with test data for 2.4.3'
@@ -142,13 +147,19 @@ namespace :tests do
INSERT INTO "accounts"
(id, username, domain, private_key, public_key, created_at, updated_at)
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"
(id, account_id, email, created_at, updated_at, admin, locale, chosen_languages)
VALUES
(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"
(id, thing_type, thing_id, var, value, created_at, updated_at)
VALUES
diff --git a/spec/models/setting_spec.rb b/spec/models/setting_spec.rb
index e98062810e..a1e24e8350 100644
--- a/spec/models/setting_spec.rb
+++ b/spec/models/setting_spec.rb
@@ -13,189 +13,65 @@ RSpec.describe Setting do
end
describe '.[]' do
+ let(:key) { 'key' }
+ let(:cache_key) { 'cache-key' }
+ let(:cache_value) { 'cache-value' }
+
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
- let(:key) { 'key' }
-
- 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
+ context 'when Rails.cache does not exists' 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
- let(:rails_initialized) { true }
- let(:cache_key) { 'cache-key' }
- let(:cache_value) { 'cache-value' }
+ let(:default_value) { 'default_value' }
+ let(:default_settings) { { key => default_value } }
+ let(:save_setting) { true }
- it 'calls not RailsSettings::Base#[]' do
- allow(RailsSettings::Base).to receive(:[]).with(key)
-
- 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
+ context 'when the setting has been saved to database' do
+ it 'returns the value from database' do
callback = double
allow(callback).to receive(:call)
+
ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do
- described_class[key]
+ expect(described_class[key]).to eq 42
end
- expect(callback).to_not have_received(:call)
- end
- it 'returns the cached value' do
- 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')
+ expect(callback).to have_received(:call)
end
end
- context 'when default_value is a Hash' do
- let(:default_value) { { 'foo' => 'fuga' } }
+ context 'when the setting has not been saved to database' do
+ let(:save_setting) { false }
- it 'returns {}' do
- expect(described_class.all_as_records).to eq({})
+ it 'returns default_settings[key]' do
+ expect(described_class[key]).to be default_settings[key]
end
end
end
- end
- describe '.default_settings' do
- subject { described_class.default_settings }
-
- 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({})
+ context 'when Rails.cache exists' do
+ before do
+ Rails.cache.write(cache_key, cache_value)
end
- end
- context 'when RailsSettings::Settings.enabled? is true' do
- let(:enabled) { true }
+ it 'does not query the database' do
+ 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
- expect(subject).to be_a RailsSettings::Default
+ it 'returns the cached value' do
+ expect(described_class[key]).to eq cache_value
end
end
end