Cory L
Cory L

Reputation: 273

Issue with Creating Model Relationships in Rails

I have 3 main models in my program; User, Country, City.

When I run rails db:migrate I get no errors and all appears well, however when I try and seed data or go into the console to create a City it will not save. Any Users or Countries will be successfully created and I am able to build relationships between them.

See my models below.

user.rb

class User < ApplicationRecord

    before_save { self.email = email.downcase }
    #attr_accessible :user_name, :email
    validates_confirmation_of :password
    has_secure_password

    validates :user_name, presence: true, length: { maximum: 25 }
    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
    validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }
    validates :password, presence: true, confirmation: true, length: { minimum: 6 }
    validates :password_confirmation, presence: true

    has_many :trips
    has_many :visits
    has_many :countries, through: :trips
    has_many :cities, through: :visits


end

city.rb

class City < ApplicationRecord

    has_many :visits
    has_many :users, through: :visits
    belongs_to :country

end

country.rb

class Country < ApplicationRecord

  has_many :trips
  has_many :cities
  has_many :users, through: :trips

end

trip.rb

class Trip < ApplicationRecord

    belongs_to :country
    belongs_to :user

end

visit.rb

class Visit < ApplicationRecord

    belongs_to :city
    belongs_to :user

end

Originally I did not even have the Visit model, I just joined both many-to-many relationships through the Trip model. However, in trying to solve the issue I separated it.

Any help with this issue would be appreciated. If you need more information just let me know.

Upvotes: 0

Views: 111

Answers (2)

max
max

Reputation: 102222

I would start by modeling it properly:

class City < ApplicationRecord
  has_many :visits
  has_many :users, through: :visits
  belongs_to :country
end

class Country < ApplicationRecord
  has_many :trips
  has_many :cities
  has_many :users, through: :trips 
end

class Trip < ApplicationRecord
  belongs_to :country
  belongs_to :user
  has_many :visits
  has_many :cities, through: :visits
end

class Visit < ApplicationRecord
  belongs_to :trip
  belongs_to :city
  has_one :country, through: :city
  has_one :user, through: :trip
end

# added
class User < ApplicationRecord
  # ...
  has_many :trips
  has_many :visits, through: :trips
  has_many :countries, through: :trips
  has_many :cities, through: :visits
end

This creates a one to many association between Trip and Visit and avoids duplicating the user_id foreign key on both.

In Rails 5 one of the major changes is that belongs_to associations are non-optional by default.

So if you attempt to create a city without a country the validations will fail. But if you create the city from an existing record:

Country.first.cities.create!(name: 'Toronto')

Or pass a record:

City.create!(name: 'Toronto', country: Country.first)

The validation will pass.

You can also set the association as optional which is the behaviour in Rails 4:

class City < ApplicationRecord
  has_many :visits
  has_many :users, through: :visits
  belongs_to :country, optional: true
end

Upvotes: 1

widjajayd
widjajayd

Reputation: 6253

as city has_many users through visits, then you have to declare has_many :visits inside city model below is sample code probably can help you problem

class City < ApplicationRecord
    has_many :visits
    has_many :users, through: :visits
    belongs_to :country
end

when you create city in your console, make sure you gave country_id as in belongs_to country, here is a sample code:

@city = City.new
@city.country = Country.first
# @city.name = .... # your seed code 
@city.save

Upvotes: 0

Related Questions