Reputation: 20144
It must be something pretty simple i'm doing wrong. i'm trying to join 3 tables together, where group
contains a location_id
which references a row in location
and a info_id
which does the same for info
.
Here's my code:
@groups = Group.joins(
'INNER JOIN location on location.id = "group".id',
'INNER JOIN info on info.id = "group".id'
)
This seems to work without errors, but all i'm getting back is the column from my group
table. What am I doing wrong here?
P.S. my associations are location
and info
belong_to group
. and group has_one
of location
and info
Upvotes: 4
Views: 6324
Reputation: 1326
Just add a select tag to select the desired columns.
Group.joins(:location, :info).select("location.*, info.*")
You may also add a where clause if needed.
Group.joins(:location, :info).select("location.*, info.*").where("locations.id = conditions.id")
Upvotes: 4
Reputation: 11
If you used this:
Group.joins(:location, :info).select("location.*, info.*").where("locations.id =
conditions.id")
and nothing changed
It is because the column names of the two tables are the same.
Upvotes: 0
Reputation: 3310
In Rails / AR we have includes
and joins
.
You are using joins
. As the SQL shows, it only selects Group
. You use joins
when you need Group
results but also want to query through Location
and Info
.
If you would use all information, which I suspect is your case, like to display details in a table, you should also use includes
.
# @groups = Groups.includes(:locations, :info) results an left outer join
@groups = Groups.joins(:locations, :info).includes(:locations, :info) # results inner join
Now when you do some thing like this it will not make additional db calls. But if you use joins
it use multiple queries (N+1).
- @groups.each do |group|
tr
td = group.id
td = group.location.lat
td = group.info.description
Use the bullet gem to find if you have such N+1 queries to optimize your project.
If you Google Rails includes vs joins
you will find more information on the topic.
Upvotes: 1
Reputation: 13014
When you say that you have location_id
and info_id
in groups
table, this means that you intend to have belongs_to
association in Group
.
Pre-requisite:
Group
model should have:
belongs_to :location
belongs_to :info
Location
and Info
should have :
has_one :group
For your question, this is expected. In ActiveRecord, Relation will return the object of the invoker, in this case Group
.
For your use case, I think you will need this approach to get the right join working:
Query:
@groups = Group.joins(:location, :info)
# "SELECT `groups`.* FROM `groups` INNER JOIN `locations` ON `locations`.`id` = `groups`.`location_id` INNER JOIN `infos` ON `infos`.`id` = `groups`.`info_id`"
After this, you can iterate on each group to get info and location as something like: @groups.map { |group| [group.location, group.info] }
This will give correct location and info.
Optimization: [group.location, group.info]
will make queries again to get location and info. You can optimize this by changing the original query to include location and info data:
@groups = Group.joins(:location, :info).includes(:location, :info)
Upvotes: 2