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
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.