How to access referenced table in a n:m relation in Ruby on Rails?

I have got a Database like this:

    users
    -id

    user_cars
    -user_id
    -car_id

    cars
    -id
    -model
    -color

So a user can have multiple cars, and detailed information about the cars are in a big cars table. I also created the models with the relationships.

class User 
has_many :user_cars

class User_car
belongs_to :user
belongs_to :cars

class Car
has_many :user_cars

Now I want to access the information for all the cars for one user. My first approach would be to get at least one information (i.e. color) from the cars table.

I tried this one, just as an example for accessing the middle table:

@user_id = current_user.user_cars.find(1).user_id

works! But when I try to access the cars table I always get an error.

@color = current_user.user_cars.cars.find(1).color

undefined method `cars' for #<ActiveRecord::Relation:0xaf92e8c>

So I think Im doin something easy very wrong...

When I know how to get access to the third table, I have to do it in that fashion, that I only get results for the user and not just only the first entry, maybe you guys can help me with that aswell. Thanks!

Upvotes: 0

Views: 976

Answers (2)

Gazler
Gazler

Reputation: 84140

The issue in your example by the way is that belongs_to should be singular. Also, your order was wrong.

@color = current_user.user_cars.find_by_car_id(1).car.color

You should rewrite this to use a has_many through association:

class User 
has_many :user_cars
has_many :cars, :through => :user_cars

class UserCar
belongs_to :user
belongs_to :car

You can then access the cars by doing:

current_user.cars

And the color by doing:

@color = current_user.cars.find_by_car_id(1).color

EDIT

After some debugging, it turns out that the Car model has a class property. Class is a reserved word in ruby. Be careful with naming your attributes!

Upvotes: 1

Dalibor Filus
Dalibor Filus

Reputation: 1254

Without has_many :through associations:

@color = current_user.user_cars.where(:car_id => 1).first.color

With them:

class User < ActiveRecord::Base
  has_many :user_cars, :foreign_key => :user_id, :class_name => "UserCar", :inverse_of => :user
  has_many :cars, :through => :user_cars
end

class UserCar < ActiveRecord::Base
  belongs_to :user
  belongs_to :car
end

class Car < ActiveRecord::Base
  has_many :user_cars, :foreign_key => :car_id, :class_name => "UserCar", :inverse_of => :car
  has_many :cars, :through => :user_cars
end

@color = current_user.cars.find(1).color

http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

  • :through defines a shortcut
  • :inverse_of defines a method (association) which represents current model in :class_name model
  • :class_name defines which model should be represented by :user_cars
  • :foreign_key tells which column in the target model's table represents current model (in table user_cars (or users_cars, depends on how you define the association, i think it should be user_cars in this example.. and users_cars for has_and_belongs_to_many)

Details on those are in the link above.

Upvotes: 1

Related Questions