diff --git a/app/models/abilities/everyone.rb b/app/models/abilities/everyone.rb index 5f9dcb3a5..b32e115e3 100644 --- a/app/models/abilities/everyone.rb +++ b/app/models/abilities/everyone.rb @@ -29,6 +29,7 @@ module Abilities can [:search, :comments, :read, :create, :new_comment], Legislation::Annotation can :read, ::SDG::Goal + can :read, ::SDG::Phase end end end diff --git a/app/models/sdg/phase.rb b/app/models/sdg/phase.rb new file mode 100644 index 000000000..6b5f5aa24 --- /dev/null +++ b/app/models/sdg/phase.rb @@ -0,0 +1,8 @@ +class SDG::Phase < ApplicationRecord + enum kind: %w[sensitization planning monitoring] + validates :kind, presence: true, uniqueness: true + + def self.[](kind) + find_by!(kind: kind) + end +end diff --git a/db/migrate/20210107125458_create_sdg_phases.rb b/db/migrate/20210107125458_create_sdg_phases.rb new file mode 100644 index 000000000..7b4e19b89 --- /dev/null +++ b/db/migrate/20210107125458_create_sdg_phases.rb @@ -0,0 +1,9 @@ +class CreateSDGPhases < ActiveRecord::Migration[5.2] + def change + create_table :sdg_phases do |t| + t.integer :kind, null: false + t.index :kind, unique: true + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 3165e920f..94cfb14ca 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_01_06_132909) do +ActiveRecord::Schema.define(version: 2021_01_07_125458) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" @@ -1333,6 +1333,13 @@ ActiveRecord::Schema.define(version: 2021_01_06_132909) do t.index ["user_id"], name: "index_sdg_managers_on_user_id", unique: true end + create_table "sdg_phases", force: :cascade do |t| + t.integer "kind", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["kind"], name: "index_sdg_phases_on_kind", unique: true + end + create_table "sdg_relations", force: :cascade do |t| t.string "related_sdg_type" t.bigint "related_sdg_id" diff --git a/db/sdg.rb b/db/sdg.rb index f81741e77..a7cef491c 100644 --- a/db/sdg.rb +++ b/db/sdg.rb @@ -23,3 +23,5 @@ end ].each do |code| SDG::Target.where(code: code, goal: SDG::Goal.find_by!(code: code.split(".").first)).first_or_create! end + +SDG::Phase.kinds.values.each { |kind| SDG::Phase.where(kind: kind).first_or_create! } diff --git a/spec/factories/sdg.rb b/spec/factories/sdg.rb index 9495a4114..a9dc94e4e 100644 --- a/spec/factories/sdg.rb +++ b/spec/factories/sdg.rb @@ -14,4 +14,8 @@ FactoryBot.define do target { SDG::Target[code.rpartition(".").first] } end + + factory :sdg_phase, class: "SDG::Phase" do + kind { :sensitization } + end end diff --git a/spec/lib/tasks/db_spec.rb b/spec/lib/tasks/db_spec.rb index b556b41b4..31448853c 100644 --- a/spec/lib/tasks/db_spec.rb +++ b/spec/lib/tasks/db_spec.rb @@ -9,27 +9,33 @@ describe "rake db:load_sdg" do it "populates empty databases and assigns targets correctly" do SDG::Goal.destroy_all + SDG::Phase.destroy_all run_rake_task expect(SDG::Goal.count).to eq 17 expect(SDG::Target.count).to eq 169 expect(SDG::Target["17.1"].goal.code).to eq 17 + expect(SDG::Phase.count).to eq 3 end it "does not create additional records on populated databases" do expect(SDG::Goal.count).to eq 17 expect(SDG::Target.count).to eq 169 + expect(SDG::Phase.count).to eq 3 goal_id = SDG::Goal.last.id target_id = SDG::Target.last.id + phase_id = SDG::Phase.last.id run_rake_task expect(SDG::Goal.count).to eq 17 expect(SDG::Target.count).to eq 169 + expect(SDG::Phase.count).to eq 3 expect(SDG::Goal.last.id).to eq goal_id expect(SDG::Target.last.id).to eq target_id + expect(SDG::Phase.last.id).to eq phase_id end end diff --git a/spec/models/abilities/everyone_spec.rb b/spec/models/abilities/everyone_spec.rb index 81b82dcd5..7aaa1e1c5 100644 --- a/spec/models/abilities/everyone_spec.rb +++ b/spec/models/abilities/everyone_spec.rb @@ -55,6 +55,7 @@ describe Abilities::Everyone do it { should be_able_to(:read, SDG::Goal) } it { should_not be_able_to(:read, SDG::Target) } + it { should be_able_to(:read, SDG::Phase) } it { should_not be_able_to(:read, SDG::Manager) } it { should_not be_able_to(:create, SDG::Manager) } diff --git a/spec/models/sdg/phase_spec.rb b/spec/models/sdg/phase_spec.rb new file mode 100644 index 000000000..160d09c25 --- /dev/null +++ b/spec/models/sdg/phase_spec.rb @@ -0,0 +1,44 @@ +require "rails_helper" + +describe SDG::Phase do + let(:phase) { build(:sdg_phase) } + before { SDG::Phase["sensitization"].destroy } + + it "is valid with a valid kind" do + phase.kind = "sensitization" + + expect(phase).to be_valid + end + + it "is not valid without a kind" do + phase.kind = nil + + expect(phase).not_to be_valid + end + + it "is not valid with a duplicate kind" do + phase.kind = "planning" + + expect(phase).not_to be_valid + end + + it "is not valid with a custom kind" do + expect { phase.kind = "improvement" }.to raise_exception(ArgumentError) + end + + describe ".[]" do + it "finds existing phases by kind" do + expect(SDG::Phase["monitoring"].kind).to eq "monitoring" + end + + it "raises an exception on empty databases" do + SDG::Phase["monitoring"].destroy! + + expect { SDG::Phase["monitoring"] }.to raise_exception ActiveRecord::RecordNotFound + end + + it "raises an exception for non-existing kinds" do + expect { SDG::Phase["improvement"] }.to raise_exception ActiveRecord::StatementInvalid + end + end +end