diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 028cf9e..c1c28db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: CI on: pull_request: push: - branches: [ main ] + branches: [main] jobs: scan_ruby: @@ -74,4 +74,4 @@ jobs: RAILS_ENV: test DATABASE_URL: postgres://postgres:postgres@localhost:5432 # REDIS_URL: redis://localhost:6379/0 - run: bin/rails db:test:prepare test + run: bin/rails db:test:prepare db:seed test diff --git a/.gitignore b/.gitignore index 063233c..bf8aba6 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ # Ignore master key for decrypting credentials and more. /config/master.key + +/config/credentials/staging.key diff --git a/app/controllers/ministers_controller.rb b/app/controllers/ministers_controller.rb new file mode 100644 index 0000000..f110349 --- /dev/null +++ b/app/controllers/ministers_controller.rb @@ -0,0 +1,21 @@ +class MinistersController < ApplicationController + before_action :set_minister, only: %i[ show ] + + # GET /ministers + def index + @ministers = Minister.all + + render json: @ministers + end + + # GET /ministers/1 + def show + render json: @minister + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_minister + @minister = Minister.find(params.expect(:id)) + end +end diff --git a/app/models/department.rb b/app/models/department.rb index dae4247..8f813d9 100644 --- a/app/models/department.rb +++ b/app/models/department.rb @@ -1,3 +1,4 @@ class Department < ApplicationRecord belongs_to :government + has_many :ministers end diff --git a/app/models/minister.rb b/app/models/minister.rb new file mode 100644 index 0000000..5f53004 --- /dev/null +++ b/app/models/minister.rb @@ -0,0 +1,4 @@ +class Minister < ApplicationRecord + belongs_to :government + belongs_to :department +end diff --git a/config/credentials/staging.yml.enc b/config/credentials/staging.yml.enc new file mode 100644 index 0000000..98e7bf8 --- /dev/null +++ b/config/credentials/staging.yml.enc @@ -0,0 +1 @@ +zzhZt2HaptbYfhrmuak0tSs4PWE+qnyBzAZUgYtjeiMPNuI/oxlwNTIhchCBhW5usn2HfwuUrnGAkh2WZWeskT73FlV6uYLmAz1TzvqFT04s9N+or4ey8hOftwzAEszqvwn5fJoLfEqzKR33M4MZ8Esl+QujOvofbNzAYxmH6zc6WLaiQ+kxgqgm8Y3TgndAthn5VnayZV5eehpBVjNOe3BDacRQIbQ9z+fHjeJLlmX6wskVL9y6eJBp0GOAtafBEYqB4x8FZONHyDhxAQ8zbKe7toNHkBbo0ycrMgq8Notkds0zRKgNveiWcXLxcTR8qtp6bdc7rCK9LQkTSpay6ZRLcfshNwqTETIfrsKKlo5Fq1mWxDmRw0NGvIiSXPphBle7EncAVE7/5LnqryS1rW5JFC7W1ZEenFLWGSdeu24EHwulCcgYXgTl80k3A1azh0ISx5usT7GSsVTsFK2VCElkx1xGh41HSEiEg946+BqhVouYY4QxDABJ--y0ACm/PCUMgn5cOI--2FGz5wcBz06WmfgGoCHHqQ== \ No newline at end of file diff --git a/config/environments/production.rb b/config/environments/production.rb index 3086ffe..9959bc7 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -54,7 +54,7 @@ # config.action_mailer.raise_delivery_errors = false # Set host to be used by links generated in mailer templates. - config.action_mailer.default_url_options = { host: "example.com" } + config.action_mailer.default_url_options = { host: ENV["HOST"] } # Specify outgoing SMTP server. Remember to add smtp/* credentials via rails credentials:edit. # config.action_mailer.smtp_settings = { diff --git a/config/environments/staging.rb b/config/environments/staging.rb new file mode 100644 index 0000000..9959bc7 --- /dev/null +++ b/config/environments/staging.rb @@ -0,0 +1,86 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.enable_reloading = false + + # Eager load code on boot for better performance and memory savings (ignored by Rake tasks). + config.eager_load = true + + # Full error reports are disabled. + config.consider_all_requests_local = false + + # Cache assets for far-future expiry since they are all digest stamped. + config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" } + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.asset_host = "http://assets.example.com" + + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local + + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + config.assume_ssl = true + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + config.force_ssl = true + + # Skip http-to-https redirect for the default health check endpoint. + # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } + + # Log to STDOUT with the current request id as a default log tag. + config.log_tags = [ :request_id ] + config.logger = ActiveSupport::TaggedLogging.logger(STDOUT) + + # Change to "debug" to log everything (including potentially personally-identifiable information!) + config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") + + # Prevent health checks from clogging up the logs. + config.silence_healthcheck_path = "/up" + + # Don't log any deprecations. + config.active_support.report_deprecations = false + + # Replace the default in-process memory cache store with a durable alternative. + # config.cache_store = :mem_cache_store + + # Replace the default in-process and non-durable queuing backend for Active Job. + # config.active_job.queue_adapter = :resque + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Set host to be used by links generated in mailer templates. + config.action_mailer.default_url_options = { host: ENV["HOST"] } + + # Specify outgoing SMTP server. Remember to add smtp/* credentials via rails credentials:edit. + # config.action_mailer.smtp_settings = { + # user_name: Rails.application.credentials.dig(:smtp, :user_name), + # password: Rails.application.credentials.dig(:smtp, :password), + # address: "smtp.example.com", + # port: 587, + # authentication: :plain + # } + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false + + # Only use :id for inspections in production. + config.active_record.attributes_for_inspect = [ :id ] + + # Enable DNS rebinding protection and other `Host` header attacks. + # config.hosts = [ + # "example.com", # Allow requests from example.com + # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` + # ] + # + # Skip DNS rebinding protection for the default health check endpoint. + # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } +end diff --git a/config/routes.rb b/config/routes.rb index 640a7fa..77b2c51 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + resources :ministers, only: [ :index, :show ] resources :departments, only: [ :index, :show ] # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html diff --git a/db/migrate/20250612225202_create_ministers.rb b/db/migrate/20250612225202_create_ministers.rb new file mode 100644 index 0000000..2308d12 --- /dev/null +++ b/db/migrate/20250612225202_create_ministers.rb @@ -0,0 +1,19 @@ +class CreateMinisters < ActiveRecord::Migration[8.0] + def change + create_table :ministers do |t| + t.references :government, null: false, foreign_key: true + t.references :department, null: false, foreign_key: true + t.integer :order_of_precedence, null: false + t.string :person_short_honorific, null: false + t.timestamp :started_at, null: false + t.timestamp :ended_at, null: true + t.string :first_name, null: false + t.string :last_name, null: false + t.string :title, null: false + t.string :avatar_url, null: true + t.string :role, null: false + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 3284ad8..517e6fe 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[8.0].define(version: 2025_06_12_223902) do +ActiveRecord::Schema[8.0].define(version: 2025_06_12_225202) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" @@ -27,11 +27,31 @@ end create_table "governments", force: :cascade do |t| - t.string "name" - t.string "slug" + t.string "name", null: false + t.string "slug", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "ministers", force: :cascade do |t| + t.bigint "government_id", null: false + t.bigint "department_id", null: false + t.integer "order_of_precedence", null: false + t.string "person_short_honorific", null: false + t.datetime "started_at", precision: nil, null: false + t.datetime "ended_at", precision: nil + t.string "first_name", null: false + t.string "last_name", null: false + t.string "title", null: false + t.string "avatar_url" + t.string "role", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["department_id"], name: "index_ministers_on_department_id" + t.index ["government_id"], name: "index_ministers_on_government_id" end add_foreign_key "departments", "governments" + add_foreign_key "ministers", "departments" + add_foreign_key "ministers", "governments" end diff --git a/db/seeds/canada.rb b/db/seeds/canada.rb index df521d7..d8e374c 100644 --- a/db/seeds/canada.rb +++ b/db/seeds/canada.rb @@ -2,7 +2,6 @@ g.slug = "federal" end -government = Government.find_or_create_by!(name: "Government of Canada") { |g| g.slug = "federal" } departments_data = [ { slug: "agriculture-and-agri-food-canada", priority: 2, display_name: "Agriculture", official_name: "Agriculture and Agri-Food Canada" }, @@ -47,3 +46,459 @@ dept.priority = attrs[:priority] end end + +# Ministers data +ministers_data = [ + { + order_of_precedence: 1, + person_short_honorific: "Right Hon.", + first_name: "Mark", + last_name: "Carney", + title: "Prime Minister", + started_at: "2025-03-14T11:31:00", + ended_at: nil, + department_slug: "prime-minister-office", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/CarneyMark_Lib.jpg", + role: "Prime Minister" + }, + { + order_of_precedence: 2, + person_short_honorific: "Hon.", + first_name: "Shafqat", + last_name: "Ali", + title: "President of the Treasury Board", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "treasury-board-of-canada-secretariat", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/AliShafqat_Lib.jpg", + role: "Minister" + }, + { + order_of_precedence: 3, + person_short_honorific: "Hon.", + first_name: "Rebecca", + last_name: "Alty", + title: "Minister of Crown-Indigenous Relations", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "crown-indigenous-relations-and-northern-affairs-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/AltyRebecca_Lib.jpg" + }, + { + order_of_precedence: 4, + person_short_honorific: "Hon.", + first_name: "Anita", + last_name: "Anand", + title: "Minister of Foreign Affairs", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "global-affairs-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/AnandAnita_Lib.jpg" + }, + { + order_of_precedence: 5, + person_short_honorific: "Hon.", + first_name: "Gary", + last_name: "Anandasangaree", + title: "Minister of Public Safety", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "public-safety-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/AnandasangareeGary_Lib.jpg" + }, + { + order_of_precedence: 6, + person_short_honorific: "Hon.", + first_name: "François-Philippe", + last_name: "Champagne", + title: "Minister of Finance and National Revenue", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "finance-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/ChampagneFrancoisPhilippe_Lib.jpg" + }, + { + order_of_precedence: 6, + person_short_honorific: "Hon.", + first_name: "François-Philippe", + last_name: "Champagne", + title: "Minister of Finance and National Revenue", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "canada-revenue-agency", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/ChampagneFrancoisPhilippe_Lib.jpg" + }, + { + order_of_precedence: 7, + person_short_honorific: "Hon.", + first_name: "Rebecca", + last_name: "Chartrand", + title: "Minister of Northern and Arctic Affairs", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "crown-indigenous-relations-and-northern-affairs-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/ChartrandRebecca_Lib.jpg" + }, + { + order_of_precedence: 8, + person_short_honorific: "Hon.", + first_name: "Julie", + last_name: "Dabrusin", + title: "Minister of Environment and Climate Change", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "environment-and-climate-change-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/DabrusinJulie_Lib.jpg" + }, + { + order_of_precedence: 9, + person_short_honorific: "Hon.", + first_name: "Sean", + last_name: "Fraser", + title: "Minister of Justice", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "justice-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/FraserSean_Lib.jpg" + }, + { + order_of_precedence: 10, + person_short_honorific: "Hon.", + first_name: "Chrystia", + last_name: "Freeland", + title: "Minister of Transport and Internal Trade", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "transport-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/FreelandChrystia_Lib.jpg" + }, + { + order_of_precedence: 11, + person_short_honorific: "Hon.", + first_name: "Steven", + last_name: "Guilbeault", + title: "Minister of Canadian Identity and Culture", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "canadian-heritage", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/GuilbeaultSteven_Lib.jpg" + }, + { + order_of_precedence: 12, + person_short_honorific: "Hon.", + first_name: "Mandy", + last_name: "Gull-Masty", + title: "Minister of Indigenous Services", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "indigenous-services-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/Gull-MastyMandy_Lib.jpg" + }, + { + order_of_precedence: 13, + person_short_honorific: "Hon.", + first_name: "Patty", + last_name: "Hajdu", + title: "Minister of Jobs and Families", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "employment-and-social-development-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/HajduPatty_Lib.jpg" + }, + { + order_of_precedence: 14, + person_short_honorific: "Hon.", + first_name: "Tim", + last_name: "Hodgson", + title: "Minister of Energy and Natural Resources", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "natural-resources-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/HodgsonTimothyEdward_Lib.jpg" + }, + { + order_of_precedence: 16, + person_short_honorific: "Hon.", + first_name: "Dominic", + last_name: "LeBlanc", + title: "President of the King's Privy Council for Canada", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "privy-council-office", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/LeBlancDominic_Lib.jpg" + }, + { + order_of_precedence: 17, + person_short_honorific: "Hon.", + first_name: "Joël", + last_name: "Lightbound", + title: "Minister of Government Transformation, Public Works and Procurement", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "public-services-and-procurement-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/LightboundJo%C3%ABl_Lib.jpg" + }, + { + order_of_precedence: 18, + person_short_honorific: "Hon.", + first_name: "Heath", + last_name: "MacDonald", + title: "Minister of Agriculture and Agri-Food", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "agriculture-and-agri-food-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/MacDonaldHeath_CPC.jpg" + }, + { + order_of_precedence: 19, + person_short_honorific: "Hon.", + first_name: "Steven", + last_name: "MacKinnon", + title: "Leader of the Government in the House of Commons", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "privy-council-office", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/MacKinnonSteven_Lib.jpg" + }, + { + order_of_precedence: 20, + person_short_honorific: "Hon.", + first_name: "David", + last_name: "McGuinty", + title: "Minister of National Defence", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "national-defence", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/McGuintyDavidJ._Lib.jpg" + }, + { + order_of_precedence: 21, + person_short_honorific: "Hon.", + first_name: "Jill", + last_name: "McKnight", + title: "Minister of Veterans Affairs", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "veterans-affairs-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/McKnightJill_Lib.jpg" + }, + { + order_of_precedence: 22, + person_short_honorific: "Hon.", + first_name: "Lena Metlege", + last_name: "Diab", + title: "Minister of Immigration, Refugees and Citizenship", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "immigration-refugees-and-citizenship-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/MetlegeDiabLena_Lib.jpg" + }, + { + order_of_precedence: 23, + person_short_honorific: "Hon.", + first_name: "Marjorie", + last_name: "Michel", + title: "Minister of Health", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "health-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/MichelMarjorie_Lib.jpg" + }, + { + order_of_precedence: 24, + person_short_honorific: "Hon.", + first_name: "Eleanor", + last_name: "Olszewski", + title: "Minister of Emergency Management and Community Resilience", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "emergency-preparedness-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/OlszewskiEleanor_Lib.jpg" + }, + { + order_of_precedence: 25, + person_short_honorific: "Hon.", + first_name: "Gregor", + last_name: "Robertson", + title: "Minister of Housing and Infrastructure", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "infrastructure-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/RobertsonGregor_Lib.jpg" + }, + { + order_of_precedence: 26, + person_short_honorific: "Hon.", + first_name: "Maninder", + last_name: "Sidhu", + title: "Minister of International Trade", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "global-affairs-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/SidhuManinder_Lib.jpg" + }, + { + order_of_precedence: 27, + person_short_honorific: "Hon.", + first_name: "Evan", + last_name: "Solomon", + title: "Minister of Artificial Intelligence and Digital Innovation", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "artificial-intelligence-and-digital-innovation", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/SolomonEvan_Lib.jpg" + }, + { + order_of_precedence: 28, + person_short_honorific: "Hon.", + first_name: "Joanne", + last_name: "Thompson", + title: "Minister of Fisheries", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "fisheries-and-oceans-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/ThompsonJoanne_Lib.jpg" + }, + { + order_of_precedence: 29, + person_short_honorific: "Hon.", + first_name: "Rechie", + last_name: "Valdez", + title: "Minister of Women and Gender Equality", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "women-and-gender-equality-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/ValdezRechie_Lib.jpg" + }, + { + order_of_precedence: 30, + person_short_honorific: "Hon.", + first_name: "Buckley", + last_name: "Belanger", + title: "Secretary of State (Rural Development)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "rural-economic-development", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/BelangerBuckley_Lib.jpg" + }, + { + order_of_precedence: 31, + person_short_honorific: "Hon.", + first_name: "Stephen", + last_name: "Fuhr", + title: "Secretary of State (Defence Procurement)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "national-defence", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/FuhrStephen_Lib.jpg" + }, + { + order_of_precedence: 32, + person_short_honorific: "Hon.", + first_name: "Anna", + last_name: "Gainey", + title: "Secretary of State (Children and Youth)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "employment-and-social-development-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/GaineyAnna_Lib.jpg" + }, + { + order_of_precedence: 33, + person_short_honorific: "Hon.", + first_name: "Wayne", + last_name: "Long", + title: "Secretary of State (Canada Revenue Agency and Financial Institutions)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "canada-revenue-agency", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/LongWayne_Lib.jpg" + }, + { + order_of_precedence: 34, + person_short_honorific: "Hon.", + first_name: "Stephanie", + last_name: "McLean", + title: "Secretary of State (Seniors)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "employment-and-social-development-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/McLeanStephanie_Lib.jpg" + }, + { + order_of_precedence: 35, + person_short_honorific: "Hon.", + first_name: "Nathalie", + last_name: "Provost", + title: "Secretary of State (Nature)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "environment-and-climate-change-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/ProvostNathalie_Lib.jpg" + }, + { + order_of_precedence: 36, + person_short_honorific: "Hon.", + first_name: "Ruby", + last_name: "Sahota", + title: "Secretary of State (Combatting Crime)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "public-safety-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/SahotaRuby_Lib.jpg" + }, + { + order_of_precedence: 37, + person_short_honorific: "Hon.", + first_name: "Randeep", + last_name: "Sarai", + title: "Secretary of State (International Development)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "global-affairs-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/SaraiRandeep_Lib.jpg" + }, + { + order_of_precedence: 38, + person_short_honorific: "Hon.", + first_name: "Adam", + last_name: "van Koeverden", + title: "Secretary of State (Sport)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "canadian-heritage", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/44/vanKoeverdenAdam_Lib.jpg" + }, + { + order_of_precedence: 39, + person_short_honorific: "Hon.", + first_name: "John", + last_name: "Zerucelli", + title: "Secretary of State (Labour)", + started_at: "2025-05-13T10:45:00", + ended_at: nil, + department_slug: "employment-and-social-development-canada", + avatar_url: "https://www.ourcommons.ca/Content/Parliamentarians/Images/OfficialMPPhotos/45/ZerucelliJohn_Lib.jpg" + } +] + +ministers_data.each do |attrs| + department = Department.find_by!(slug: attrs[:department_slug], government: government) + role = attrs[:role] || attrs[:title].include?("Secretary of State") ? "Secretary of State" : "Minister" + + Minister.find_or_create_by!( + department: department, + government: government, + started_at: attrs[:started_at], + role: role + ) do |minister| + minister.person_short_honorific = attrs[:person_short_honorific] + minister.order_of_precedence = attrs[:order_of_precedence] + minister.first_name = attrs[:first_name] + minister.last_name = attrs[:last_name] + minister.title = attrs[:title] + minister.started_at = attrs[:started_at] + minister.ended_at = attrs[:ended_at] + minister.avatar_url = attrs[:avatar_url] + end +end diff --git a/test/controllers/departments_controller_test.rb b/test/controllers/departments_controller_test.rb index 84f3c8e..831a0cb 100644 --- a/test/controllers/departments_controller_test.rb +++ b/test/controllers/departments_controller_test.rb @@ -14,5 +14,4 @@ class DepartmentsControllerTest < ActionDispatch::IntegrationTest get department_url(@department), as: :json assert_response :success end - end diff --git a/test/controllers/ministers_controller_test.rb b/test/controllers/ministers_controller_test.rb new file mode 100644 index 0000000..f68af0e --- /dev/null +++ b/test/controllers/ministers_controller_test.rb @@ -0,0 +1,17 @@ +require "test_helper" + +class MinistersControllerTest < ActionDispatch::IntegrationTest + setup do + @minister = Minister.first + end + + test "should get index" do + get ministers_url, as: :json + assert_response :success + end + + test "should show minister" do + get minister_url(@minister), as: :json + assert_response :success + end +end diff --git a/test/models/minister_test.rb b/test/models/minister_test.rb new file mode 100644 index 0000000..7841f8f --- /dev/null +++ b/test/models/minister_test.rb @@ -0,0 +1,8 @@ +require "test_helper" + +class MinisterTest < ActiveSupport::TestCase + test "that each department has a minister" do + # Ensure that each department has + assert_equal 0, Department.joins(:ministers).where(ministers: { id: nil }).count + end +end