Reputation: 273
I have 3 main models in my program; User, Country, City.
User and Country have a many-to-many relationship, which I join with a Trip model.
User and City have a many-to-many relationship, which I join with a Visit model.
Country and City have a one-to-many relationship.
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
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
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