2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-03-04 01:15:08 +08:00
discourse/app/models/form_template.rb
Natalie Tay 9e99066b07
DEV: Expand top_tags, topic.tags, etc, to return an array of tag objects instead of tag names (#36678)
Currently in several endpoints, we return an array of strings for tags.
Our goal with this PR is to expand array tag name strings to an array of
tag objects.

#### before: Tags were returned as string arrays
```
{ "tags": ["support", "bug-report"] }
```

#### after: Tags are returned as object arrays
```
{ "tags": [{"id": 12, "name": "support", "slug": "support"}, {"id": 13, "name": "bug-report", "slug": "bug-report"}] }
```

This allows us to start referencing tags by their ids, and return more
information for a tag for future features.

This commit involves updating several areas:
- topic lists (/latest.json, /top.json, /c/:category/:id.json, etc, for
`top_tags`)
- tag chooser components (`MiniTagChooser`, `TagDrop`, etc)
- topic view (/t/:id.json)
- tag groups (/tag_groups.json, tags, parent_tag)
- category settings
- staff action logs
- synonyms
- ...

APIs that reference tags based on their names will still be supported
with a deprecation warning. Moving on, we will reference them using
their tag ids.
2026-02-02 10:03:02 +08:00

82 lines
2.3 KiB
Ruby

# frozen_string_literal: true
class FormTemplate < ActiveRecord::Base
validates :name,
presence: true,
uniqueness: true,
length: {
maximum: -> { SiteSetting.max_form_template_title_length },
}
validates :template,
presence: true,
length: {
maximum: -> { SiteSetting.max_form_template_content_length },
}
validates_with FormTemplateYamlValidator, if: ->(ft) { ft.template }
has_many :category_form_templates, dependent: :destroy
has_many :categories, through: :category_form_templates
class NotAllowed < StandardError
end
def process!(guardian)
parsed_template = YAML.safe_load(template)
tag_group_names = parsed_template.map { |f| f["tag_group"] }.compact.map(&:downcase).uniq
tag_groups =
TagGroup
.includes(:tags)
.visible(guardian)
.where("lower(name) IN (?)", tag_group_names)
.index_by { |tg| tg.name }
parsed_template.map! do |form_field|
next form_field unless form_field["tag_group"]
tag_group_name = form_field["tag_group"]
tags = tag_groups[tag_group_name].tags.reject { |tag| tag.target_tag_id.present? }
ordered_field = {}
tags =
tags.sort_by do |t|
# Transform the name to the displayed value before ordering
display = t.description.presence || t.name.tr("-", " ").upcase
display
end
form_field.each do |key, value|
ordered_field[key] = value
ordered_field["choices"] = tags.map { |t| { "id" => t.id, "name" => t.name } } if key ==
"id"
end
ordered_field["attributes"] ||= {}
ordered_field["attributes"]["tag_group"] = tag_group_name
translated_tags = tags.select { |t| t.description }.to_h { |t| [t.name, t.description] }
ordered_field["attributes"]["tag_choices"] = translated_tags
ordered_field
end
self.template = YAML.dump(parsed_template)
self
end
end
# == Schema Information
#
# Table name: form_templates
#
# id :bigint not null, primary key
# name :string not null
# template :text not null
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_form_templates_on_name (name) UNIQUE
#