このコミットが含まれているのは:
@@ -2,6 +2,10 @@
|
||||
class CountsResourceDefinition
|
||||
# Compatibility belongs at the request boundary, not in field definitions.
|
||||
def self.normalise_params(params)
|
||||
aliases = nil
|
||||
predicates = nil
|
||||
scope = params['name_scope']
|
||||
raise ArgumentError if scope && !['locale', 'language'].include?(scope)
|
||||
params.each_with_object({}) do |(key, value), result|
|
||||
result[key] = value
|
||||
next unless value.is_a?(String)
|
||||
@@ -14,6 +18,16 @@ class CountsResourceDefinition
|
||||
value == 'is_latest')
|
||||
result[key] = 'latest'
|
||||
end
|
||||
if (['columns', 'children', 'order', 'sort', 'child_sort'].include?(key) &&
|
||||
value.match?(/(?:name|aliases)_[a-z]+_[a-z0-9_]+/))
|
||||
aliases ||= new('tags').column_aliases.to_h { [_1[:key], _1[:value]] }
|
||||
result[key] = result[key].gsub(/(?:name|aliases)_[a-z0-9_]+/) { aliases.fetch(_1, _1) }
|
||||
end
|
||||
if (scope != 'language' && key.match?(/\Aconditions\.[0-9]+\.field\z/) &&
|
||||
value.match?(/(?:name|aliases)_[a-z0-9_]+/))
|
||||
predicates ||= new('tags').condition_aliases.to_h { [_1[:key], _1[:value]] }
|
||||
result[key] = value.gsub(/(?:name|aliases)_[a-z0-9_]+/) { predicates.fetch(_1, _1) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -116,12 +130,8 @@ class CountsResourceDefinition
|
||||
|
||||
def name_columns
|
||||
@name_columns ||= begin
|
||||
locales = Locale.joins(:language)
|
||||
.select('locales.code', 'locales.language_code', 'locales.script_code')
|
||||
.order('languages.created_at ASC', 'languages.code ASC', 'locales.code ASC')
|
||||
codes = locales.map do |locale|
|
||||
{ code: locale.code, language_code: locale.language_code,
|
||||
script_code: locale.script_code }
|
||||
codes = Language.select(:code).order(:created_at, :code).map do |language|
|
||||
{ code: language.code, language_code: language.code }
|
||||
end
|
||||
names = codes.map do |locale|
|
||||
{ key: self.class.name_key(locale[:code]), label: 'counts:localeName',
|
||||
@@ -135,7 +145,45 @@ class CountsResourceDefinition
|
||||
end
|
||||
end
|
||||
|
||||
def name_column(key) = name_columns.find { _1[:key] == key }
|
||||
# Old locale-qualified predicates keep their script restriction at the input boundary.
|
||||
def legacy_name_columns
|
||||
@legacy_name_columns ||= Locale.select(:code, :language_code, :script_code)
|
||||
.order(:code).flat_map do |locale|
|
||||
codes = { code: locale.code, language_code: locale.language_code,
|
||||
script_code: locale.script_code }
|
||||
code = locale.code == locale.language_code ? "#{ locale.code }_#{ locale.script_code }" :
|
||||
locale.code
|
||||
[{ key: self.class.name_key(code), label: 'counts:localeName',
|
||||
name_locale: codes, legacy: true },
|
||||
{ key: self.class.aliases_key(code), label: 'counts:localeAliases',
|
||||
name_locale: codes, multiple_values: true, legacy: true }]
|
||||
end
|
||||
end
|
||||
|
||||
def column_aliases
|
||||
legacy_name_columns.map do |field|
|
||||
language = field[:name_locale][:language_code]
|
||||
value = if field[:multiple_values]
|
||||
self.class.aliases_key(language)
|
||||
else self.class.name_key(language)
|
||||
end
|
||||
{ key: field[:key], value: }
|
||||
end
|
||||
end
|
||||
|
||||
def condition_aliases
|
||||
legacy_name_columns.filter_map do |field|
|
||||
code = field[:name_locale][:code]
|
||||
key = field[:multiple_values] ? self.class.aliases_key(code) : self.class.name_key(code)
|
||||
next if key == field[:key]
|
||||
|
||||
{ key:, value: field[:key] }
|
||||
end
|
||||
end
|
||||
|
||||
def name_column(key)
|
||||
name_columns.find { _1[:key] == key } || legacy_name_columns.find { _1[:key] == key }
|
||||
end
|
||||
|
||||
def name_expression(key, row = 'v')
|
||||
if key.start_with?('aliases_')
|
||||
@@ -148,21 +196,26 @@ class CountsResourceDefinition
|
||||
locale = name_column(key).fetch(:name_locale)
|
||||
connection = model.connection
|
||||
path = connection.quote("$.#{ locale[:language_code].to_json }")
|
||||
value = "JSON_UNQUOTE(NULLIF(JSON_EXTRACT(#{ row }.names, " +
|
||||
"CONCAT(#{ path }, '.name')), CAST('null' AS JSON)))"
|
||||
return value unless locale[:script_code]
|
||||
|
||||
script = connection.quote(locale[:script_code])
|
||||
"CASE WHEN LOWER(JSON_UNQUOTE(JSON_EXTRACT(#{ row }.names, " +
|
||||
"CONCAT(#{ path }, '.script_code')))) = LOWER(#{ script }) " +
|
||||
"THEN JSON_UNQUOTE(NULLIF(JSON_EXTRACT(#{ row }.names, " +
|
||||
"CONCAT(#{ path }, '.name')), CAST('null' AS JSON))) END"
|
||||
"THEN #{ value } END"
|
||||
end
|
||||
|
||||
def alias_source(key, row = 'v')
|
||||
locale = name_column(key).fetch(:name_locale)
|
||||
connection = model.connection
|
||||
path = connection.quote("$.#{ locale[:language_code].to_json }.aliases[*]")
|
||||
script = connection.quote(locale[:script_code])
|
||||
source = "JSON_TABLE(COALESCE(#{ row }.names, JSON_OBJECT()), #{ path } " +
|
||||
"COLUMNS (ordinal FOR ORDINALITY, name TEXT PATH '$.name', " +
|
||||
"script TEXT PATH '$.script_code')) locale_alias"
|
||||
return [source, 'locale_alias.name'] unless locale[:script_code]
|
||||
|
||||
script = connection.quote(locale[:script_code])
|
||||
value = "CASE WHEN LOWER(locale_alias.script) = LOWER(#{ script }) " +
|
||||
'THEN locale_alias.name END'
|
||||
[source, value]
|
||||
@@ -231,11 +284,11 @@ class CountsResourceDefinition
|
||||
fields = fields.map do |field|
|
||||
next field unless field[:key] == 'parents'
|
||||
|
||||
field.merge(children: field[:children] + [
|
||||
field.merge(children: field[:children] + legacy_name_columns + [
|
||||
{ key: 'name', label: 'history:name' },
|
||||
{ key: 'names', label: 'counts:columns.names', children: child_fields('names') }])
|
||||
end
|
||||
fields += [{ key: 'name', label: 'counts:columns.name' },
|
||||
fields += legacy_name_columns + [{ key: 'name', label: 'counts:columns.name' },
|
||||
{ key: 'names', label: 'counts:columns.names', children: child_fields('names') },
|
||||
{ key: 'aliases', label: 'tags:aliases', children: child_fields('aliases') }]
|
||||
end
|
||||
@@ -243,7 +296,7 @@ class CountsResourceDefinition
|
||||
fields = fields.map do |field|
|
||||
next field unless field[:key] == 'tags'
|
||||
|
||||
field.merge(children: field[:children] + [
|
||||
field.merge(children: field[:children] + legacy_name_columns + [
|
||||
{ key: 'name', label: 'history:name' },
|
||||
{ key: 'names', label: 'counts:columns.names', children: child_fields('names') },
|
||||
{ key: 'aliases', label: 'tags:aliases', children: child_fields('aliases') }])
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする