[deploy] Introduce ClassifiedListingCategory model (#7172)

* Add ClassifiedListingCategoryModel

* Add data update script for classified listing categories

* Add foreign key to reference

* Move data update script to temporary rake task

* Update factory

* Add and fix specs

* Fix typo

* Fix migration

* Correctly add unique index

* Fix migration

* Add slug column to classified listing categories

* Add unique index for slug column
This commit is contained in:
Michael Kohl 2020-04-13 20:01:58 +07:00 committed by GitHub
parent 80737b5404
commit ca23b8e1c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 112 additions and 2 deletions

View file

@ -4,6 +4,7 @@ class ClassifiedListing < ApplicationRecord
SEARCH_SERIALIZER = Search::ClassifiedListingSerializer
SEARCH_CLASS = Search::ClassifiedListing
# TODO: remove this once we are live with the new ClassifiedListingCategory model
CATEGORIES_AVAILABLE = {
cfp: { cost: 1, name: "Conference CFP", rules: "Currently open for proposals, with link to form." },
forhire: { cost: 1, name: "Available for Hire", rules: "You are available for hire." },
@ -18,8 +19,13 @@ class ClassifiedListing < ApplicationRecord
misc: { cost: 1, name: "Miscellaneous", rules: "Must not fit in any other category." }
}.with_indifferent_access.freeze
# TODO: remove this once we are live with the new ClassifiedListingCategory model
before_validation :assign_classified_listing_category
attr_accessor :action
# TODO: this is optional for now to ease the migration
belongs_to :classified_listing_category, optional: true
belongs_to :user
belongs_to :organization, optional: true
before_save :evaluate_markdown
@ -109,4 +115,12 @@ class ClassifiedListing < ApplicationRecord
def create_slug
self.slug = title.to_s.downcase.parameterize.tr("_", "") + "-" + rand(100_000).to_s(26)
end
def assign_classified_listing_category
category_name = CATEGORIES_AVAILABLE.dig(attributes["category"], :name)
category = ClassifiedListingCategory.find_by(name: category_name)
return unless category
self.classified_listing_category_id = category.id
end
end

View file

@ -0,0 +1,6 @@
class ClassifiedListingCategory < ApplicationRecord
has_many :classified_listings
validates :name, :cost, :rules, :slug, presence: true
validates :name, :slug, uniqueness: true
end

View file

@ -0,0 +1,14 @@
class CreateClassifiedListingCategories < ActiveRecord::Migration[5.2]
def change
create_table :classified_listing_categories do |t|
t.string :name, null: false
t.integer :cost, null: false
t.string :rules, null: false
t.string :slug, null: false
t.timestamps
end
add_index(:classified_listing_categories, :name, unique: true)
add_index(:classified_listing_categories, :slug, unique: true)
end
end

View file

@ -0,0 +1,10 @@
class AddListingCategoryToClassifiedListing < ActiveRecord::Migration[5.2]
disable_ddl_transaction!
def change
add_reference :classified_listings,
:classified_listing_category,
foreign_key: true,
index: { algorithm: :concurrently }
end
end

View file

@ -10,8 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_04_07_091449) do
ActiveRecord::Schema.define(version: 2020_04_09_050122) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -311,11 +310,23 @@ ActiveRecord::Schema.define(version: 2020_04_07_091449) do
t.index ["slug"], name: "index_chat_channels_on_slug", unique: true
end
create_table "classified_listing_categories", force: :cascade do |t|
t.integer "cost", null: false
t.datetime "created_at", null: false
t.string "name", null: false
t.string "rules", null: false
t.string "slug", null: false
t.datetime "updated_at", null: false
t.index ["name"], name: "index_classified_listing_categories_on_name", unique: true
t.index ["slug"], name: "index_classified_listing_categories_on_slug", unique: true
end
create_table "classified_listings", force: :cascade do |t|
t.text "body_markdown"
t.datetime "bumped_at"
t.string "cached_tag_list"
t.string "category"
t.bigint "classified_listing_category_id"
t.boolean "contact_via_connect", default: false
t.datetime "created_at", null: false
t.datetime "expires_at"
@ -328,6 +339,7 @@ ActiveRecord::Schema.define(version: 2020_04_07_091449) do
t.string "title"
t.datetime "updated_at", null: false
t.bigint "user_id"
t.index ["classified_listing_category_id"], name: "index_classified_listings_on_classified_listing_category_id"
t.index ["organization_id"], name: "index_classified_listings_on_organization_id"
t.index ["user_id"], name: "index_classified_listings_on_user_id"
end
@ -1232,6 +1244,7 @@ ActiveRecord::Schema.define(version: 2020_04_07_091449) do
add_foreign_key "badge_achievements", "users"
add_foreign_key "chat_channel_memberships", "chat_channels"
add_foreign_key "chat_channel_memberships", "users"
add_foreign_key "classified_listings", "classified_listing_categories"
add_foreign_key "classified_listings", "users", on_delete: :cascade
add_foreign_key "email_authorizations", "users", on_delete: :cascade
add_foreign_key "identities", "users", on_delete: :cascade

View file

@ -0,0 +1,13 @@
namespace :temporary do
namespace :classified_listings do
desc "Backfill classified listings categories"
task backfill_categories: :environment do
ClassifiedListing::CATEGORIES_AVAILABLE.each do |key, attributes|
category = ClassifiedListingCategory.find_or_create_by!(attributes.merge(slug: key))
ClassifiedListing.
where(category: key.to_s).
update_all(classified_listing_category_id: category.id)
end
end
end
end

View file

@ -0,0 +1,12 @@
FactoryBot.define do
factory :classified_listing_category do
name { "Education/Courses" }
cost { [1, 5, 25].sample }
rules { Faker::Hipster.paragraph(sentence_count: 1) }
slug { "education" }
trait :cfp do
name { "Conference CFP" }
end
end
end

View file

@ -0,0 +1,16 @@
require "rails_helper"
RSpec.describe ClassifiedListingCategory, type: :model do
describe "validations" do
# The uniqueness validation didn't work without this, see section "Caveat" at
# https://www.rubydoc.info/github/thoughtbot/shoulda-matchers/Shoulda%2FMatchers%2FActiveRecord:validate_uniqueness_of
subject { create(:classified_listing_category) }
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_presence_of(:cost) }
it { is_expected.to validate_presence_of(:rules) }
it { is_expected.to validate_presence_of(:slug) }
it { is_expected.to validate_uniqueness_of(:name) }
it { is_expected.to validate_uniqueness_of(:slug) }
end
end

View file

@ -32,6 +32,18 @@ RSpec.describe ClassifiedListing, type: :model do
end
end
# TODO: remove this once we are live with the new ClassifiedListingCategory model
describe "classified listing category" do
it "automatically assigns a category on save" do
create(:classified_listing_category)
cl = build(:classified_listing, user_id: user.id)
cl.save
expect(cl).to be_valid
expect(cl.reload.classified_listing_category).to be_present
end
end
describe "body html" do
it "converts markdown to html" do
expect(classified_listing.processed_html).to include("<p>")