Wasabi Developer
Wasabi Developer

Reputation: 3553

Setting up State and Cities Rails Models, ActiveRecord Associations and Form

I wanted to know the best way to implement the following:

I have setup a State and City model.

The State model:

# == Schema Information
#
# Table name: states
#
#  id         :integer          not null, primary key
#  name       :string           default(""), not null
#  short      :string           default(""), not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class State < ApplicationRecord
  has_many :cities
end

The City model:

# == Schema Information
#
# Table name: cities
#
#  id         :integer          not null, primary key
#  name       :string
#  state_id   :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
# Indexes
#
#  index_cities_on_state_id  (state_id)
#

class City < ApplicationRecord
  belongs_to :state
end

With the Post model

# == Schema Information
#
# Table name: posts
#
#  id              :integer          not null, primary key
#  title           :string           default(""), not null
#  body            :string           default(""), not null

class Post < ApplicationRecord
end

With the Post model I thought I would to a belongs_to and has_many association with references/foreign key setup like:

class Post < ApplicationRecord
  belongs_to :city
  belongs_to :state
end

class City < ApplicationRecord
  belongs_to :state
  has_many :posts
end

class State < ApplicationRecord
  has_many :cities
  has_many :posts
end

The view would use a form_for with a grouped_collection for cities and collection for the states but I don't think this is a good implementation because:

  1. Selecting the city already as the association with the state. It seems redundant having the user select both model options?
  2. The dropdown box in view will load 60000 city records and it will slow down the browser.

I wanted to know if a Polymorphic association would fit my use case and if someone can forward me in the right direction.


My thoughts: I was thinking something where the user selects the the State in a dropdown box eg. California, but enters the city in a text field and if the city does not exists in Cities table it create it, otherwise it will link to it?

Thanks for your help.

Upvotes: 0

Views: 1149

Answers (1)

max
max

Reputation: 102250

What you want is a has_one through: association. This indirect relation tells rails to join through another association and removes the need for a duplicated foreign key.

class Post < ApplicationRecord
  belongs_to :city
  has_one :state, through: :city
end

To create a full hierarchy you would do it like so:

class Post < ApplicationRecord
  belongs_to :city
  has_one :state, through: :city
  has_one :country, through: :state
end

class City < ApplicationRecord
  belongs_to :state
  has_one :country, through: :state
  has_many :posts
end

class State
  belongs_to :country
  has_many :cities
  has_many :posts, through: :cities
end

class Country < ApplicationRecord
  has_many :states
  has_many :cities, through: :states
  has_many :posts, through: :cities
end

Polymorphic associations are a very different thing altogether - its used when an association can be to different models. In this example a Comment can be belong to a Post or a Page.

class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end

class Post < ApplicationRecord
  # this tells AR to look at the `commentable` association on 
  # Comment. 
  has_many :comments, as: :commentable 
end

class Page < ApplicationRecord 
  has_many :comments, as: :commentable
end

Upvotes: 4

Related Questions