From 6c91a9a1db299249658780e206dd6a0430ddb7dd Mon Sep 17 00:00:00 2001
From: ArtOfCode- <hello@artofcode.co.uk>
Date: Fri, 8 May 2020 17:57:46 +0100
Subject: [PATCH] Add model validations and display

---
 app/assets/stylesheets/utilities.scss   |  4 ++++
 app/controllers/questions_controller.rb |  2 +-
 app/models/post.rb                      | 14 ++++++++++++--
 app/models/question.rb                  |  9 ---------
 app/views/posts/_expanded.html.erb      |  9 ++++++---
 app/views/posts/_list.html.erb          |  7 +++++--
 6 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index bf202126f..6f13bce99 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -83,4 +83,8 @@ pre.unformatted {
 
 .stat-value {
   font-size: 2.0em;
+}
+
+.badge.is-tag.is-outlined {
+  border: 1px solid #001db1;
 }
\ No newline at end of file
diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb
index 916e3f00e..f68b28e44 100644
--- a/app/controllers/questions_controller.rb
+++ b/app/controllers/questions_controller.rb
@@ -49,7 +49,7 @@ class QuestionsController < ApplicationController
       not_found
       return
     end
-    @questions = @tag.posts.undeleted.order('updated_at DESC').paginate(page: params[:page], per_page: 50)
+    @questions = @tag.posts.list_includes.undeleted.order('updated_at DESC').paginate(page: params[:page], per_page: 50)
   end
 
   def lottery
diff --git a/app/models/post.rb b/app/models/post.rb
index bd3ab8060..4c681d883 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -30,17 +30,18 @@ class Post < ApplicationRecord
   validate :stripped_minimum, if: :question?
   validate :category_allows_post_type
   validate :license_available
+  validate :has_required_tags
 
   scope :undeleted, -> { where(deleted: false) }
   scope :deleted, -> { where(deleted: true) }
   scope :qa_only, -> { where(post_type_id: [Question.post_type_id, Answer.post_type_id]) }
-  scope :list_includes, -> { includes(:user, user: :avatar_attachment) }
+  scope :list_includes, -> { includes(:user, :tags, user: :avatar_attachment) }
 
   after_save :check_attribution_notice
   after_save :modify_author_reputation
   after_save :copy_last_activity_to_parent
   after_save :break_description_cache
-  after_save :update_tag_associations, if: :question?
+  before_validation :update_tag_associations, if: :question?
   after_create :create_initial_revision
   after_create :add_license_if_nil
 
@@ -230,4 +231,13 @@ class Post < ApplicationRecord
       update(license: License.site_default)
     end
   end
+
+  def has_required_tags
+    required = category&.required_tag_ids
+    return unless required.present? && !required.empty?
+
+    unless tag_ids.any? { |t| required.include? t }
+      errors.add(:tags, "must contain at least one required tag (#{category.required_tags.pluck(:name).join(', ')})")
+    end
+  end
 end
diff --git a/app/models/question.rb b/app/models/question.rb
index 50b298947..b0a347e7e 100644
--- a/app/models/question.rb
+++ b/app/models/question.rb
@@ -11,15 +11,6 @@ class Question < Post
     PostType.mapping['Question']
   end
 
-  validates :title, :body, :tags_cache, presence: true
-  validate :tags_in_tag_set
-  validate :maximum_tags
-  validate :maximum_tag_length
-  validate :no_spaces_in_tags
-  validate :stripped_minimum
-
-  after_save :update_tag_associations
-
   def answers
     Answer.where(parent: self)
   end
diff --git a/app/views/posts/_expanded.html.erb b/app/views/posts/_expanded.html.erb
index 1a71fceb5..b00c2ca01 100644
--- a/app/views/posts/_expanded.html.erb
+++ b/app/views/posts/_expanded.html.erb
@@ -98,9 +98,12 @@
           <% if is_question %>
             <div class="post--tags has-padding-2">
               <% tag_set = post.tag_set %>
-              <% post.tags_cache.each do |tag| %>
-                <% next if tag.nil? || tag.empty? %>
-                <%= link_to tag, questions_tagged_path(tag_set: tag_set.id, tag: tag), class: 'badge is-tag' %>
+              <% post.tags.each do |tag| %>
+                <% next if tag.nil? %>
+                <% required = post.category&.required_tag_ids&.include? tag.id %>
+                <% topic = post.category&.topic_tag_ids&.include? tag.id %>
+                <%= link_to tag.name, questions_tagged_path(tag_set: tag_set.id, tag: tag.name),
+                            class: "badge is-tag #{required ? 'is-filled' : ''} #{topic ? 'is-outlined' : ''}" %>
               <% end %>
             </div>
           <% end %>
diff --git a/app/views/posts/_list.html.erb b/app/views/posts/_list.html.erb
index 290017e6d..557282947 100644
--- a/app/views/posts/_list.html.erb
+++ b/app/views/posts/_list.html.erb
@@ -27,8 +27,11 @@
     <div class="has-padding-top-2">
       <% if is_question %>
         <% tag_set = post.tag_set %>
-        <% post.tags_cache.each do |tag| %>
-          <%= link_to tag, questions_tagged_path(tag_set: tag_set.id, tag: tag), class: 'badge is-tag' %>
+        <% post.tags.each do |tag| %>
+          <% required = post.category&.required_tag_ids&.include? tag.id %>
+          <% topic = post.category&.topic_tag_ids&.include? tag.id %>
+          <%= link_to tag.name, questions_tagged_path(tag_set: tag_set.id, tag: tag.name),
+                      class: "badge is-tag #{required ? 'is-filled' : ''} #{topic ? 'is-outlined' : ''}" %>
         <% end %>
       <% end %>
     </div>
-- 
GitLab