Add podcast_appearances joined table (forem#82) (#11354)

* Add podcast_appearances joined table (forem#82)

* Add podcast appearances keys unique constraint and creator property (forem#82)

* Add podcast_appearance role validation forem(#82)

* Add spec test for podcast_appearances model (forem#82)

* Small refactoring - place podcast appearance association by alphabetical order

* Adapt m2m association to pass rspec test (forem#82)

* Rename podcast appearance model to podcast episode appearance and remove fk indexing

* Rename podcast appearance model to podcast episode appearance and remove fk indexing

* Rename podcast episode appearance models and spec models. Update podcast episode and user spec tests (forem#82)

* Rename podcast episode appearances composite index to follow Rails naming pattern (forem#82)

* Remove ddl_transaction disabling and conurrent index adding from appearance migration

* Add role validation in model spec (forem#82)
This commit is contained in:
Nenad Pantelić 2020-11-30 17:12:52 +01:00 committed by GitHub
parent d43ff0d46c
commit ad04158b90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 75 additions and 1 deletions

View file

@ -16,6 +16,8 @@ class PodcastEpisode < ApplicationRecord
belongs_to :podcast
has_many :comments, as: :commentable, inverse_of: :commentable, dependent: :nullify
has_many :podcast_episode_appearances, dependent: :destroy
has_many :users, through: :podcast_episode_appearances
mount_uploader :image, ProfileImageUploader
mount_uploader :social_image, ProfileImageUploader

View file

@ -0,0 +1,7 @@
class PodcastEpisodeAppearance < ApplicationRecord
belongs_to :user, class_name: "User", inverse_of: :podcast_episode_appearances
belongs_to :podcast_episode
validates :podcast_episode_id, uniqueness: { scope: :user_id }
validates :podcast_episode_id, :user_id, :role, presence: true
validates :role, inclusion: { in: %w[host guest], message: "provided role is not valid" }
end

View file

@ -118,6 +118,8 @@ class User < ApplicationRecord
has_many :organizations, through: :organization_memberships
# we keep page views as they belong to the article, not to the user who viewed it
has_many :page_views, dependent: :nullify
has_many :podcast_episode_appearances, dependent: :destroy, inverse_of: :user
has_many :podcast_episodes, through: :podcast_episode_appearances, source: :podcast_episode
has_many :podcast_ownerships, dependent: :destroy, inverse_of: :owner
has_many :podcasts_owned, through: :podcast_ownerships, source: :podcast
has_many :poll_skips, dependent: :destroy

View file

@ -0,0 +1,16 @@
class CreatePodcastEpisodeAppearances < ActiveRecord::Migration[6.0]
def change
create_table :podcast_episode_appearances do |t|
t.references :user, null: false, foreign_key: true, index: false
t.references :podcast_episode, null: false, foreign_key: true, index: false
t.string :role, null: false, default: "guest"
t.boolean :approved, null: false, default: false
t.boolean :featured_on_user_profile, null: false, default: false
t.timestamps
end
add_index :podcast_episode_appearances,
%i[podcast_episode_id user_id],
unique: true,
name: "index_pod_episode_appearances_on_podcast_episode_id_and_user_id"
end
end

View file

@ -10,8 +10,8 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_11_19_153512) do
ActiveRecord::Schema.define(version: 2020_11_19_153512) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "pgcrypto"
@ -848,6 +848,17 @@ ActiveRecord::Schema.define(version: 2020_11_19_153512) do
t.index ["slug"], name: "index_pages_on_slug", unique: true
end
create_table "podcast_episode_appearances", force: :cascade do |t|
t.boolean "approved", default: false, null: false
t.datetime "created_at", precision: 6, null: false
t.boolean "featured_on_user_profile", default: false, null: false
t.bigint "podcast_episode_id", null: false
t.string "role", default: "guest", null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "user_id", null: false
t.index ["podcast_episode_id", "user_id"], name: "index_pod_episode_appearances_on_podcast_episode_id_and_user_id", unique: true
end
create_table "podcast_episodes", force: :cascade do |t|
t.boolean "any_comments_hidden", default: false
t.text "body"
@ -1436,6 +1447,8 @@ ActiveRecord::Schema.define(version: 2020_11_19_153512) do
add_foreign_key "organization_memberships", "users", on_delete: :cascade
add_foreign_key "page_views", "articles", on_delete: :cascade
add_foreign_key "page_views", "users", on_delete: :nullify
add_foreign_key "podcast_episode_appearances", "podcast_episodes"
add_foreign_key "podcast_episode_appearances", "users"
add_foreign_key "podcast_episodes", "podcasts", on_delete: :cascade
add_foreign_key "podcast_ownerships", "podcasts"
add_foreign_key "podcast_ownerships", "users"

View file

@ -0,0 +1,7 @@
FactoryBot.define do
factory :podcast_episode_appearance do
user
podcast_episode
role { "guest" }
end
end

View file

@ -0,0 +1,23 @@
require "rails_helper"
RSpec.describe PodcastEpisodeAppearance, type: :model do
let(:podcast_episode_appearance) { create(:podcast_episode_appearance) }
describe "validations" do
subject { podcast_episode_appearance }
it { is_expected.to belong_to(:user).inverse_of(:podcast_episode_appearances) }
it { is_expected.to belong_to(:podcast_episode) }
it { is_expected.to validate_presence_of(:podcast_episode_id) }
it { is_expected.to validate_presence_of(:user_id) }
it { is_expected.to validate_presence_of(:role) }
it do
expect(podcast_episode_appearance).to validate_inclusion_of(:role).in_array(%w[host guest])
.with_message("provided role is not valid")
end
it { is_expected.to validate_uniqueness_of(:podcast_episode_id).scoped_to(:user_id) }
end
end

View file

@ -9,6 +9,8 @@ RSpec.describe PodcastEpisode, type: :model do
it { is_expected.to belong_to(:podcast) }
it { is_expected.to have_many(:comments).inverse_of(:commentable).dependent(:nullify) }
it { is_expected.to have_many(:podcast_episode_appearances).dependent(:destroy) }
it { is_expected.to have_many(:users).through(:podcast_episode_appearances) }
it { is_expected.to validate_presence_of(:comments_count) }
it { is_expected.to validate_presence_of(:guid) }

View file

@ -68,6 +68,8 @@ RSpec.describe User, type: :model do
it { is_expected.to have_many(:organization_memberships).dependent(:destroy) }
it { is_expected.to have_many(:organizations).through(:organization_memberships) }
it { is_expected.to have_many(:page_views).dependent(:nullify) }
it { is_expected.to have_many(:podcast_episode_appearances).dependent(:destroy) }
it { is_expected.to have_many(:podcast_episodes).through(:podcast_episode_appearances).source(:podcast_episode) }
it { is_expected.to have_many(:podcast_ownerships).dependent(:destroy) }
it { is_expected.to have_many(:podcasts_owned).through(:podcast_ownerships).source(:podcast) }
it { is_expected.to have_many(:poll_skips).dependent(:destroy) }