Tidying up and documenting Tag model (#15949)
* Tidying up and documenting Tag model Prior to this commit we had a custom `where(alias_for: [nil, ""])` call. That call highlighted that we lacked a term for a Tag that was not an alias. As part of this commit, I named that a "concrete" tag. Further, I added scopes to assist in helping "name" those concepts. This commit also adds a data migration and utilization of StringAttributeCleaner to hopefully get away from `alias_for == ""` situations. As of writing this commit <2022-01-04 Tue 17:22 UTC>, in DEV.to we had 5 tags with `alias_for == ""`: - actionshackathon21 - regex - atlashackathon - hotwire - foremfest In https://dev.to/admin/blazer I ran the following: ```sql SELECT name FROM tags WHERE alias_for = '' ``` * Renaming concrete to direct
This commit is contained in:
parent
775bdb7810
commit
5b10addbb4
4 changed files with 62 additions and 1 deletions
|
|
@ -18,7 +18,7 @@ class TagsController < ApplicationController
|
|||
def index
|
||||
skip_authorization
|
||||
@tags_index = true
|
||||
@tags = Tag.where(alias_for: [nil, ""]).includes(:sponsorship).order(hotness_score: :desc).limit(100)
|
||||
@tags = Tag.direct.includes(:sponsorship).order(hotness_score: :desc).limit(100)
|
||||
end
|
||||
|
||||
def edit
|
||||
|
|
|
|||
|
|
@ -1,3 +1,18 @@
|
|||
# We allow content creators to "tag" their content. This model helps
|
||||
# define what we mean when we "tag" something.
|
||||
#
|
||||
# These tags can be arbitrary or supported (e.g. `tag.supported ==
|
||||
# true`). We allow for sponsorship of tags (see `belongs_to
|
||||
# :sponsorship`). Some tags have moderators. These tags can create a
|
||||
# defacto "sub-community" within a Forem.
|
||||
#
|
||||
# Sometimes we need to consolidate tags (e.g. rubyonrails and rails).
|
||||
# In this case, we mark one of those tags as an alias for the other
|
||||
# (via `alias_for`). The direct tags is the "preferred" tag
|
||||
# (e.g. not the alias).
|
||||
#
|
||||
# @note models with `acts_as_taggable_on` declarations (e.g., Article and Listing)
|
||||
# @see https://developers.forem.com/technical-overview/architecture/#tags for more discussion
|
||||
class Tag < ActsAsTaggableOn::Tag
|
||||
self.ignored_columns = %w[mod_chat_channel_id].freeze
|
||||
|
||||
|
|
@ -10,6 +25,13 @@ class Tag < ActsAsTaggableOn::Tag
|
|||
include Purgeable
|
||||
include PgSearch::Model
|
||||
|
||||
# @note Even though we have a data migration script (see further
|
||||
# comments below), as of <2022-01-04 Tue> we had 5 tags where
|
||||
# the `alias_for == ""` (ideally they should be nil). This
|
||||
# change will help us achieve that goal.
|
||||
#
|
||||
# @see https://github.com/forem/forem/blob/72bb284ba73c3df8aa11525427b1dfa1ceba39df/lib/data_update_scripts/20211115154021_nullify_invalid_tag_fields.rb
|
||||
include StringAttributeCleaner.for(:alias_for)
|
||||
ALLOWED_CATEGORIES = %w[uncategorized language library tool site_mechanic location subcommunity].freeze
|
||||
HEX_COLOR_REGEXP = /\A#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\z/
|
||||
|
||||
|
|
@ -37,6 +59,22 @@ class Tag < ActsAsTaggableOn::Tag
|
|||
|
||||
after_commit :bust_cache
|
||||
|
||||
# @note Even though we have a data migration script (see further
|
||||
# comments below), as of <2022-01-04 Tue> we had 5 tags where
|
||||
# the alias_for was "" (ideally they should be nil). Once we
|
||||
# have the StringAttributeCleaner (see above) in place, and
|
||||
# our next data migration runs, we can remove the [nil, ""]
|
||||
# and favor `where(alias_for: nil)`.
|
||||
#
|
||||
# @see https://github.com/forem/forem/blob/72bb284ba73c3df8aa11525427b1dfa1ceba39df/lib/data_update_scripts/20211115154021_nullify_invalid_tag_fields.rb
|
||||
scope :aliased, -> { where.not(alias_for: [nil, ""]) }
|
||||
|
||||
# @note We had named the concept of a tag that was an alias;
|
||||
# however, prior to adding this scope, we didn't have a name
|
||||
# for a non-aliased tag (aside from "not an alias"). With
|
||||
# this scope we have a name.
|
||||
scope :direct, -> { where(alias_for: [nil, ""]) }
|
||||
|
||||
pg_search_scope :search_by_name,
|
||||
against: :name,
|
||||
using: { tsearch: { prefix: true } }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
module DataUpdateScripts
|
||||
class NullifyEmptyStringForAliasFor
|
||||
def run
|
||||
Tag.where(alias_for: "").update_all(alias_for: nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
require "rails_helper"
|
||||
require Rails.root.join(
|
||||
"lib/data_update_scripts/20220104165348_nullify_empty_string_for_alias_for.rb",
|
||||
)
|
||||
|
||||
describe DataUpdateScripts::NullifyEmptyStringForAliasFor do
|
||||
it "converts empty string `alias_for` to nil value" do
|
||||
Tag.upsert_all([
|
||||
attributes_for(:tag).merge(id: 1, alias_for: "", created_at: Time.current,
|
||||
updated_at: Time.current),
|
||||
])
|
||||
tag = Tag.first
|
||||
|
||||
expect { described_class.new.run }.to change { tag.reload.alias_for }.from("").to(nil)
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue