Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to select fields from joined table properly?

here is my simplified models, i have joined models,

model apartment

   has_many :towers

and

model tower

   belong_to :apartment

and then i tried to join both tables in controller also tried it in rails console like this :

Apartment.joins(:towers).select('apartments.id', 'apartments.name', 'towers.id' , 'towers.name')

the problem is above query only returns

apartments.id and apartments.name

also tried to use alias like this, still no luck

Apartment.joins(:towers).select('apartments.id', 'apartments.name', 'towers.id as towerid' , 'towers.name as towername')

i have confirmed that all towers have an apartment, i know i could do this to get 1 record

Apartment.joins(:towers).select('apartments.id', 'apartments.name', 'towers.id' , 'towers.name').first.towers.id

and etc, but i need all records and all those fields, please advice.

here is the latest result i got in rails console :

 Apt Load (1.0ms)  SELECT apts.id, apts.apt_name, towers.id as towerid, towers.
    tower_name as towername FROM `apts` INNER JOIN `towers` ON `towers`.`apt_id` = `
    apts`.`id`
    => #<ActiveRecord::Relation [#<Apt id: 5, apt_name: "basura">, #<Apt id: 5, apt_
    name: "basura">, #<Apt id: 124, apt_name: "hydra">, #<Apt id: 124, apt_name: "hy
    dra">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 142, apt_name: "apartement gajah mada">, #<Apt id: 142, apt_name: "apartement gajah mada">]>

as you can see, above query only return 2 fields, i need the result to be like this :

#<Apt id: 126, apt_name: "mediterania", tower_id: 12, tower_name: "tower A">, 
#<Apt id: 126, apt_name: "mediterania", tower_id: 15, tower_name: "tower F">

etcc...

like image 711
NomNomNom Avatar asked Oct 14 '16 06:10

NomNomNom


2 Answers

The only way I see this is possible is using as

q = Apartment.joins(:towers).select('apartments.id, apartments.name, towers.id as t_id, towers.name as t_name')

q.first.t_id
q.first.t_name

Why first.towers.id will not work?

apartment.towers will return ActiveRecord::Associations::CollectionProxy. You can think of it as a collection of towers. In SQL query you are referring to towers table. But when you run apartment.towers.id you are calling id on CollectionProxy object which will not work. You can get first tower using towers.first.

Regarding,

Apt Load (1.0ms)  SELECT apts.id, apts.apt_name, towers.id as towerid, towers.
    tower_name as towername FROM `apts` INNER JOIN `towers` ON `towers`.`apt_id` = `
    apts`.`id`
    => #<ActiveRecord::Relation [#<Apt id: 5, apt_name: "basura">, #<Apt id: 5, apt_
    name: "basura">, #<Apt id: 124, apt_name: "hydra">, #<Apt id: 124, apt_name: "hy
    dra">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 142, apt_name: "apartement gajah mada">, #<Apt id: 142, apt_name: "apartement gajah mada">]>

What you see in console is result returned by inspsect method. The inspect method is not designed to show non column attributes. Hence even if you have towername in memory it will only show attributes which are columns of Apartment model. More about inspect

I also recommend to try following:

Apartment.joins(:towers).pluck('apartments.id, apartments.name, towers.id as t_id, towers.name as t_name')

Above statement will get all data in array. The same result you get with select but select will not load all data in array.

like image 100
dnsh Avatar answered Sep 23 '22 09:09

dnsh


You should use

Apartment.joins(:towers).select('apartments.id, apartments.name, towers.id , towers.name')

that is all column names inside a single string.

Refer this.

like image 24
Sajan Avatar answered Sep 25 '22 09:09

Sajan