From 1957cb354ebbd59aeca3c235308809bc6f46ef05 Mon Sep 17 00:00:00 2001 From: evazion Date: Mon, 4 Apr 2022 02:14:23 -0500 Subject: [PATCH] post queries: add #replace_aliases method. --- app/logical/post_query.rb | 12 +++++++++++- app/logical/post_query/ast.rb | 14 ++++++++++++++ app/models/tag_alias.rb | 15 +++++++++++---- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/app/logical/post_query.rb b/app/logical/post_query.rb index 63ec0bfcc..b6047530e 100644 --- a/app/logical/post_query.rb +++ b/app/logical/post_query.rb @@ -47,5 +47,15 @@ class PostQuery select_metatags(*names).first&.value end - memoize :tags + # Return a new query AST, with aliased tags replaced with real tags. + def replace_aliases + ast.replace_tags(aliases) + end + + # A hash mapping aliased tag names to real tag names. + def aliases + TagAlias.aliases_for(tag_names) + end + + memoize :tags, :aliases end diff --git a/app/logical/post_query/ast.rb b/app/logical/post_query/ast.rb index 56266b89e..4a59926a9 100644 --- a/app/logical/post_query/ast.rb +++ b/app/logical/post_query/ast.rb @@ -254,6 +254,20 @@ class PostQuery end end + # Replace tags according to a hash mapping old tag names to new tag names. + # + # @param replacements [Hash] A hash mapping old tag names to new tag names. + # @return [AST] A new AST with the tags replaced. + def replace_tags(replacements) + rewrite do |node| + if node.tag? && replacements.has_key?(node.name) + node(:tag, replacements[node.name]) + else + node + end + end + end + # Call the block on the AST repeatedly until the output stops changing. # # `ast.repeat_until_unchanged(&:trim)` is like doing `ast.trim.trim.trim...` diff --git a/app/models/tag_alias.rb b/app/models/tag_alias.rb index 3019a433c..d09848d52 100644 --- a/app/models/tag_alias.rb +++ b/app/models/tag_alias.rb @@ -10,9 +10,9 @@ class TagAlias < TagRelationship scope :empty, -> { joins(:consequent_tag).merge(Tag.empty) } - def self.to_aliased(names) - names = Array(names).map(&:to_s) - return [] if names.empty? + # Given a list of tag names, return a hash mapping aliased names to real names. + def self.aliases_for(names) + return {} if names.empty? aliases = active.where(antecedent_name: names).map { |ta| [ta.antecedent_name, ta.consequent_name] }.to_h @@ -22,7 +22,14 @@ class TagAlias < TagRelationship aliases[abbrev] = tag.name if tag.present? end - names.map { |name| aliases[name] || name } + aliases + end + + # Given a list of tag names, return a new list with aliased tag names replaced by real tag names. + def self.to_aliased(names) + names = Array.wrap(names).map(&:to_s) + aliases = aliases_for(names) + names.map { |name| aliases.fetch(name, name) } end def process!