Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails belongs_to_many

I'm a beginner in Rails and I have a problem with ActiveRecords associations.
I'm creating simple car rental service and I made the following associations:

class Client < ActiveRecord::Base
  has_many :rentals
  has_many :bookings
  has_many :cars, :through => :rentals
  has_many :cars, :through => :bookings
end

class Rental < ActiveRecord::Base
  belongs_to :client, dependent: :destroy
  has_one :car
end

class Booking < ActiveRecord::Base
  belongs_to :client, dependent: :destroy
  has_one :car
end

What I need is to have a car belonging to many bookings and rentals while every booking and rental can have only one car assigned.

class Car < ActiveRecord::Base
    # belongs_to_many :bookings
    # belongs_to_many :rentals
end

How should I do that?

like image 210
Kamil Lelonek Avatar asked Nov 24 '13 23:11

Kamil Lelonek


People also ask

What is the difference between Has_one and Belongs_to?

They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user . To determine who "has" the other object, look at where the foreign key is.

How do you implement has and belongs to many in Rails?

Consider we have two models Post and Tag and the post has many tags and the tag has many posts. In this case, we can use has_many association and has_and_belongs_to_many association. In this article we'll see has_and_belongs_to_many association.

What is polymorphic association in Rails?

Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.

What is single table inheritance in Rails?

Single-table inheritance (STI) is the practice of storing multiple types of values in the same table, where each record includes a field indicating its type, and the table includes a column for every field of all the types it stores.


2 Answers

If a car can have many bookings/rentals, but a booking/rental can only have one car, you're looking at a classic belongs_to/has_many situation. It looks like you're being tripped up by the distinction between belongs_to and has_one -- it's not a grammatical one, but a matter of where the foreign key column is located in your database.

  • belongs_to: "I am related to exactly one of these, and I have the foreign key."
  • has_one: "I am related to exactly one of these, and it has the foreign key."
  • has_many: "I am related to many of these, and they have the foreign key."

Note that has_one and has_many both imply there's a belongs_to on the other model, since that's the only option where "this" model has the foreign key. Note also that this means has_one should only be used when you have a one-to-one relationship, not a one-to-many.

Taking this into consideration, I would replace the has_one :car with belongs_to :car in both your Rental and Booking models, and place has_many :bookings and has_many :rentals in your Car model. Also ensure that your rentals and bookings tables have a car_id column; there should be no rental- or booking-related columns in your cars table.

like image 114
DigitalCora Avatar answered Sep 28 '22 16:09

DigitalCora


Yes, there is a "belongs_to_many" in Rails, sort of. It's a little more work and you can't use generators with it. It's called a polymorphic association.

Even though you could make a car have many bookings & rentals, you could associate the car by making it belong to a polymorph such as rentable_vehicle. Your code would look like this

class Car < ActiveRecord::Base
  belongs_to :rentable_vehicle, polymorphic: true
end

class Rental < ActiveRecord::Base
  belongs_to :client, dependent: :destroy
  has_many :cars, as: :rentable_vehicle
end

class Booking < ActiveRecord::Base
  belongs_to :client, dependent: :destroy
  has_many :cars, as: :rentable_vehicle
end
like image 30
Andrew Avatar answered Sep 28 '22 15:09

Andrew