このコミットが含まれているのは:
2026-10-28 21:13:08 +09:00
コミット 49721e6915
17個のファイルの変更、170行の追加、48行の削除
+1
ファイルの表示
@@ -35,6 +35,7 @@ class CountsCondition
operators: CountsResourceDefinition::OPERATORS.fetch(type) }
entry[:label_values] = field[:label_values] if field[:label_values]
entry[:name_locale] = field[:name_locale] if field[:name_locale]
entry[:legacy] = true if field[:legacy]
result.reject! { _1[:key] == key }
result << entry
visit.call(field[:children] || [], key, path_labels)
+3 -2
ファイルの表示
@@ -13,8 +13,9 @@ class CountsDefaults
'rows' => '', 'cols' => '', 'conditions' => '', 'tags' => '' } }
details = detail_params(resource)
if details
name = CountsResourceDefinition.name_key(locale)
aliases = CountsResourceDefinition.aliases_key(locale)
language = Locale.find_by(code: locale)&.language_code || locale
name = CountsResourceDefinition.name_key(language)
aliases = CountsResourceDefinition.aliases_key(language)
details = details.transform_values do |value|
value.split(' ').flat_map do |token|
if resource == 'tags' && ['name', 'parents.name'].include?(token)
+66 -13
ファイルの表示
@@ -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') }])
+1 -1
ファイルの表示
@@ -6,7 +6,7 @@ class CountsTableQuery
KEYS = ['resource', 'definition', 'mode', 'at', 'execution_at', 'from', 'through',
'timezone', 'rows', 'cols', 'conditions', 'drill', 'tags', 'tag_refs', 'match',
'tag', 'kind', 'resource_id', 'user_id', 'page', 'limit', 'sort', 'locale',
'measures', 'column_order', 'condition_values'].freeze
'measures', 'column_order', 'condition_values', 'name_scope'].freeze
attr_reader :population, :axes, :page, :limit, :mode
def initialize(params)