diff --git a/app/models/concerns/sdg/relatable.rb b/app/models/concerns/sdg/relatable.rb index 07d71afdc..a64ade1bc 100644 --- a/app/models/concerns/sdg/relatable.rb +++ b/app/models/concerns/sdg/relatable.rb @@ -10,6 +10,8 @@ module SDG::Relatable source: :related_sdg, source_type: sdg_type end + + has_one :sdg_review, as: :relatable, dependent: :destroy, class_name: "SDG::Review" end class_methods do diff --git a/app/models/sdg/review.rb b/app/models/sdg/review.rb new file mode 100644 index 000000000..79198a7a8 --- /dev/null +++ b/app/models/sdg/review.rb @@ -0,0 +1,5 @@ +class SDG::Review < ApplicationRecord + validates :relatable_id, uniqueness: { scope: [:relatable_type] } + + belongs_to :relatable, polymorphic: true, optional: false +end diff --git a/db/migrate/20201221100246_create_sdg_reviews.rb b/db/migrate/20201221100246_create_sdg_reviews.rb new file mode 100644 index 000000000..5a3f594d1 --- /dev/null +++ b/db/migrate/20201221100246_create_sdg_reviews.rb @@ -0,0 +1,8 @@ +class CreateSDGReviews < ActiveRecord::Migration[5.2] + def change + create_table :sdg_reviews do |t| + t.references :relatable, polymorphic: true, index: { unique: true } + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 94cfb14ca..c06db2e50 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1352,6 +1352,14 @@ ActiveRecord::Schema.define(version: 2021_01_07_125458) do t.index ["related_sdg_type", "related_sdg_id"], name: "index_sdg_relations_on_related_sdg_type_and_related_sdg_id" end + create_table "sdg_reviews", force: :cascade do |t| + t.string "relatable_type" + t.bigint "relatable_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["relatable_type", "relatable_id"], name: "index_sdg_reviews_on_relatable_type_and_relatable_id", unique: true + end + create_table "sdg_targets", force: :cascade do |t| t.bigint "goal_id" t.string "code", null: false diff --git a/spec/factories/sdg.rb b/spec/factories/sdg.rb index a9dc94e4e..42073cf67 100644 --- a/spec/factories/sdg.rb +++ b/spec/factories/sdg.rb @@ -18,4 +18,13 @@ FactoryBot.define do factory :sdg_phase, class: "SDG::Phase" do kind { :sensitization } end + + factory :sdg_review, class: "SDG::Review" do + SDG::Related::RELATABLE_TYPES.map { |relatable_type| relatable_type.downcase.gsub("::", "_") } + .each do |relatable| + trait :"#{relatable}_review" do + association :relatable, factory: relatable + end + end + end end diff --git a/spec/models/sdg/relatable_spec.rb b/spec/models/sdg/relatable_spec.rb index 036b5af96..fbdf65890 100644 --- a/spec/models/sdg/relatable_spec.rb +++ b/spec/models/sdg/relatable_spec.rb @@ -117,6 +117,18 @@ describe SDG::Relatable do end end + describe "#sdg_review" do + it "returns nil when relatable is not reviewed" do + expect(relatable.sdg_review).to be_blank + end + + it "returns the review when relatable is reviewed" do + review = create(:sdg_review, relatable: relatable) + + expect(relatable.sdg_review).to eq(review) + end + end + describe ".by_goal" do it "returns everything if no code is provided" do expect(relatable.class.by_goal("")).to eq [relatable] diff --git a/spec/models/sdg/review_spec.rb b/spec/models/sdg/review_spec.rb new file mode 100644 index 000000000..1bd8ff219 --- /dev/null +++ b/spec/models/sdg/review_spec.rb @@ -0,0 +1,23 @@ +require "rails_helper" + +describe SDG::Review do + describe "Validations" do + it "is valid for any given relatable" do + review = build(:sdg_review, :debate_review) + + expect(review).to be_valid + end + + it "is not valid without a relatable" do + review = build(:sdg_review, relatable: nil) + + expect(review).not_to be_valid + end + + it "is not valid when a review for given relatable already exists" do + relatable = create(:sdg_review, :proposal_review).relatable + + expect(build(:sdg_review, relatable: relatable)).not_to be_valid + end + end +end