Search code examples
ruby-on-railsactiverecordforeign-keysdatabase-migrationrelation

Ruby on Rails ActiveRecord - making relationships errors


I am new to rails and have followed a number of guides on various online courses and using other Stack Overflow questions to generate some models (Continent, Country, State) with references and attempt to start making some instances and testing them.

rails g model Continent name:string
rails g model Country name:string continent:reference
rails g model State name:string country:reference

I do not remember which order I made them in. But I had to manually add the following in the model folders.

class Continent < ApplicationRecord
    has_many :countries
    has_many :states, through: :countries
    has_many :regions, through: :states
end


class Country < ApplicationRecord
    belongs_to :continents, optional: true
    has_many :states
    has_many :regions, through: :states
end


class State < ApplicationRecord
  belongs_to :country, , optional: true
  has_one :continent, through: :country
  has_many :regions
end

class Region < ApplicationRecord
  belongs_to :state, optional: true
  has_one :country, through: :state
  has_one :continent, through: :country

Finally, I start adding some tests to use in the seeds and console. Adding the continent works as it is simple, however, running Country.create(name:"Australia", continent: Continent.find_by(name: "Oceania")) does not build the relationship between Continent and Country (Continent_id is nil in the Country).

However, I can run just the Continent.find_by(name: "Oceania") and get:

=> Continent id: 10, name: "Oceania", created_at: "2018-09-19 09:18:07", updated_at: "2018-09-19 09:18:07"

I have a feeling I am on the right track but have mixed up a few things between patching together multiple solutions/methods. I may be using the generators wrong or similar, potentially mixing up some manual methods with somethings I should let the generators handle. If anyone can help fill in the gaps that would be appreciated. Here is the schema.rb

ActiveRecord::Schema.define(version: 2018_09_13_044538) do

  create_table "continents", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "countries", force: :cascade do |t|
    t.string "name"
    t.integer "continent_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["continent_id"], name: "index_countries_on_continent_id"
  end

  create_table "states", force: :cascade do |t|
    t.string "name"
    t.integer "country_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["country_id"], name: "index_states_on_country_id"
  end

Solution

  • In your Country model, you have:

    belongs_to :continents
    

    Since belongs_to denotes a singular relationship (i.e., a country can only belong to one continent), you need to change this to

    belongs_to :continent
    

    Then Rails should start to assign the continent correctly.