このコミットが含まれているのは:
2026-10-28 19:28:11 +09:00
コミット 8ea3d211dc
49個のファイルの変更、967行の追加、356行の削除
+33 -20
ファイルの表示
@@ -18,10 +18,10 @@ class CountsExportProjection
'autoGenerated' => 'auto_generated' }.freeze
NAME_FIELDS = ['languageCode', 'scriptCode', 'name', 'aliases', 'autoGenerated'].freeze
CHILDREN = {
'tags' => ['id', 'versionNo', 'kind', 'name', 'category', 'sections', 'names'],
'tags' => ['id', 'versionNo', 'kind', 'name', 'category', 'sections', 'names', 'aliases'],
'names' => NAME_FIELDS,
'aliases' => ['languageCode', 'name', 'scriptCode'],
'parents' => ['id', 'name'] }.freeze
'parents' => ['id', 'name', 'names'] }.freeze
def self.default_columns(resource)
fields = { 'posts' => ['title', 'url', 'tags', 'parents', 'video_ms'],
@@ -47,6 +47,14 @@ class CountsExportProjection
params = CountsDefaults.for(params.merge('resource' => resource)).merge(params)
end
@params = params
definition = CountsResourceDefinition.new(resource)
name_keys = definition.name_columns.map { _1[:key] }
@root_keys = ROOT_KEYS.merge(name_keys.to_h { [_1, _1] })
@child_keys = CHILD_KEYS.merge(name_keys.to_h { [_1, _1] })
@children = CHILDREN.transform_values(&:dup)
['tags', 'parents'].each { @children[_1] += name_keys }
@complete_names = params.fetch('format', 'json') == 'json'
@resource = resource
@labels = JSON.parse(params.fetch('labels', '{}'))
raise ArgumentError unless @labels.is_a?(Hash) && @labels.length <= 100
raise ArgumentError unless @labels.all? { |key, value| valid_label?(key, value) }
@@ -54,7 +62,7 @@ class CountsExportProjection
allowed = if summary
tags ? ['kind', 'tag_id', 'name', 'deprecated', 'count'] : ['group', 'count']
else
CountsQuery::COLUMNS.fetch(resource)
CountsQuery::COLUMNS.fetch(resource) + (resource == 'tags' ? name_keys : [])
end
defaults = summary ? allowed : self.class.default_columns(resource)
@columns = QueryState.list(params.fetch('columns', defaults.join(' ')))
@@ -77,7 +85,7 @@ class CountsExportProjection
end
@selected = params.key?('children') ? QueryState.list(params['children']).to_set :
self.class.default_children(resource).to_set
valid = CHILDREN.flat_map do |key, fields|
valid = @children.flat_map do |key, fields|
paths(fields, key)
end
raise ArgumentError if @selected && (@selected.to_a - valid).any?
@@ -91,9 +99,9 @@ class CountsExportProjection
@selected.delete(path) unless children.any? { @selected.include?("#{ path }.#{ _1 }") }
end
end
CHILDREN.each { |key, fields| prune.call(fields, key) }
@children.each { |key, fields| prune.call(fields, key) }
pairs = @columns.zip(@headers).select do |key, _header|
!CHILDREN.key?(key) || CHILDREN[key].any? { @selected.include?("#{ key }.#{ _1 }") }
!@children.key?(key) || @children[key].any? { @selected.include?("#{ key }.#{ _1 }") }
end
@columns = pairs.map(&:first)
@headers = pairs.map(&:last)
@@ -110,24 +118,28 @@ class CountsExportProjection
def metadata
@columns.each_with_index.map do |key, index|
{ key: @summary ? key : ROOT_KEYS.fetch(key), label: @headers[index] }
{ key: @summary ? key : @root_keys.fetch(key), label: @headers[index] }
end
end
def project(row)
@columns.to_h do |key|
result = @columns.to_h do |key|
if @summary
value = key == 'group' ? { key: row[:key], name: row[:name] } : row[key.to_sym]
[key, value]
else
value = case key
when 'thumbnail' then row[:thumbnail_base]
else row[ROOT_KEYS.fetch(key).to_sym]
else row[@root_keys.fetch(key).to_sym]
end
value = nested(value || [], CHILDREN.fetch(key), key) if CHILDREN.key?(key)
[ROOT_KEYS.fetch(key), value]
value = nested(value || [], @children.fetch(key), key) if @children.key?(key)
[@root_keys.fetch(key), value]
end
end
if @complete_names && ((!@summary && @resource == 'tags') || row.key?(:names))
result['names'] = row[:names] || []
end
result
end
def csv_record(record, row)
@@ -165,7 +177,7 @@ class CountsExportProjection
def fields_for(key)
return NAME_FIELDS if key == 'names'
return ['name', 'scriptCode'] if key == 'aliases'
return ['languageCode', 'name', 'scriptCode'] if key == 'aliases'
[]
end
@@ -197,13 +209,10 @@ class CountsExportProjection
end
def sort_value(row, key)
if key == 'languageCode'
language = named_code(row, 'language')
return @labels.fetch("language:#{ language[:code] }", language[:name])
end
return named_code(row, 'script')[:name] if key == 'scriptCode'
return fetch(row, 'language_code') if key == 'languageCode'
return fetch(row, 'script_code') if key == 'scriptCode'
fetch(row, CHILD_KEYS.fetch(key))
fetch(row, @child_keys.fetch(key))
end
def comparison(left, right)
@@ -249,8 +258,8 @@ class CountsExportProjection
ordered = (@order + keys.map { "#{ prefix }.#{ _1 }" }).uniq
.filter_map { |path| keys.find { "#{ prefix }.#{ _1 }" == path } }
sorted(rows, prefix, fields).map do |row|
ordered.to_h do |key|
stable = CHILD_KEYS.fetch(key)
result = ordered.to_h do |key|
stable = @child_keys.fetch(key)
value = case key
when 'languageCode' then named_code(row, 'language')
when 'scriptCode' then named_code(row, 'script')
@@ -261,6 +270,10 @@ class CountsExportProjection
end
[stable, value]
end
if @complete_names && ['tags', 'parents'].include?(prefix)
result['names'] = fetch(row, 'names') || []
end
result
end
end
end